§
Surov diskovni gonilnik

Lastnosti dokumenta

Naslov
Surov diskovni gonilnik
Del
-
Datum vsebine
31. 01. 2007
Original
Surov diskovni gonilnik
Vrsta
seminarska naloga
Jezik
slovenščina
Različica
1.0
Ustanova
Fakulteta za računalništvo in informatiko, Univerza v Ljubljani
Študij
Računalništvo in informatika, Logika in sistemi, 4. letnik
Predmet
Operacijska programska oprema
Mentor
prof. dr. Borut Robič
Avtor
Tine Lesjak, Borut Lesjak
Ocena
9 od 1-10

Krajša seminarska naloga, ki zajema le eno poglavje knjige o pisanju gonilnikov za naprave v sistemu UNIX [1].

Opredelitev

Surov disk

Izraz surov disk (ang. raw disk) se nanaša na dostop do podatkov na trdem disku ali kakšni podobni napravi za shranjevanje podatkov (npr. mediju) neposredno, to je na nivoju zloga (ang. byte), namesto prek datotečnega sistema (ang. file system), kot se to počne običajno.

Datotečni sistem ima sicer veliko prednosti pred surovim dostopom (npr. organiziranje in iskanje datotek ali metapodatki), vendar je surov dostop nujen vsaj v naslednjih primerih:

Surov dostop do diska je v sistemu Linux preprost. Le "izpišemo" vsebino naprave:

cat /dev/hda

Surov V/I gonilnik

Poznamo bločne ali medpomnilniške ali sistemske (ang. block/buffer/system) in znakovne ali neposredne ali surove (ang. character/direct/raw) vhodno/izhodne (V/I) gonilnike. Za pomnilniške naprave (npr. diskovne pogone), na katerih se nahajajo datotečni sistemi vrste UNIX, se navadno uporablja bločne gonilnike.

Znakovni gonilniki prenašajo podatke neposredno med uporabniškim procesom in napravo, medtem ko bločni gonilniki vedno prenašajo podatke med medpomnilnikom in napravo. Za prenose med uporabniškim procesom in medpomnilnikom pa je odgovorno jedro (ang. kernel) operacijskega sistema.

Jedro, ki sodeluje samo pri bločnih gonilnikih, prikrije fizične lastnosti naprave, podpira datotečne sisteme in uporabnikom omogoča transparentno delo s podatki.

Slika 1: Razlika med znakovnim in bločnim gonilnikom.

Neposredni dostop

Čeprav je model medpomnilnika in bločnega gonilnika še posebno učinkovita metoda za upravljanje datotečnih sistemov in izvajanje običajnih aplikacij, ki uporabljajo V/I, se lahko izkaže kot manj optimalna, kadar prebiramo ali zapisujemo več (manjših) blokov podatkov zaporedoma. Namesto optimalnejše izrabe V/I sistema medpomnilnik samo vsiljuje dodatno, nepotrebno kopiranje podatkov.

Četudi znakovnega pomnilnika ne moremo uporabljati za dostop do diska prek datotečnega sistema, ga lahko izrabljamo za neposredni dostop do naprave. Pri obsežnih prenosih podatkov (prenosih večjega števila blokov) bi bil to precej hitrejši način kot prenašanje prek medpomnilnika.

Dejansko se to pogosto počne pri UNIX sistemih. Znakovni gonilnik je za diskovne pogone kvečjemu dodan k običajnim bločnim. Ker se znakovni gonilnik izogne medpomnilniku in omogoča uporabniškemu procesu neposreden nadzor nad diskom, se disku, kadar do njega dostopimo prek znakovnega gonilnika, pogosto reče surov (ang. raw).

Kot se bomo v nadaljevanju prepričali, je razvoj znakovnega gonilnika za napravo, za katero že obstaja bločni gonilnik, povsem preprost. Jedro (govorimo o UNIX sistemu) ponuja programske rutine za opravljanje vsega bolj zahtevnega dela, ostalo pa lahko izvedemo prek obstoječe strategy rutine bločnega gonilnika.

