Sdílet prostřednictvím


Synchronní a asynchronní vstupně-výstupní operace

Viz také ukázkové aplikace související s vstupně-výstupními operacemi.

Existují dva typy synchronizace vstupu a výstupu (V/V): synchronní vstupně-výstupní operace a asynchronní vstupně-výstupní operace. Asynchronní vstupně-výstupní operace se také označuje jako překrývající se vstupně-výstupní operace.

V synchronní vstupně-výstupnísouboru vlákno spustí vstupně-výstupní operaci a okamžitě přejde do stavu čekání, dokud se vstupně-výstupní požadavek nedokončí. Vlákno provádějící asynchronních vstupně-výstupních operací souboru odešle do jádra vstupně-výstupní požadavek voláním příslušné funkce. Pokud je požadavek přijat jádrem, volající vlákno pokračuje ve zpracování jiné úlohy, dokud jádro signalizuje vlákno, že vstupně-výstupní operace je dokončena. Potom přeruší aktuální úlohu a podle potřeby zpracuje data z operace vstupně-výstupní operace.

Dva typy synchronizace jsou znázorněny na následujícím obrázku.

Snímek obrazovky diagramu znázorňující synchronní a asynchronní vstupně-výstupní operace

V situacích, kdy se očekává, že požadavek na vstupně-výstupní operace trvá hodně času, například aktualizace nebo zálohování velké databáze nebo pomalého komunikačního propojení, je obecně dobrým způsobem optimalizace efektivity zpracování asynchronní vstupně-výstupní operace. U relativně rychlých vstupně-výstupních operací ale může být režie zpracování požadavků na vstupně-výstupní operace jádra a signály jádra méně přínosné, zejména pokud je potřeba provést mnoho rychlých vstupně-výstupních operací. V tomto případě by byl lepší synchronní vstupně-výstupní operace. Mechanismy a podrobnosti implementace těchto úloh se liší v závislosti na typu popisovače zařízení, který se používá, a konkrétních potřebách aplikace. Jinými slovy, obvykle existuje několik způsobů, jak tento problém vyřešit.

Synchronní a asynchronní informace o vstupně-výstupních operacích

Pokud je soubor nebo zařízení otevřené pro synchronní vstupně-výstupní operace (tj. není zadáno FILE_FLAG_OVERLAPPED ), následná volání funkcí, jako je WriteFile , může blokovat provádění volajícího vlákna, dokud nedojde k jedné z následujících událostí:

  • Operace vstupně-výstupní operace se dokončí (v tomto příkladu zápis dat).
  • Dojde k vstupně-výstupní chybě. (Například potrubí je uzavřeno od druhého konce.)
  • V samotném volání došlo k chybě (například jeden nebo více parametrů není platný).
  • Jiné vlákno v procesu volá funkci CancelSynchronousIo pomocí popisovače zablokovaného vlákna, čímž ukončí probíhající vstupně-výstupní operace pro toto vlákno, což způsobí selhání této vstupně-výstupní operace.
  • Blokované vlákno je ukončeno systémem; Například samotný proces je ukončen nebo jiné vlákno volá funkci TerminateThread pomocí popisovače blokovaného vlákna. (Toto je obecně považováno za poslední možnost a není dobrý návrh aplikace.)

V některých případech může být toto zpoždění nepřijatelné pro návrh a účel aplikace, takže návrháři aplikací by měli zvážit použití asynchronních vstupně-výstupních operací s příslušnými objekty synchronizace vláken, jako jsou vstupně-výstupní porty dokončení. Další informace o synchronizaci vláken naleznete v tématu O synchronizaci.

Proces otevře soubor pro asynchronní vstupně-výstupní operace ve volání CreateFile zadáním příznaku FILE_FLAG_OVERLAPPED v parametru dwFlagsAndAttributes . Pokud není zadaný FILE_FLAG_OVERLAPPED, soubor se otevře pro synchronní vstupně-výstupní operace. Po otevření souboru pro asynchronní vstup a výstup se do volání ReadFile a WriteFile předá ukazatel na strukturu OVERLAPPED. Při provádění synchronních vstupně-výstupních operací se tato struktura nevyžaduje při volání ReadFile a WriteFile.

Poznámka

Pokud je soubor nebo zařízení otevřené pro asynchronní vstupně-výstupní operace, následná volání funkcí, jako je WriteFile , pomocí tohoto popisovače obvykle vrací okamžitě, ale může se také chovat synchronně s ohledem na blokované spuštění. Další informace naleznete v tématu asynchronní disk vstupně-výstupní operace se zobrazí jako synchronní ve Windows.

I když CreateFile je nejběžnější funkcí, která se používá pro otevírání souborů, svazků disků, anonymních kanálů a dalších podobných zařízení, lze také provádět vstupně-výstupní operace pomocí přetypovaného popisovače z jiných systémových objektů, jako je soket vytvořený funkcemisocket nebo accept.

