Delen via


Het aanvragen en verlenen van oplocks

Wanneer de netwerkomleiding bestanden op externe servers opent, wordt de oplock van de externe server aangevraagd. Clienttoepassingen vragen alleen oplocks aan wanneer de vergrendeling is bedoeld voor een bestand op de lokale server.

Oplocks worden aangevraagd via FSCTLs. De volgende FSCTLs worden gebruikt voor de verschillende oplocktypen, die zowel gebruikersmodustoepassingen als kernelmodusstuurprogramma's kunnen uitgeven.

Een oplock aanvragen in de gebruikersmodus

Als u een Windows 7-oplock wilt aanvragen in de gebruikersmodus, roept u DeviceIoControl-aan:

Zie FSCTL_REQUEST_OPLOCKvoor meer informatie.

Als de aangevraagde oplock kan worden verleend, retourneert DeviceIoControl FALSE en retourneert GetLastError ERROR_IO_PENDING. Daarom worden oplocks nooit verleend voor synchrone invoer/uitvoer. De overlappende bewerking wordt pas voltooid als de oplock is verbroken. Nadat de bewerking is voltooid, bevat de REQUEST_OPLOCK_OUTPUT_BUFFER informatie over de oplock-onderbreking.

Als de oplock niet kan worden verleend, retourneert het bestandssysteem een geschikte foutcode. De meest geretourneerde foutcodes zijn ERROR_OPLOCK_NOT_GRANTED en ERROR_INVALID_PARAMETER.

Een oplock aanvragen in kernelmodus

Windows 7-oplocks aanvragen in kernelmodus:

Minifilters voor bestandssysteem

Een minifilter voor het bestandssysteem moet FltAllocateCallbackData- gebruiken en de toegewezen FLT_CALLBACK_DATA als volgt invullen:

  • Stel het Iopb-->MajorFunction veld in op IRP_MJ_FILE_SYSTEM_CONTROL.
  • Stel het veld Iopb->MinorFunction in op IRP_MN_USER_FS_REQUEST.
  • Stel het Iopb->Parameters.FileSystemControl.Buffered.FsControlCode veld op FSCTL_REQUEST_OPLOCK.
  • Wijs een buffer toe waarvan de grootte gelijk is aan de grotere REQUEST_OPLOCK_INPUT_BUFFER of REQUEST_OPLOCK_OUTPUT_BUFFER.
    • Stel het toegewezen lid FLT_CALLBACK_DATA's Iopb->Parameters.FileSystemControl.Buffered.SystemBuffer in om naar die buffer te verwijzen.
    • Stel de velden en > van de toegewezen FLT_CALLBACK_DATAin op de grootte van die buffer.

Raadpleeg de documentatie van de REQUEST_OPLOCK_INPUT_BUFFER structuur voor informatie over hoe de oplock-aanvraag te formatteren.

Vervolgens moet het minifilter van het bestandssysteem FltPerformAsynchronousIoaanroepen, waarbij de toegewezen FLT_CALLBACK_DATA wordt doorgegeven als de parameter CallbackData.

Als de aangevraagde oplock kan worden verleend, retourneert de FltPerformAsynchronousIo aanroep STATUS_PENDING. Daarom worden oplocks nooit verleend voor synchrone invoer/uitvoer. De bewerking wordt pas voltooid als de oplock is verbroken. Nadat de bewerking is voltooid, bevat de REQUEST_OPLOCK_OUTPUT_BUFFER informatie over de oplock-onderbreking.

Als de oplock niet kan worden verleend, retourneert het bestandssysteem een geschikte foutcode. De meest geretourneerde foutcodes zijn STATUS_OPLOCK_NOT_GRANTED en STATUS_INVALID_PARAMETER.

Andere soorten chauffeurs

Andere soorten stuurprogramma's kunnen ZwFsControlFileaanroepen:

  • Stel FsControlCode in op FSCTL_REQUEST_OPLOCK.
  • Verwijs naar een REQUEST_OPLOCK_INPUT_BUFFER structuur in de parameter InputBuffer en stel de parameter InputBufferLength in als de lengte van die buffer.
  • Geef een aanwijzer door naar een REQUEST_OPLOCK_OUTPUT_BUFFER structuur in de parameter OutputBuffer en stel de parameter OutputBufferLength in op de grootte van die buffer.

Raadpleeg de documentatie van de REQUEST_OPLOCK_INPUT_BUFFER structuur voor informatie over hoe de oplock-aanvraag te formatteren.