Navidezni pomnilnik

Večina današnjih (UNIX) sistemov uporablja obliko pomnilniškega upravljanja, imenovano navidezni pomnilnik. To pomeni, da jedro rokuje z enoto za upravljanje s pomnilnikom (ang. memory management unit, MMU) na tak način, da uporabniški proces vidi, da ima na voljo več pomnilnika, kot pa ga je dejansko dodeljenega. Vsebina pomnilnika, ki trenutno ni dejansko dodeljena, je shranjena na disku.

Kadar proces dostopa do pomnilnika, ki dejansko ni dodeljen, se proces začasno ustavi (ang. suspend), dodeli se pomnilniško področje in vsebina se prebere z diska. Proces se nato nadaljuje, kot da bi bil dostopan pomnilnik že ves čas na voljo.

Podobno se zgodi, kadar jedru zmanjka pomnilnika. Takrat jedro pregleda, kateri deli pomnilnika so bili dodeljeni posameznim procesom in ugotovi, kateri deli se lahko prepišejo nazaj na disk in se sprostijo. Tej tehniki se reče ostranjevanje.

Težave

Sedaj pa razmislimo, kakšne potrebe ima lahko naprava, ki izvaja neposredni dostop do pomnilnika (ang. direct memory access, DMA). Ko prenaša podatke z diska v računalnik, prejme fizični pomnilniški naslov in tja prepiše podatke z diska neposredno v pomnilnik brez vpletanja MMU enote.

Pojavita se lahko dve težavi. Prva je, da se pri sistemih z navideznim pomnilnikom posameznim procesom ponavadi ne dodeli sosednjih delov pomnilnika. Kar proces vidi kot zaporedne logične naslove, je lahko povsem razmetano po vsem fizičnem pomnilniku.

Slika 2: Preslikava med navideznim in fizičnim pomnilnikom (vir: QNX).

Kaj se zgodi, če se pomnilnik, ki ga uporabniški proces dodeli za prebrane podatke, razteza prek meja strani? Naprava bo prenesla podatke v pomnilnik tja, kamor kaže fizični naslov (saj nima pomoči MMU enote) in bo zapisala del podatkov v pomnilnik, ki pripada nekemu drugemu procesu!

Druga težava nastane, kadar se jedro odloči, da pomnilniški blok, kamor naj bi se zapisali prebrani podatki, procesu ni več potreben in ga zapiše na disk ter sprosti. Ta del pomnilnika se priredi nekemu drugemu procesu. Ko naprava uporabi fizični naslov, ki ga ima od prejšnjega procesa, se del pomnilnika novega procesa pomotoma prepiše.

Jasno je, da nikoli ne sme priti do teh primerov.

Ti težavi se ne pojavljata v drugih gonilnikih iz dveh razlogov. Prvič, prenosi se vedno odvijajo le v času, ko je uporabniški proces v teku, in drugič, rutini za kopiranje podatkov skrijeta vse težave navideznega pomnilnika pred gonilnikom.

Pri znakovnih gonilnikih, ki uporabljajo DMA dostop, bomo morali uporabiti jedro. Jedru moramo naročiti posebne priprave, ki zagotavljajo, da DMA prenosi:

Znakovni gonilnik bomo zgradili na osnovi bločnega.

Splošna zgradba gonilnika

Splošna zgradba vseh surovih diskovnih gonilnikov je enaka. Rutini za branje (ang. read) in pisanje (ang. write) kličeta rutini jedra physck in physio. Neposredni dostop izvede rutina strategy, ki je del bločnega gonilnika.

Rutina physck zagotovi, da bo zahteva lahko postrežena s strani same naprave.
Rutina physio pa:

rawread(device)
dev_t device;
{
   if (physck(disksize, B_READ))
      physio(strategyaddr, NULL, device, B_READ);
}

