Oplocks anfragen und gewähren
Wenn der Netzwerkumleiter auf Dateien auf Remoteservern zugreift, fordert er das Oplock vom Remoteserver an. Client-Anwendungen fragen Oplocks nur dann direkt an, wenn die Sperre für eine Datei auf dem lokalen Server bestimmt ist.
Oplocks werden über FSCTLs angefordert. Die folgenden FSCTLs werden für die verschiedenen Oplock-Typen verwendet, die sowohl von Benutzermodus-Anwendungen als auch von Kernel-Treibern vergeben werden können.
- Um Windows 7 Oplocks anzufordern:
- So fragen Sie veraltete Oplocks an:
Anfordern eines Oplocks im Benutzermodus
Um einen Windows 7-Oplock im Benutzermodus anzufordern, rufen Sie DeviceIoControl auf:
- Legen Sie dwIoControlCode auf FSCTL_REQUEST_OPLOCK fest.
- Übergeben Sie einen Zeiger auf eine REQUEST_OPLOCK_INPUT_BUFFER Struktur im lpInBuffer Parameter.
- Informationen zum Formatieren der Oplock-Anforderung finden Sie in der Dokumentation zu dieser Struktur.
- Übergeben Sie einen Zeiger auf eine REQUEST_OPLOCK_OUTPUT_BUFFER Struktur im lpOutBuffer Parameter.
Weitere Informationen finden Sie unter FSCTL_REQUEST_OPLOCK.
Wenn der angefragte Oplock gewährt werden kann, gibt DeviceIoControl FALSE zurück und GetLastError gibt ERROR_IO_PENDING zurück. Aus diesem Grund werden Oplocks nie für synchrone E/A gewährt. Die überlappende Operation wird erst abgeschlossen, wenn der Oplock fehlerhaft ist. Nach dem Abschluss der Operation enthält der REQUEST_OPLOCK_OUTPUT_BUFFER Informationen über die Aufhebung des Oplocks.
Wenn der Oplock nicht gewährt werden kann, gibt das Dateisystem einen entsprechenden Fehlercode zurück. Die am häufigsten zurückgegebenen Fehlercodes sind ERROR_OPLOCK_NOT_GRANTED und ERROR_INVALID_PARAMETER.
Anfordern eines Oplocks im Kernelmodus
So fragen Sie Windows 7 Oplocks im Kernel-Modus an:
Dateisystem-Minifilter
Ein Dateisystem-Minifilter muss FltAllocateCallbackData verwenden und das zugewiesene FLT_CALLBACK_DATA wie folgt ausfüllen:
- Legen Sie das Feld Iopb->MajorFunction auf IRP_MJ_FILE_SYSETM_CONTROL fest.
- Legen Sie sein Iopb->MinorFunction-Feld auf IRP_MN_USER_FS_REQUEST fest.
- Legen Sie sein Mitglied Iopb->Parameters.FileSystemControl.Buffered.FsControlCode auf FSCTL_REQUEST_OPLOCK fest.
- Weisen Sie einen Puffer zu, dessen Größe dem größeren von REQUEST_OPLOCK_INPUT_BUFFER oder REQUEST_OPLOCK_OUTPUT_BUFFERentspricht.
- Legen Sie das Mitglied > des zugewiesenen FLT_CALLBACK_DATA so fest, dass es auf diesen Puffer zeigt.
- Legen Sie die zugewiesenen FLT_CALLBACK_DATA-Felder Iopb->Parameters.FileSystemControl.Buffered.InputBufferLength und Iopb->Parameters.FileSystemControl.Buffered.OutputBufferLength auf die Größe dieses Puffers fest.
Lesen Sie in der Dokumentation der Struktur REQUEST_OPLOCK_INPUT_BUFFER nach, wie Sie die oplock-Anfrage formatieren.
Dann muss der Dateisystem-Minifilter FltPerformAsynchronousIoaufrufen und die zugeordnete FLT_CALLBACK_DATA als CallbackData-Parameter übergeben.
Wenn der angeforderte Oplock gewährt werden kann, gibt der Aufruf FltPerformAsynchronousIo den Status STATUS_PENDING zurück. Aus diesem Grund werden Oplocks nie für synchrone E/A gewährt. Der Vorgang wird erst abgeschlossen, wenn das Oplock aufgehoben ist. Nach dem Abschluss der Operation enthält der REQUEST_OPLOCK_OUTPUT_BUFFER Informationen über die Aufhebung des Oplocks.
Wenn der Oplock nicht gewährt werden kann, gibt das Dateisystem einen entsprechenden Fehlercode zurück. Die am häufigsten zurückgegebenen Fehlercodes sind STATUS_OPLOCK_NOT_GRANTED und STATUS_INVALID_PARAMETER.
Andere Arten von Treibern
Andere Arten von Treibern können ZwFsControlFileaufrufen:
- Legen Sie FsControlCode auf FSCTL_REQUEST_OPLOCK fest.
- Übergeben Sie einen Zeiger auf eine REQUEST_OPLOCK_INPUT_BUFFER-Struktur im InputBuffer-Parameter, und legen Sie den InputBufferLength-Parameter auf die Größe dieses Puffers fest.
- Übergeben Sie einen Zeiger auf eine REQUEST_OPLOCK_OUTPUT_BUFFER-Struktur im OutputBuffer-Parameter, und legen Sie den OutputBufferLength-Parameter auf die Größe dieses Puffers fest.
Lesen Sie in der Dokumentation der Struktur REQUEST_OPLOCK_INPUT_BUFFER nach, wie Sie die oplock-Anfrage formatieren.
Wenn der angeforderte Oplock gewährt werden kann, gibt der Aufruf ZwFsControlFile STATUS_PENDING zurück. Aus diesem Grund werden Oplocks nie für synchrone E/A gewährt. Der Vorgang wird erst abgeschlossen, wenn der Oplock fehlerhaft ist. Nach dem Abschluss der Operation enthält der REQUEST_OPLOCK_OUTPUT_BUFFER Informationen über die Aufhebung des Oplocks.
Wenn der Oplock nicht gewährt werden kann, gibt das Dateisystem einen entsprechenden Fehlercode zurück. Die am häufigsten zurückgegebenen Fehlercodes sind STATUS_OPLOCK_NOT_GRANTED und STATUS_INVALID_PARAMETER.
Vermeidung von Sharing-Verstößen bei der Anfrage von Oplocks
Verwenden der Atomic-Create-With-Oplock-Methode
Die atomare create-with-oplock-Prozedur ist kein Oplock-Typ. Vielmehr handelt es sich um eine Prozedur, die offenen Vorgängen die Möglichkeit bietet, Verletzungen des Freigabemodus in der Zeitspanne zwischen dem Öffnen einer Datei und dem Erhalt eines Oplocks zu vermeiden. Bei Legacy-Oplocks sind Filter-Oplocks und das Öffnen von zwei Handles erforderlich. Bei Windows 7-Oplocks kann eine Anwendung oder ein Treiber mit dieser Prozedur eine beliebige Art von Oplock anfordern und muss nur ein Handle öffnen.
Um die atomare create-with-oplock-Prozedur durchzuführen, sollten Sie:
- Gegebenenfalls FltCreateFileEx2 oder ZwCreateFile verwenden, um die Datei zu öffnen. Übergeben Sie im CreateOptions-Parameter das FILE_OPEN_REQUIRING_OPLOCK-Flag. Sie können die parameter DesiredAccess und ShareAccess wie gewünscht festlegen. Legen Sie z. B. im DesiredAccess-Parameter GENERIC_READ fest, damit Sie die Datei lesen können, und im ShareAccess-Parameter die FILE_SHARE_READ | FILE_SHARE_DELETE-Flags, damit andere die Datei lesen, umbenennen und/oder zum Löschen markieren können, während Sie sie geöffnet haben.
- Verwenden Sie den FSCTL_REQUEST_OPLOCK-Steuercode, um ein Oplock für das resultierende Dateiobjekt oder Handle anzufordern, wie in Anfordern eines Oplock im Kernelmodusbeschrieben.
Führen Sie keine Dateisystemvorgänge für die Datei zwischen schritt 1 und 2 aus. Dies kann zu Deadlocks führen.
Der am häufigsten verwendete Oplock, der mithilfe dieser Prozedur angefordert werden kann, ist der Read-Handle-Typ. Dies bietet Ihnen die Möglichkeit, anderen Aufrufern so viel parallelen Zugriff wie möglich zu gewähren, während Sie immer noch benachrichtigt werden, wenn Sie Ihr Handle schließen müssen, um eine Verletzung der gemeinsamen Nutzung durch ein konkurrierendes Öffnen zu vermeiden.
Verwendung des veralteten Filter-Oplocks
Der veraltete Filter Oplock bietet einer Anwendung ebenfalls die Möglichkeit, ein "back out" durchzuführen, wenn andere Anwendungen/Clients versuchen, auf denselben Stream zuzugreifen, ist aber weniger flexibel als die atomare Methode create-with-oplock. Dieser Mechanismus bietet einer Anwendung die Möglichkeit, auf einen Stream zuzugreifen, ohne dass andere Accessors des Streams beim Versuch, den Stream zu öffnen, eine Verletzung der Freigabe erhalten. Um Freigabeverletzungen zu vermeiden, sollten Sie die folgende dreistufige Prozedur anwenden, um einen Filter-Oplock anzufordern:
Öffnen Sie die Datei mit einer erforderlichen Zugriffsfreiheit von FILE_READ_ATTRIBUTES und einem Freigabemodus von FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE. Das in diesem Schritt geöffnete Handle führt nicht dazu, dass andere Anwendungen Freigabeverletzungen erhalten, da es nur für den Attributzugriff (FILE_READ_ATTRIBUTES) und nicht für den Datenzugriff (FILE_READ_DATA) geöffnet ist. Dieses Handle eignet sich für die Anfrage des Filter-Oplocks, aber nicht für die Durchführung der eigentlichen E/A auf dem Datenstrom.
Fordern Sie ein Filter-Oplock (FSCTL_REQUEST_FILTER_OPLOCK) für das Handle aus Schritt 1 an. Der in diesem Schritt gewährte Oplock bietet dem Oplock-Inhaber die Möglichkeit, "aus dem Weg zu gehen", ohne eine Freigabeverletzung für eine andere Anwendung zu verursachen, die versucht, auf den Datenstrom zuzugreifen.
Öffnen Sie die Datei erneut für den Lesezugriff. Das in diesem Schritt geöffnete Handle bietet dem Oplock-Inhaber die Möglichkeit, E/A auf dem Stream durchzuführen.
Das NTFS-Dateisystem bietet mit dem Flag für die Erstellungsoption FILE_RESERVE_OPFILTER eine Optimierung für diesen Vorgang. Wenn dieses Flag in Schritt 1 der vorherigen Prozedur angegeben ist, ermöglicht es dem Dateisystem, die Erstellungsanforderung mit dem Status STATUS_OPLOCK_NOT_GRANTED abzulehnen, falls das Dateisystem feststellen kann, dass Schritt 2 fehlschlägt. Wenn Schritt 1 erfolgreich ist, besteht keine Garantie dafür, dass Schritt 2 erfolgreich ist, auch wenn FILE_RESERVE_OPFILTER für die Erstellungsanforderung angegeben wurde.
Bedingungen für die Gewährung von Oplocks
In der folgenden Tabelle sind die Bedingungen aufgeführt, die für die Gewährung eines Oplocks erforderlich sind.
Anforderungstyp | Bedingungen |
---|---|
Stufe 1 Filter Batch |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Stufe 2 |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Lesen |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Read-Handle |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Lesen/Schreiben |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Read-Write-Handle |
Wird nur gewährt, wenn alle folgenden Bedingungen erfüllt sind:
Wenn der aktuelle Status des Oplocks ist:
|
Hinweis
Read-Oplocks und Level 2-Oplocks können im selben Datenstrom koexistieren. Read-Oplocks und Read-Handle-Oplocks können koexistieren, aber Level 2-Oplocks und Read-Handle-Oplocks können nicht koexistieren.