Als de aangevraagde oplock kan worden verleend, keert de ZwFsControlFile oproep terug met STATUS_PENDING. Daarom worden oplocks nooit verleend voor synchrone invoer/uitvoer. De bewerking wordt pas voltooid als de oplock is verbroken. Nadat de bewerking is voltooid, bevat de REQUEST_OPLOCK_OUTPUT_BUFFER informatie over de oplock-onderbreking.

Als de oplock niet kan worden verleend, retourneert het bestandssysteem een geschikte foutcode. De meest geretourneerde foutcodes zijn STATUS_OPLOCK_NOT_GRANTED en STATUS_INVALID_PARAMETER.

Schendingen van gedeelde toegang voorkomen bij het aanvragen van oplocks

De methode Atomic Create-With-Oplock gebruiken

Atomic create-with-oplock is geen oplocktype. In plaats daarvan is het een procedure die open bewerkingen toestaat om schendingen van de deelmodus in de tijdsduur tussen het openen van een bestand en het ontvangen van een oplock te voorkomen. Bij legacy oplocks zijn Filter oplocks en het openen van twee handles vereist. Met Windows 7-oplocks kan een toepassing of driver elk type oplock aanvragen via deze procedure en slechts één handle openen.

Als u de atomic create-with-oplock-procedure wilt uitvoeren, moet u het volgende doen:

  1. Gebruik FltCreateFileEx2 of ZwCreateFileom het bestand te openen. Geef in de parameter CreateOptions de vlag FILE_OPEN_REQUIRING_OPLOCKdoor. U kunt de DesiredAccess- en ShareAccess parameters naar wens instellen. Bijvoorbeeld, in de parameterset DesiredAccess de GENERIC_READ instellen zodat u het bestand kunt lezen, en in de parameter ShareAccess de FILE_SHARE_READ | FILE_SHARE_DELETE vlaggen instellen zodat anderen het bestand kunnen lezen, hernoemen en/of markeren voor verwijdering terwijl u het geopend hebt.
  2. Gebruik de FSCTL_REQUEST_OPLOCK-besturingscode om een oplock aan te vragen op het resulterende bestandsobject of de resulterende ingang, zoals beschreven in Een oplock aanvragen in kernelmodus.

Voer tussen stap 1 en 2 geen bestandssysteembewerkingen uit op het bestand. Dit kan impasses veroorzaken.

Het meest voorkomende oplock dat wordt aangevraagd met behulp van deze procedure is het Read-Handle-type. Hiermee kunt u andere oproepers zoveel mogelijk gelijktijdige toegang toestaan, terwijl u nog steeds op de hoogte kunt worden gesteld als u uw handvat moet sluiten om te voorkomen dat u een conflicterend gebruik veroorzaakt.

Verouderde filteroplock gebruiken

Met de verouderde filtervergrendeling kan een toepassing zich ook terugtrekken wanneer andere toepassingen/clients proberen toegang te krijgen tot dezelfde gegevensstroom, maar is minder flexibel dan het atomisch creëren met een oplock. Met dit mechanisme kan een toepassing toegang krijgen tot een stream zonder dat andere gebruikers van de stream gedeeltesvoorschriftenovertredingen krijgen bij het proberen te openen van de stream. Om gedeeld gebruik schendingen te voorkomen, moet de volgende driestappenprocedure worden gebruikt om een filtervergrendeling aan te vragen.

  1. Open het bestand met een vereiste toegang tot FILE_READ_ATTRIBUTES en een sharemodus van FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE. De handle die in deze stap wordt geopend, zorgt er niet voor dat andere toepassingen schendingen van delen ervaren, omdat deze alleen is geopend voor kenmerktoegang (FILE_READ_ATTRIBUTES) en niet voor gegevenstoegang (FILE_READ_DATA). Deze ingang is geschikt voor het aanvragen van de filtervergrendeling, maar niet voor het uitvoeren van werkelijke I/O op de gegevensstroom.

  2. Vraag een filtervergrendeling (FSCTL_REQUEST_FILTER_OPLOCK) aan op het handvat uit stap 1. De oplock die in deze stap is verleend, stelt de oplockhouder in staat om 'uit de weg te komen' zonder een schending van het delen te veroorzaken voor een andere toepassing die toegang probeert te krijgen tot de stream.

  3. Open het bestand opnieuw voor leestoegang. Met de in deze stap geopende handgreep kan de oplockhouder I/O uitvoeren op de stream.