rawwrite(device)
dev_t device;
{
   if (physck(disksize, B_WRITE))
      physio(strategyaddr, NULL, device, B_WRITE);
}

Spremenljivka disksize vsebuje število 512 bajtnih blokov na disku in se uporablja v rutini physck za potrditev veljavnosti zahteve. Rutina physio prebere parametre zahteve iz posebnih, prej določenih spremenljivk in pripravi glavo medpomnilnika tako, da do medpomnjenja ne bo prišlo.

physio nato pokliče strategy podprogram, podan z naslovom strategyaddr, ki izvede dejanski V/I dostop. Z vidika strategy podprograma izgleda zahteva enaka katerikoli drugi zahtevi jedra za praznjenje ali polnjenje medpomnilnika.

physio izvede tudi celo vrsto pomembnih funkcij poleg tega, da pridobi in nastavi glavo medpomnilnika. V pomnilniku zaklene strani, do katerih se dostopa, da jih jedro ne more vrniti na disk in sprostiti med izvajanjem V/I zahteve. Poleg tega razbije zahtevo na več delov v primeru, če le-ta seže prek meja strani.

Dodatne skrbi pri podprogramu strategy

Kadar se strategy rutine kličejo le za praznjenje in polnjenje medpomnilnika, se nam ni treba ukvarjati z velikostjo prenosa, saj je vedno nastavljena na en blok (navadno 1 kB).
Ko pa dodamo surov vmesnik bločnemu gonilniku in začnemo klicati strategy preko rutine physio, se stvari spremenijo. physio nastavi velikost prenosa na vrednost, ki je lahko kar velikost strani (ponavadi 4 kB).
Vedeti pa moramo, da čeprav diskovni gonilniki zmorejo obravnavati zahteve poljubne velikosti, nekateri bločni gonilniki ne znajo delati s prenosi, večjimi od 1 kB.

Dodatna skrb je, da se pomnilniški naslov medpomnilnika zdaj nahaja v uporabniškem naslovnem prostoru in ne več v naslovnem prostoru jedra. Posledično mora gonilnik uporabiti druge funkcije, ki znajo dobiti fizični naslov medpomnilnika.

Uporaba

Surov diskovni gonilnik se uporablja pri:

Koncept surovega gonilnika ni nov. V preteklosti so večkrat poskušali uvesti neposredni dostop na UNIX sistemih. V resnici ga danes podpira le nekaj inačic (npr. IBM AIX). Težava je v tem, da je potrebno imeti dobesedno dvakrat več logičnih naprav v sistemu (bločne in znakovne).

Avtorji sistema Linux so v jedru različice 2.4 vpeljali način, da je lahko več naprav povezanih s poljubno bločno napravo. Predstavili so objekt kiobuf. kiobuf skrije vse komplikacije v zvezi z navideznim pomnilnikom. Neposredni prenos lahko dosežemo tako, da ustvarimo kiobuf in mu podamo fizične strani, ki jih proces uporablja za V/I.

Viri

1
Pajari G. Writing UNIX Device Drivers. Addison-Wesley Professional. 1991. Poglavje 8, str. 147-153.
2
Raw Disk Definition. The Linux Information Project. 2006. http://www.bellevuelinux.org/raw_disk.html
3
Kalev D. Linux Tips and Tricks: Raw Disk I/O. ITworld.com, Accela Communications, Inc. 12. oktober 2001. http://www.itworld.com/nl/lnx_tip/10122001/
4
UnixWare 7 Documentation: physio(D3oddi). The SCO Group, Inc. 29. september 2004. http://uw714doc.sco.com/en/man/html.D3oddi/physio.D3oddi.html
5
UnixWare 7 Documentation: buf(D4). The SCO Group, Inc. 29. september 2004. http://uw714doc.sco.com/en/man/html.D4/buf.D4.html
6
QNX Developer Support: Finding Memory Errors. QNX Software Systems. 31. januar 2007. http://www.qnx.com/developers/docs/6.3.0/ide_en/user_guide/memory.html