Držitele objektů adresáře se získávají voláním funkce CreateFile s atributem FILE_FLAG_BACKUP_SEMANTICS. Popisovače adresářů se téměř nikdy nepoužívají – zálohovací aplikace jsou jednou z několika aplikací, které je obvykle používají.

Po otevření objektu souboru pro asynchronní I/O operace musí být struktura OVERLAPPED správně vytvořena, inicializována a předána do každého volání funkcí, jako je ReadFile a WriteFile. Při použití struktury OVERLAPPED v asynchronních operacích čtení a zápisu mějte na paměti následující skutečnosti:

  • Neuvolňujte ani neupravujte OVERLAPPED strukturu ani datový buffer, dokud nejsou všechny asynchronní vstupně-výstupní operace pro objekt souboru dokončeny.
  • Pokud deklarujete ukazatel na strukturu OVERLAPPED jako lokální proměnnou, neukončujte místní funkci, dokud nebudou dokončeny všechny asynchronní I/O operace na objektu souboru. Pokud dojde k předčasnému ukončení místní funkce, struktura OVERLAPPED vypadne z rozsahu a nebude přístupná žádným funkcím ReadFile nebo WriteFile, které potká mimo tuto funkci.

Můžete také vytvořit událost a umístit popisovač do struktury OVERLAPPED; čekací funkce je pak možné použít k čekání na dokončení vstupně-výstupní operace čekáním na popisovač události.

Jak už bylo uvedeno dříve, při práci s asynchronním popisovačem by aplikace měly při určování, kdy uvolnit prostředky přidružené k zadané vstupně-výstupní operaci na tomto popisovači. Pokud je popisovač předčasně uvolněn, ReadFile nebo WriteFile mohou nesprávně hlásit, že je vstupně-výstupní operace dokončena. Kromě toho funkce WriteFile někdy vrátí hodnotu TRUE s hodnotou GetLastErrorERROR_SUCCESS, i když používá asynchronní popisovač (který může také vrátit HODNOTU NEPRAVDA s ERROR_IO_PENDING). Programátoři zvyklí na synchronní vstupně-výstupní návrh obvykle uvolní prostředky vyrovnávací paměti dat v tomto okamžiku, protože TRUE a ERROR_SUCCESS označuje, že operace je dokončena. Pokud se ale porty pro dokončení vstupně-výstupních operací používají s tímto asynchronním popisovačem, paket dokončení se odešle i v případě, že se operace vstupně-výstupní operace dokončila okamžitě. Jinými slovy, pokud aplikace uvolní prostředky po WriteFile vrátí TRUE s ERROR_SUCCESS kromě rutiny portu pro doplňování vstupně-výstupních operací, bude mít dvojitou chybovou podmínku. V tomto příkladu doporučujeme, aby rutina portu dokončení byla zodpovědná výhradně za všechny operace uvolnění těchto prostředků.

Systém neudržuje ukazatel souboru na asynchronních popisovačích na soubory a zařízení, která podporují ukazatele souborů (tj. hledající zařízení), proto musí být pozice souboru předána funkcím čtení a zápisu v souvisejících posunových datových členech překrývající se struktury. Další informace naleznete v tématu WriteFile a ReadFile.

Umístění ukazatele souboru pro synchronní popisovač je udržováno systémem při čtení nebo zápisu dat a lze je aktualizovat také pomocí funkcí SetFilePointer nebo SetFilePointerEx.

Aplikace může také počkat na popisovač souboru, aby synchronizovala dokončení vstupně-výstupní operace, ale to vyžaduje extrémní opatrnost. Při každém spuštění vstupně-výstupní operace operační systém nastaví popisovač souboru na nepřiřazený stav. Při každém dokončení vstupně-výstupní operace operační systém nastaví popisovač souboru na signalovaný stav. Proto pokud aplikace spustí dvě vstupně-výstupní operace a čeká na popisovač souboru, neexistuje způsob, jak určit, která operace je dokončena, když je popisovač nastaven na signalovaný stav. Pokud aplikace musí v jednom souboru provádět více asynchronních vstupně-výstupních operací, měla by čekat na zpracování událostí v konkrétní struktuře OVERLAPPED pro každou vstupně-výstupní operaci, a ne na společném popisovači souborů.

Zrušení vstupně-výstupních operací

Pokud chcete zrušit všechny čekající asynchronní vstupně-výstupní operace, použijte jednu z těchto akcí:

  • CancelIo: Tato funkce zruší pouze operace vydané volajícím vláknem pro zadaný popisovač souboru.
  • CancelIoEx: Tato funkce zruší všechny operace vydané vlákny pro zadaný popisovač souboru.

Pomocí funkce CancelSynchronousIo zrušte čekající synchronní vstupně-výstupní operace.

Funkce ReadFileEx a WriteFileEx umožňují aplikaci určit rutinu, která se má provést (viz FileIOCompletionRoutine), když je dokončen asynchronní vstupně-výstupní požadavek.

ZapsatSoubor

ČístSoubor