Asynchronní I/O

V informatice je asynchronní I/O forma neblokujícího I/O zpracování , která umožňuje procesu pokračovat v provádění bez čekání na dokončení přenosu dat .

Vstupní a výstupní operace (I/O) na počítači mohou být ve srovnání se zpracováním dat poměrně pomalé. I/O zařízení může být o několik řádů pomalejší než RAM. Například během diskové operace, která trvá deset milisekund, může procesor, který běží na jeden gigahertz , provést deset milionů cyklů zpracování instrukcí.

Popis

Typy I/O a příklady unixových I/O funkcí :

Blokování neblokování
Synchronní psát, číst psát, číst + anketa / výběr
Asynchronní - aio_write, aio_read

Výhodou neblokování I/O je efektivní využití prostředků CPU. Například v aplikacích s grafickým uživatelským rozhraním může klasické blokování I/O zablokovat smyčku událostí při dlouhé operaci a způsobit, že aplikace nebude reagovat na interakci uživatele tím, že zablokuje celé vlákno provádění, které spouští smyčku událostí. Neblokující I/O se také používá v síťových aplikacích, kde je potřeba současně obsluhovat několik klientů v jednom vláknu (procesu) provádění. Při blokovacím přístupu by jen jeden „pomalý“ klient zpomalil celé vlákno.

Jaký je tedy rozdíl mezi asynchronním a synchronním přístupem k neblokujícím I/O? V druhém případě se zablokování zamezí kontrolou přítomnosti příchozích dat nebo možnosti zápisu odchozích dat. V asynchronním přístupu není vyžadována žádná validace. Název asynchronní znamená, že „ztratíme“ kontrolu nad pořadím I/O operací. Pořadí určuje operační systém, který staví operace na základě dostupnosti I/O zařízení. [jeden]

Asynchronní přístup k psaní programu je obtížnější, ale umožňuje větší efektivitu. Příkladem může být porovnání systémového volání epollna Linuxu a překrývajících se I/O na Microsoft Windows . epollje příkladem neblokujícího synchronního I/O a dotazuje se seznam deskriptorů souborů na připravenost k provádění operací. Je efektivní pro síťové I/O nebo různé typy meziprocesové komunikace, protože tyto operace zahrnují kopírování dat z a do vyrovnávací paměti jádra a nespotřebovávají významný čas CPU. Toto systémové volání je však neefektivní s pomalejším souborovým I/O. Například: pokud jsou v souboru nějaká data, pak jejich čtení zablokuje proces, dokud nebudou načtena z disku a zkopírována do poskytnuté vyrovnávací paměti. Přístup Windows je odlišný: zavoláte funkci ReadFile, předáte jí vyrovnávací paměť pro zápis a deskriptor souboru. Tato funkce pouze zahájí operaci čtení a okamžitě vrátí řízení procesu. V době, kdy operační systém na pozadí načte data ze souboru do vyrovnávací paměti, signalizuje procesu, že operace je dokončena, buď prostřednictvím ReadFile zpětného volání předaného funkci nebo přes port pro dokončení I/O (IOCP). Funkce zpětného volání bude volána pouze při čekání na dokončení operace (operací). [2]

Přístupy k asynchronnímu I/O

Druhy API poskytované aplikaci nemusí nutně odpovídat mechanismům skutečně poskytovaným operačním systémem, emulace je možná.

Zpětná volání

Dostupné na FreeBSD , OS X , VMS a Windows .

Potenciální problém je v tom, že hloubka zásobníku může nekontrolovatelně růst, takže extrémně klíčovou věcí je naplánovat další I/O až po dokončení předchozího. Pokud musí být uspokojeno okamžitě, počáteční zpětné volání „nerozvine“ zásobník před zavoláním dalšího. Systémy, které tomu zabraňují (jako je plánování další zakázky „uprostřed“), zvyšují složitost a snižují produktivitu. V praxi to však obvykle není problém, protože další I/O se obvykle sám vrátí, jakmile začne další I/O, což umožní „rozbalení zásobníku“. Problému také nelze zabránit tím, že se vyhnete dalším zpětným voláním pomocí fronty, dokud se nevrátí první zpětné volání.

Coroutines

Coroutines (coroutines) umožňují psát asynchronní programy v synchronním stylu. Příklady:

Existuje také mnoho knihoven pro vytváření coroutin (libcoro [3] , Boost Coroutine)

Dokončovací porty (fronty)

Dostupné na Microsoft Windows , Solaris a DNIX . Vstupně-výstupní požadavky jsou vydávány asynchronně, ale oznámení o provedení jsou poskytovány prostřednictvím mechanismu synchronizační fronty v pořadí, v jakém jsou dokončeny. Obvykle se spojuje se stavovým automatem strukturujícím hlavní proces ( programování řízené událostmi ), který se může jen málo podobat procesu, který nepoužívá asynchronní I/O nebo který používá jednu z jiných forem, což ztěžuje opětovné použití kódu. Nevyžaduje další speciální synchronizační mechanismy ani knihovny bezpečné pro vlákna , stejně jako textové (kód) a časové (událostní) proudy jsou odděleny.

I/O kanály

I/O kanály , které jsou k dispozici na sálových počítačích IBM , Groupe Bull a Unisys , jsou navrženy tak, aby maximalizovaly využití CPU a šířky pásma prováděním I/O na koprocesoru. Koprocesor má na desce DMA , zpracovává přerušení zařízení, je řízen CPU a přerušuje hlavní procesor pouze tehdy, když je to opravdu potřeba. Tato architektura také podporuje takzvané kanálové programy, které běží na kanálovém procesoru, aby vykonávaly těžké I/O aktivity a protokoly.

Implementace