Het NTFS-bestandssysteem biedt een optimalisatie voor deze procedure via de FILE_RESERVE_OPFILTER optievlag bij het aanmaken. Als deze vlag is opgegeven in stap 1 van de vorige procedure, kan het bestandssysteem het aanmaakverzoek afwijzen met STATUS_OPLOCK_NOT_GRANTED als het bestandssysteem kan bepalen dat stap 2 mislukt. Als stap 1 slaagt, is er geen garantie dat stap 2 slaagt, zelfs als FILE_RESERVE_OPFILTER is opgegeven voor de maakaanvraag.

Voorwaarden voor het verlenen van Oplocks

In de volgende tabel verwijzen we naar de vereiste voorwaarden die nodig zijn om een oplock te verlenen.

Aanvraagtype Voorwaarden

Niveau 1

Filter

Batch

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
    • Als het een map is, wordt STATUS_INVALID_PARAMETER geretourneerd.
  • De stream wordt geopend voor ASYNCHRONE toegang.
    • Als deze wordt geopend voor synchrone toegang, wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd (oplocks worden niet verleend voor synchrone I/O-aanvragen).
  • Er zijn geen TxF- transacties op een stream van het bestand.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen andere openingen in de stream (zelfs niet door dezelfde thread).
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.

Als de huidige oplockstatus is:

  • Geen oplock: de aanvraag wordt verleend.

  • Niveau 2: De oorspronkelijke aanvraag op niveau 2 is verbroken met FILE_OPLOCK_BROKEN_TO_NONE. De aangevraagde exclusieve oplock wordt vervolgens verleend.

  • Niveau 1, Batch, Filter, Lezen, Lezen-Verwerken, Lees-Schrijven, of Lees-Schrijven-Verwerken: STATUS_OPLOCK_NOT_GRANTED wordt geretourneerd.

Niveau 2

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
    • Als het een map is, wordt STATUS_INVALID_PARAMETER geretourneerd.
  • De stream wordt geopend voor ASYNCHRONE toegang.
    • Wanneer deze voor SYNCHRONE toegang wordt geopend, wordt STATUS_OPLOCK_NOT_GRANTED teruggestuurd.
  • Er zijn geen TxF-transacties in het bestand.
    • Anderszins wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen huidige Byte Range-vergrendelingen op de stream.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
    • Voordat Windows 7 uitkwam, controleerde het besturingssysteem of er ooit een bytebereikvergrendeling op de stream had bestaan sinds de laatste keer dat deze was geopend, en wees de aanvraag af als dit het geval was.

Als de huidige oplockstatus is:

  • Geen oplock: de aanvraag wordt verleend.

  • Niveau 2 en/of lezen: de aanvraag wordt verleend. U kunt tegelijkertijd meerdere lees-oplocks op niveau 2 aan dezelfde stream verlenen. Meerdere oplocks op niveau 2 (maar niet Read) kunnen zelfs op hetzelfde handvat bestaan.
    • Als een leesvergrendeling wordt aangevraagd op een handle waaraan al een leesvergrendeling is verleend, wordt de IRP van de eerste leesvergrendeling voltooid met STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE voordat de tweede leesvergrendeling wordt verleend.
  • Niveau 1, Batch, Filter, Read-Handle, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED wordt teruggegeven.

Lezen

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
  • De stream wordt geopend voor Asynchrone toegang.
    • Wanneer deze voor SYNCHRONE toegang wordt geopend, wordt STATUS_OPLOCK_NOT_GRANTED teruggestuurd.
  • Er zijn geen TxF-transacties in het bestand.
    • In dat geval wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen huidige Byte Range-vergrendelingen op de stream.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen schrijfbare gebruikersgerichte secties op de stream.
    • Anders wordt STATUS_CANNOT_GRANT_REQUESTED_OPLOCK geretourneerd. De REQUEST_OPLOCK_OUTPUT_BUFFER.Flags veld zal de vlag REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT ingesteld hebben.

Als de huidige oplockstatus is:

  • Geen oplock: de aanvraag wordt verleend.

  • Niveau 2 en/of lezen: de aanvraag wordt verleend. U kunt tegelijkertijd meerdere lees-oplocks op niveau 2 aan dezelfde stream verlenen.
    • Bovendien, als een bestaande oplock eenzelfde oplocksleutel heeft als bij de nieuwe aanvraag, wordt de IRP afgehandeld met STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
  • Read-Handle en de bestaande oplock hebben een andere oplock-sleutel dan de nieuwe aanvraag: De aanvraag wordt verleend. Meerdere Read- en Read-Handle-oplocks kunnen op dezelfde stroom naast elkaar bestaan (zie de opmerking na deze tabel).
    • Anders (oplocktoetsen zijn hetzelfde) wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Niveau 1, Batch, Filter, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED wordt geretourneerd.

