System operacyjny nie posiadajacy systemu wejscia-wyjscia pozostaje czarna skrzynka bez jakiegokolwiek dostepu z zewnatrz. Dzieki systemowi wejscia-wyjscia mozliwa jest obsluga urzadzen zewnetrznych, umozliwiajacych roznorodna komunikacje uzytkownika z systemem. W dzisiejszych systemach niezbednymi urzadzeniami sa szeroko pojete terminale (jednostki terminalowe - np. X-TERMy, klawiatury i monitory podpiete do PC-ta lub tez wirtualne terminale obslugiwane przez siec), pamieci masowe (dyski, streamery, CD-ROMy, etc.), drukarki, modemy, karty sieciowe, karty graficzne i dzwiekowe, etc. Oprocz fizycznych urzadzen niektore wirtualne mechanizmy systemu operacyjnego moga byc obslugiwane przez system jako urzadzenia wejscia-wyjscia (np. sterownik pamieci czy tez mechanizm komunikacji korzystajacy z wirtualnych terminali "pty").
Komunikacja z urzadzeniami sprowadza sie do przesylania znakow (albo bajtow - jak kto woli). Dostep do urzadzen zewnetrznych mozemy podzielic na dostep blokowy i znakowy. Dostep znakowy (inaczej surowy) jest to rodzaj dostepu w ktorym przy odczycie zadania mozemy podzielic na poszczegolne znaki. W dostepie blokowym najmniejsza jednostka na jaka mozemy podzielic zadanie jest blok - pewien pakiet znakow o okreslonej dlugosci.
Przynajmniej teoretycznie wszystkie urzadzenia powinny udostepniac dostep znakowy, a tylko niektore dostep blokowy. W praktyce niektore sterowniki urzadzen daja nam jedynie dostep blokowy, uznajac dostep znakowy za zbedny.
Przykladem urzadzenia blokowego moze byc dysk twardy, stacje dyskietek, ZIP drive-y, etc. Urzadzenia znakowe to np. terminale i myszy. Pewne fizyczne parametry urzadzen wymuszaja uzycie danego trybu dostepu (jako jedynego logicznego sposobu dostepu). Trudno sobie wyobrazic dostep do myszy w trybie blokowym - musielibysmy wtedy czekac na reakcje komputera dopiero po wykonaniu odpowiedniej liczby ruchow... (mysz przesylalaby dopiero wtedy dane, gdy dopelnilibysmy bufor myszy do pelnego bloku). Dostep do dysku w trybie znakowym powodowalby znaczne spowolnienie komunikacji, poniewaz juz na poziomie hardware'owego mechanizmu obslugi dysku czytany jest od razu caly sektor. Gdybysmy chcieli odczytac caly sektor w trybie znakowym, bylby on czytany tyle razy, ile zawiera znakow.
Dostep do urzadzen blokowych sprowadza sie do zapisu / odczytu blokow o stalej wielkosci. Dla wszystkich urzadzen blokowych Linux dostarcza mechanizm pamieci buforowej, dzieki ktoremu mozemy uzyskac znaczne przyspieszenie komunikacji. O ile system otrzyma zadanie odczytu bloku, sprawdza najpierw czy w pamieci buforowej nie znajduje sie aktualna kopia tego bloku (wtedy nie trzeba go czytac z urzadzenia). Pamiec buforowa moze rowniez zapewniac strategie opoznionego zapisu oraz odczytu naprzod (read-ahead). Wiecej o tym w czesci dotyczacej dyskow.
Przerwania kontra odpytywanie
Za niskopoziomowy dostep do danego urzadzenia odpowiada tzw. sterownik (driver). Jest to zbior funkcji potrafiacych wykonywac zadania zapisu, odczytu oraz konfiguracji dla danego urzadzenia. Sterownik zazwyczaj jest dostarczany przez producenta danego urzadzenia.
Sterowniki mozemy podzielic na dwie glowne kategorie:
- sterowniki odpytujace (polling drivers)
- sterowniki przerwaniowe (interrupt driven drivers)
Sterownik odpytujacy nie korzysta z przerwan, wykonuje na raz jedno zadanie i to w sposob ciagly (nie przerywa pracy na wykonanie innego zadania). Najwazniejsza jednak cecha (jak rowniez najwieksza wada) jest blokowanie systemu podczas odczytu z urzadzenia (aktywne czekanie na mozliwosc zapisu / odczytu). Zaleta jest prosta budowa sterownika, niewielki naklad pracy systemu na obsluge wejscia/wyjscia (nie liczac aktywnego czekania) oraz nie zajmowanie przerwan. Ostatnia cecha jest o tyle wazna, ze czesto dysponujemy niewielka liczba wolnych przerwan.
Sterowniki odpytujace mozna stosowac do urzadzen, dla ktorych rzadko wystepuje sytuacja wielu zlecen w jednym czasie albo tez sa one rownie szybkie jak procesor.
W zamieszczonym przykladzie zadanie Procesu 1 jest realizowane, a Proces 2 musi czekac na zwolnienie urzadzenia. Oczekiwanie to jest realizowane przez aktywne czekanie - co jakis czas Proces 2 sprawdza, czy urzadzenie jest wolne. Dodatkowo warto zauwazyc, ze Proces 1 aktywnie czeka na otrzymanie wynikow.
Sterownik przerwaniowy dzieki przerwaniom jest w stanie uniknac aktywnego czekania. W przypadku urzadzen blokowych dodatkowo moze byc wykorzystana pamiec buforowa:
Zadanie odczytu / zapisu jest kierowane najpierw do pamieci buforowej.
W przypadku zadania odczytu, gdy nie ma w pamieci buforowej odpowiednich blokow, zadanie jest odkladane na pewna kolejke, z ktorej zadania sa pobierane przez urzadzenie (niekoniecznie po jednym). W oczekiwaniu na dane, system operacyjny moze wykonywac inne zadania. Urzadzenie po wykonaniu pobranych zadan wysyla PRZERWANIE, ktore budzi sterownik urzadzenia, ktory zajmuje sie odeslaniem danych do pamieci buforowej, skad moga byc one pobrane przez proces.
W przypadku zadania zapisu, system moze zadecydowac o odlozeniu na kolejke zadania zapisu, albo tez moze przetrzymac dane zadanie na pewien okres (opozniony zapis).
W Linuxie niektore urzadzenia moga byc sterowane na obydwa sposoby. Np. sterownik drukarki standardowo dziala jako sterownik odpytujacy, ale lokalizujac karte I/O dostarczajaca przerwanie dla drukarki, sterownik moze przejsc w tryb przerwaniowy.
INFORMACJE DODATKOWE:
W Kernel Hacker's Guide mozna przeczytac o innym rodzaju sterownikow - sterownikach dzialajacych w obszarze pamieci uzytkownika (user-space device drivers). Obsluga wejscia-wyjscia dziala wtedy w trybie uzytkownika (a nie jadra), a pamiec procesu jest wykorzystywana jako bufor pomiedzy procesem a urzadzeniem. Jest to dosc zgrabny chwyt na znaczne przyspieszenie komunikacji z urzadzeniem, z zachowaniem jednak pewnych specyficznych warunkow: dostep do urzadzenia ma tylko jeden proces, ktory dodatkowo musi pracowac w trybie super uzytkownika (superuser). Jako przyklad w KHG mozna obejrzec biblioteke vgalib - do szybkiej komunikacji z karta graficzna.