Naprostá většina výpočetního vybavení pro všeobecné použití se zcela spoléhá na dvě metody implementace asynchronního I/O: dotazování a přerušení. Obvykle se obě metody používají společně, vyvážení je velmi závislé na konstrukci hardwaru a jeho požadovaných vlastnostech. ( DMA sama o sobě není další nezávislá metoda, je to jen prostředek, pomocí kterého lze udělat více práce s každým dotazováním nebo přerušením.)

Systémy pouze pro dotazování jsou obecně možné, malé mikrokontroléry (jako jsou systémy využívající PIC ) se často staví tímto způsobem. Systémy CP/M lze také budovat tímto způsobem (ačkoli tomu tak bylo jen zřídka), s nebo bez DMA. Také, když je potřeba nejlepší možný výkon pouze pro několik úkolů, na úkor jakýchkoli jiných potenciálních úkolů, dotazování může být dokonce vhodnější, protože režie spojená s přerušeními může být nežádoucí. (Obsluha přerušení vyžaduje čas a prostor k uložení alespoň části stavu procesoru, než bude čas pokračovat v přerušené úloze.)

Většina výpočetních systémů pro obecné účely se silně spoléhá na přerušení. Může existovat systém pouze pro přerušení, i když je obvykle vyžadováno určité dotazování. Více potenciálních zdrojů přerušení často sdílí společnou signální linku přerušení, v takovém případě ovladač zařízení používá dotazování ke zjištění skutečného zdroje. (Tentokrát zjišťování přispívá ke snížení výkonu přerušení systému. V průběhu let bylo vykonáno mnoho práce ve snaze minimalizovat režii spojenou s obsluhou přerušení. O moderních systémech přerušení lze říci, že jsou pomalé ve srovnání s některými dobře optimalizovanými systémy. , implementace dřívějších verzí, ale obecné zvýšení výkonu hardwaru to značně zmírnilo.)

Jsou možné hybridní přístupy, kdy přerušení může způsobit spuštění malého shluku asynchronních I/O a dotazování se provádí v tomto shluku samotném. Tato technika je běžná u ovladačů vysokorychlostních zařízení, jako je síť nebo disk, kde je čas ztracený při návratu k úloze spuštěné před přerušením delší než čas do další nutné údržby. (Hardware I/O pro obecné účely, který se dnes používá, silně spoléhá na DMA a velké datové vyrovnávací paměti, aby vyrovnal nevýhodu relativně pomalého systému přerušení. Je běžné používat dotazování v rámci hlavní smyčky ovladače , což může mít obrovskou propustnost ( v ideálním případě jsou průzkumy vždy úspěšné, když se objeví data nebo pokud je počet opakování nanejvýš malý).

Kdysi byl tento druh hybridního přístupu běžný u diskových a síťových ovladačů, kde neexistovala žádná DMA nebo významná schopnost ukládání do vyrovnávací paměti. Protože očekávané přenosové rychlosti byly vyšší než i čtyři operace v minimálním cyklu zpracování (bit-test, podmíněné-branch-back, načtení a uložení), často je hardware postaven tak, aby automaticky generoval stav čekání na I/ O zařízení, připravenost k dotazování dat je přenesena ze softwaru do hardwaru pro ukládání dat v procesoru, a tím se počet operací programového cyklu sníží na dvě. (Skutečně, použití samotného procesoru jako DMA exekutora). Procesor 6502 nabízel neobvyklý způsob poskytování tří prvků smyčky, která zpracovává vzhled dat, protože existuje hardwarový kolík, který při spuštění přímo nastavuje bit přetečení procesoru. (Samozřejmě je třeba věnovat velkou pozornost návrhu hardwaru, aby nedošlo k předefinování bitu přetečení mimo ovladač!)

Příklady

V těchto příkladech jsou všechny tři typy I/O v Pythonu uvažovány pomocí příkladu čtení. I/O objekty a funkce jsou abstraktní a slouží pouze jako příklad.

1. Blokování, synchronní:

zařízení = IO . otevřená () data = zařízení . read () # proces se zablokuje, dokud nebudou v zařízení tisknout nějaká data ( data )

2. Neblokující, synchronní:

zařízení = IO . open () while True : is_ready = IO . poll ( device , IO . INPUT , 5 ) # nečekejte déle než 5 sekund na příležitost ke čtení (INPUT) ze zařízení if is_ready : data = device . read () # proces se nezablokuje, protože jsme se ujistili, že je čitelný break # break out of the loop else : print ( "v zařízení nejsou žádná data!" )

3. Neblokující, asynchronní:

ios = IO . Zařízení IOService () = IO . otevřít ( ios ) def inputHandler ( data , err ): " Obsluha události přítomnosti dat " pokud ne err : print ( data ) zařízení . readSome ( inputHandler ) ios . loop () # počkejte na konec operace, aby se zavolaly potřebné handlery. Pokud nejsou žádné další operace, smyčka vrátí řízení.

Vzor reaktoru lze také připsat asynchronnímu :

zařízení = IO . otevřený () reaktor = IO . reaktor () def inputHandler ( data ): " Obsluha události přítomnosti dat " print ( data ) reaktor . zastavit () reaktor . addHandler ( inputHandler , zařízení , IO . INPUT ) reaktor . run () # spustí reaktor, který bude reagovat na I/O události a zavolá potřebné handlery

Poznámky

  1. Microsoft. Synchronní a asynchronní I/  O . Získáno 21. září 2017. Archivováno z originálu 22. září 2017.
  2. msdn FileIOCompletionRoutine . Získáno 21. září 2017. Archivováno z originálu 22. září 2017.
  3. libcoro . Získáno 21. září 2017. Archivováno z originálu 2. prosince 2019.