Read-Handle

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
  • De stream wordt geopend voor asynchrone toegang.
    • Wanneer deze voor SYNCHRONE toegang wordt geopend, wordt STATUS_OPLOCK_NOT_GRANTED teruggestuurd.
  • Er zijn geen TxF-transacties in het bestand.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen huidige Byte Range-vergrendelingen op de stream.
    • Anderszins wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen schrijfbare gebruikersgerichte secties op de stream.
    • Anders wordt STATUS_CANNOT_GRANT_REQUESTED_OPLOCK geretourneerd. De REQUEST_OPLOCK_OUTPUT_BUFFER.Flags veld zal de vlag REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT ingesteld hebben.

Als de huidige oplockstatus is:

  • Geen oplock: het verzoek wordt verleend.

  • Lees: de aanvraag wordt verleend.
    • Als een bestaande Read oplock dezelfde oplocksleutel heeft als de nieuwe aanvraag, wordt de IRP voltooid met STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE. Het resultaat is dat de oplock wordt bijgewerkt van Read naar Read-Handle.
    • Een bestaande leesvergrendeling die niet dezelfde oplocksleutel heeft als de nieuwe aanvraag blijft ongewijzigd.
  • Niveau 2, Niveau 1, Batch, Filter, Lezen-Schrijven, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED wordt geretourneerd.

Lezen-Schrijven

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
    • Als het een map is, wordt STATUS_INVALID_PARAMETER geretourneerd.
  • De stream wordt geopend voor ASYNCHRONE toegang.
    • Wanneer deze voor SYNCHRONE toegang wordt geopend, wordt STATUS_OPLOCK_NOT_GRANTED teruggestuurd.
  • Er zijn geen TxF-transacties in het bestand.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Als er andere openingen op de stream zijn (ook wanneer door dezelfde thread), moeten ze dezelfde oplock-sleutel hebben.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen schrijfbare gebruikersgerichte secties op de stream.
    • Anders wordt STATUS_CANNOT_GRANT_REQUESTED_OPLOCK geretourneerd. De REQUEST_OPLOCK_OUTPUT_BUFFER.Flags veld zal de vlag REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT ingesteld hebben.

Als de huidige oplockstatus is:

  • Geen oplock: het verzoek wordt verleend.

  • Lezen of Lezen-Schrijven en de bestaande oplock heeft dezelfde oplock-sleutel als de aanvraag: het IRP van de bestaande oplock wordt voltooid met STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE en de aanvraag wordt goedgekeurd.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Niveau 2, Niveau 1, Batch, Filter, Lees-Handvat, Lees-Schrijf-Handvat: STATUS_OPLOCK_NOT_GRANTED wordt geretourneerd.

Lezen -Write-Handle

Alleen verleend als aan alle volgende voorwaarden wordt voldaan:

  • De aanvraag is voor een bepaalde stroom van een bestand.
    • Als het een map is, wordt STATUS_INVALID_PARAMETER geretourneerd.
  • De stream is geopend voor asynchrone toegang.
    • Wanneer deze voor SYNCHRONE toegang wordt geopend, wordt STATUS_OPLOCK_NOT_GRANTED teruggestuurd.
  • Er zijn geen TxF-transacties in het bestand.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Als er andere open verzoeken in de stream zijn, zelfs door dezelfde thread, moeten ze dezelfde oplock-sleutel hebben.
    • Anders wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Er zijn geen schrijfbare gebruikersgerichte secties op de stream.
    • Anders wordt STATUS_CANNOT_GRANT_REQUESTED_OPLOCK geretourneerd. De REQUEST_OPLOCK_OUTPUT_BUFFER.Flags veld zal de vlag REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT ingesteld hebben.

Als de huidige oplockstatus is:

  • Geen oplock: het verzoek wordt verleend.

  • Lezen, Lezen-afhandelen, Lezen-schrijven, of Lezen-Write-Handle en de bestaande oplock heeft dezelfde oplock-sleutel als de aanvraag: de IRP van de bestaande oplock wordt voltooid met STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE en de aanvraag wordt goedgekeurd.
    • In andere gevallen wordt STATUS_OPLOCK_NOT_GRANTED geretourneerd.
  • Niveau 2, Niveau 1, Batch, Filter: STATUS_OPLOCK_NOT_GRANTED wordt teruggegeven.

Notitie

Lees- en Niveau 2 oplocks kunnen naast elkaar bestaan op dezelfde stroom, en Lees- en Read-Handle oplocks kunnen ook naast elkaar bestaan, maar Niveau 2 en Read-Handle oplocks kunnen niet naast elkaar bestaan.