189
OPERACIJSKI SISTEMI Saša Divjak FRI, maj 2005 Vsebina Vsebina............................................................... 1 SPLOŠNI KONCEPTI...................................................... 5 Struktura operacijskega sistema........................................................................................................ 5 Pojem procesa...................................................................................................................................... 8 Razvrščanje procesov.......................................................................................................................... 9 Uvod v paralelne procese.................................................................................................................. 10 Problemi paralelnih procesov.....................................10 Problem kritičnih sekcij.........................................11 Problem omejenega pomnilnika (Proizvajalec - porabnik)...........12 Problem pisalcev in bralcev......................................12 Problem smrtnega objema..........................................13 Problem stradanja................................................13 Semaforji............................................................................................................................................ 14 Sinhronizacija procesov s semaforji..............................14 Semaforji in problem proizvajalec - porabnik.....................15 Števni semaforji.................................................16 Monitorji............................................................................................................................................. 16 Preprosto dodeljevanje (allocation) sredstev (resources) z monitorji:....................................................... 17 Monitorji in problem krožnega medpomnilnika......................18 Monitorji in problem Bralci - pisalci............................19 Zmenki................................................................................................................................................ 20 Osnovni koncepti.................................................20 Zmenki in problem proizvajalec - porabnik........................20 Kanali in sporočila............................................................................................................................. 21 Kanali........................................................... 21 Sporočila........................................................ 22 Porazdeljeni sistemi........................................................................................................................... 22 Komunikacija v porazdeljenih sistemih............................24

Handout Os 2

Embed Size (px)

DESCRIPTION

arhitecture of operating systems

Citation preview

Page 1: Handout Os 2

OPERACIJSKI SISTEMISaša Divjak

FRI, maj 2005

VsebinaVsebina............................................................................................................................................................1

SPLOŠNI KONCEPTI...................................................................................................................................5

Struktura operacijskega sistema..................................................................................................................5

Pojem procesa.............................................................................................................................................8

Razvrščanje procesov..................................................................................................................................9

Uvod v paralelne procese..........................................................................................................................10Problemi paralelnih procesov...............................................................................................................10Problem kritičnih sekcij........................................................................................................................11Problem omejenega pomnilnika (Proizvajalec - porabnik)..................................................................12Problem pisalcev in bralcev..................................................................................................................12Problem smrtnega objema.....................................................................................................................13Problem stradanja..................................................................................................................................13

Semaforji....................................................................................................................................................14Sinhronizacija procesov s semaforji.....................................................................................................14Semaforji in problem proizvajalec - porabnik......................................................................................15Števni semaforji....................................................................................................................................16

Monitorji....................................................................................................................................................16Preprosto dodeljevanje (allocation) sredstev (resources) z monitorji:..................................................17Monitorji in problem krožnega medpomnilnika...................................................................................18Monitorji in problem Bralci - pisalci....................................................................................................19

Zmenki........................................................................................................................................................20Osnovni koncepti..................................................................................................................................20Zmenki in problem proizvajalec - porabnik..........................................................................................20

Kanali in sporočila....................................................................................................................................21Kanali....................................................................................................................................................21Sporočila...............................................................................................................................................22

Porazdeljeni sistemi...................................................................................................................................22Komunikacija v porazdeljenih sistemih................................................................................................24

Niti, nitkanje..............................................................................................................................................25Implementacija niti...............................................................................................................................28Niti in Java............................................................................................................................................29

Upravljanje s primarnim pomnilnikom.....................................................................................................30Asociacija naslovov..............................................................................................................................30Dinamično nalaganje in povezovanje...................................................................................................31Zamenjava (swapping)..........................................................................................................................31

Page 2: Handout Os 2

Virtualni pomnilnik...............................................................................................................................31Krmiljenje bremena (Load control)......................................................................................................34

Sekundarni pomnilnik................................................................................................................................35Zaporedno alociranje (Contiguous Allocation):...................................................................................35Povezano alociranje (Linked Allocation):............................................................................................36Indeksirano alociranje (Indexed Allocation):.......................................................................................37

Uvod v datotečne sisteme...........................................................................................................................38Atributi datotek.....................................................................................................................................38Operacije nad datotekami.....................................................................................................................39Tipi datotek...........................................................................................................................................39Vrste direktorijev..................................................................................................................................40

Porazdeljeni datotečni sistemi...................................................................................................................42Lastnosti porazdeljenega datotečnega sistema......................................................................................43

Strategije razvrščanja dostopov do diska..................................................................................................44

Vhodno - izhodni podsistem.......................................................................................................................46

Gonilniki naprav........................................................................................................................................48Namen gonilnika naprave.....................................................................................................................48Tipi gonilnikov naprav..........................................................................................................................48Kdaj kličemo gonilnik naprave.............................................................................................................48Mesto gonilnika (pri UNIX).................................................................................................................49Primer branja enega znaka....................................................................................................................50

Zaščita in varnost OS.................................................................................................................................52Domena zaščite:....................................................................................................................................53Varnost sistemov...................................................................................................................................54

ŠTUDIJ PRIMERA UNIX/LINUX.............................................................................................................55

Struktura operacijskega sistema UNIX.....................................................................................................55

Procesi pri sistemu UNIX..........................................................................................................................56Življenje procesa...................................................................................................................................56Primer fork( )........................................................................................................................................56Stanja procesa.......................................................................................................................................57Struktura procesa:.................................................................................................................................58

Datotečni sistem UNIX..............................................................................................................................59Vloga podatkovnih struktur pri stavku read( )......................................................................................62

Interna predstavitev datotek......................................................................................................................62Trde vezi...............................................................................................................................................63

Študijski primer z datotečnim sistemom....................................................................................................64

Medpomnilnik (buffer cache).....................................................................................................................66

Vhodno - izhodni podsistem UNIX............................................................................................................69

Prekinitve in njihova obravnava................................................................................................................72Inicializacija podatkovnih struktur za obravnavo prekinitev................................................................73Obravnava prekinitev............................................................................................................................74

Primer gonilnika UNIX..............................................................................................................................75

Medprocesna komunikacija pri UNIX.......................................................................................................80Semaforji...............................................................................................................................................80Skupen pomnilnik.................................................................................................................................81

2

Page 3: Handout Os 2

Sporočila...............................................................................................................................................81

Signali UNIX..............................................................................................................................................81Koncept signalov UNIX.......................................................................................................................81Nezanesljivi signali...............................................................................................................................83Problem prekinjenih sistemskih klicev.............................................................................................84"Reentrant" funkcije:............................................................................................................................84Množice signalov (signal sets)..............................................................................................................85

Cevi (Pipes)...............................................................................................................................................86

Sistem NFS.................................................................................................................................................88Kako montiramo nek datotečni sistem na strežnik NFS.......................................................................91

ŠTUDIJ WINDOWS NT (Win 2000)..........................................................................................................93

Struktura op. sistema Windows NT/2000...................................................................................................93In še struktura Windows 2000..............................................................................................................94

Upravnik objektov......................................................................................................................................95Objekti izvajalnika................................................................................................................................95Struktura objektov Windows 2000.......................................................................................................97Upravljanje z objekti.............................................................................................................................99Zaščita objektov..................................................................................................................................101

Procesi in niti...........................................................................................................................................103Procesi.................................................................................................................................................103Kako tvorimo proces...........................................................................................................................105Niti......................................................................................................................................................106Stanja niti............................................................................................................................................107Proces jedra in objekti niti..................................................................................................................108Razvrščanje niti in procesov...............................................................................................................109Še nekaj o scenarijih razvrščanja........................................................................................................111Struktura procesov..............................................................................................................................112

Okna in zaščiteni podsistemi...................................................................................................................112Uvod v zaščitene podsisteme..............................................................................................................112Podsistem Win32................................................................................................................................114Virtualni stroj DOS (VDM)................................................................................................................115WOW..................................................................................................................................................116Posredovanje obvestil s klicem lokalne procedure.............................................................................117

Upravnik virtualnega pomnilnika............................................................................................................117

Prekinitve in izjeme..................................................................................................................................120Kaj so prekinitve?...............................................................................................................................120Delovanje prekinitev in izjem?...........................................................................................................120Aparaturne prekinitve.........................................................................................................................121Prekinitve za klice zamaknjenih procedur DPC (deferred procedure call).........................................122Prekinitve za klice asinhronih procedur APC (asynchronous procedure call)...................................123Programske prekinitve........................................................................................................................124

Vhodno - izhodni sistem...........................................................................................................................125Komponente vhodno izhodnega sistema............................................................................................125Pregled................................................................................................................................................126Potek vhodno izhodnih operacij..........................................................................................................127Vrste gonilnikov..................................................................................................................................127Vhodno- izhodne operacije.................................................................................................................129Plasti gonilnikov naprav.....................................................................................................................131Struktura gonilnika..............................................................................................................................132

3

Page 4: Handout Os 2

Problem sinhronizacije........................................................................................................................133Podatkovne strukture..........................................................................................................................133Paketi vhodno izhodnih zahtevkov.....................................................................................................135Servisiranje vhodno-izhodnega zahtevka...........................................................................................137Servisiranje prekinitvenega zahtevka naprave....................................................................................138Zaključek vhodno izhodnega zahtevka...............................................................................................139Vhodno izhodni zahtevki in plastni gonilniki.....................................................................................142

Upravnik medpomnilnika.........................................................................................................................142Koherenca vmesnega pomnenja.........................................................................................................142Struktura medpomnilnika....................................................................................................................143

NTFS........................................................................................................................................................145Interna struktura NTFS.......................................................................................................................145NTFS - struktura na disku...................................................................................................................146NTFS - toleranca napak......................................................................................................................148

4

Page 5: Handout Os 2

SPLOŠNI KONCEPTIStruktura operacijskega sistema

Operacijski sistem zagotavlja programom okolje in storitve, potrebne za njihovo izvajanje. Sestavlja ga več sistemskih komponent:

Upravljanje procesov, Upravljanje s primarnim pomnilnikom, Upravljanje s sekundarnim pomnilnikom, Upravljanje z vhodno-izhodnimi napravami, Upravljanje z datotečnim sistemom, Sistem zaščite (dostop programov, procesov, uporabnikov, ugotavljanje napak), Sodelovanje v mreži (porazdeljeni sistemi), Interpretiranje ukazov.

Vmesnik med procesi in operacijskim sistemom predstavljajo sistemski klici. Z njimi zahtevajo (uporabniški) programi neko storitev operacijskega sistema. Po drugi strani pa lahko pride do prekinitev izvajanja uporabniških programov tudi s strani operacijskega sistema. Splošno sliko strukture operacijskega sistema prikazuje spodnja slika:

5

Page 6: Handout Os 2

Operacijski sistem interaktira neposredno z aparaturno opremo, programom pa zagotavlja storitve tako, da so le-ti izolirani od aparaturne opreme. Na celoten sistem lahko gledamo kot na množico plasti. Aplikacijski programi predstavljajo zunanje plasti, sam operacijski sistem pa predstavlja sistemsko jedro (kernel). Aplikacijski programi lahko zahtevajo od jedra izvedbo posameznih storitev s takoimenovanimi sistemskimi klici.

Praviloma pozna računalnik dva režima izvajanja nekega procesa: uporabniški režim (user mode) in sistemski režim (kernel mode, system mode). Normalno so naši programi v uporabniškem režimu. Šele ko to zahtevamo s primernim sistemskim klicem, preide proces v sistemski režim. V takem stanju izvedejo rutine v jedru zahtevano storitev in nato vrnejo klicočemu programu kodo s statusom izvedbe (error code).Proces se povrne v uporabniški režim.

Proces lahko preide iz uporabniškega v sistemski nivo tudi zaradi izjemnega dogodka (exception), kakršnega predstavlja na primer poskus izvedbe nelegalne instrukcije. Tako v primeru nepredvidenega dogodka kot tudi v primeru namernega sistemskega klica pride do takoimenovane programske prekinitve (ali pasti), ki povzroci preklop v sistemski režim in klic ustrezne servisne rutine jedra.

Do prekinitve programa lahko pride tudi zaradi aparaturne prekinitve (zahtevek z neke periferne naprave). Tudi v tem primeru pride do preklopa iz uporabniškega režima v sistemski (če se v tem še ne nahajamo) in do izvedbe ustrezne prekinitvene rutine. Ko je proces v sistemskem režimu, lahko pride do preklopa na drug proces. Pri takem preklopu se mora seveda ohraniti stanje (prekinjenega) procesa tako, da se bo kasneje lahko nemoteno nadaljeval. Pravimo, da ima proces nek kontekst in da pride do preklopa konteksta (context switch). V sodobnejših operacijskih sistemih zasledimo organiziranost operacijskega sistema po konceptih klijent- strežnik (client-server). Tu so komponente operacijskega sistema majhne in samostojne. Vsak strežnik teče kot poseben proces v uporabniškem režimu. Jedro skrbi le za komunikacijo med takimi strežniki (message passing). Govorimo o mikro-jedru. Tak sistem je bolj varen pred izpadi in bolj fleksibilen. Njegov koncept prikazuje spodnja slika:

6

Page 7: Handout Os 2

Konkretni primeri: Zgradba operacijskega sistema UNIX Zgradba operacijskega sistema Windows NT

V obdobju večprocesorskih sistemov ločimo med simetričnimi (SMP) in asimetričnimi modeli. V prvem primeru nimamo nekega "glavnega" procesorja, pri asimetričnih modelih pa operacijski sistem uporablja en procesor, aplikacije pa druge. Primer simetričnega operacijskega sistema je Windows 2000.

7

Page 8: Handout Os 2

Pojem procesaProgramski proces je pravzaprav odvijanje nekega programa skupaj z okoljem, ki je za to odvijanje potrebno.V to okolje sodijo predvsem potrebne programske strukture, kot je njegova koda, podatkovne strukture in sklad. V to okolje sodijo tudi vsi ostala potrebna sredstva (resources). Tako potrebujemo za omenjene programske strukture zadostno količino pomnilnika, dostop do perifernih naprav itd.

Procesi so paralelni, če obstojajo istočasno. Paralelni procesi so lahko drug od drugega neodvisni, lahko pa so asinhroni, kar pomeni, da zahtevajo občasno sinhronizacijo in sodelovanje. Interakcija asinhronih programov je včasih zelo kompleksna.

Pri obravnavi paralelnih procesov zasledimo vrsto zanimivih pojavov in pred programerjem takih (programskih) procesov se pojavijo dodatni problemi, na kakršne ni naletel niti pri zelo kompliciranih klasičnih programskih sistemih.

Tako si lahko posamezni programi med seboj konkurirajo za sredstva (resources), ki so v njihovem "delovnem" okolju na voljo. Pravimo, da so taki procesi konkurenčni. Preprost zgled za tako konkurenčnost so na primer sočasne zahteve po dostopu do diska v mnogouporabniškem računalniškem sistemu.

8

Page 9: Handout Os 2

Pogosto se pojavi potreba po medsebojni časovni koordinaciji posameznih paralelnih procesov. In ne nazadnje, posamezni procesi se morajo pogosto med seboj pogovarjati. Govorimo o medprocesni koordinaciji in komunikaciji.

Prav zaradi konkurenčnosti procesov in tudi potreb po nihovi medsebojni sinhronizaciji moramo uvesti pojem stanja procesa. Zaenkrat omenimo le, da je proces, ki mora čakati na nek drug proces, na sprostitev nekega sredstva (resource) ali na nek dogodek, v blokiranem stanju. Poenostavljeno naj velja, da je proces, ki ni blokiran, tekoč. V resnici so pri gradnji posameznih operacijskih sistemov uvedli še vec procesnih stanj. Splošen koncept prehajanja med procesnimi stanji prikazuje naslednja slika.  

Konkreten primer: Stanja procesov pri sistemu UNIX

Razvrščanje procesov  

Sodobni operacijski procesi so tipično večprocesni oziroma celo večnitni. Zato  mora posebni modul, ki mu pravimo  razvrščevalnik (scheduler) poskrbeti, da izmenično vsakemu od teh procesov dodeljuje krajšo časovno rezino. Tako imamo vtis, kot da vsi procesi potekajo sočasno.

Eden od algoritmov, ki ga uporabljajo razvrščevalniki, je takoimenovani Round-Robin, ki ga prikazuje spodnja slika.

 

9

Page 10: Handout Os 2

Bolj kompleksni algoritmi razvrščanja skušajo zagotoviti ugodno prepustnost za procese, ki jim zadoščajo kratke časovne rezine. V to skupino sodijo krajši programi in interaktivni programi, ki večinoma čakajo na konec neke vhodno-izhodne operacije.  Numerično intenzivnim procesom pa prepuščajo čas, ko računalnik ni zaposlen. Primer takega algoritma je večnivojski algoritem razvrščanja, ki ga prikazuje spodnja slika.

 

Pri tem algoritmu dodeli razvrščevalnik računalniški čas procesu, ki je prvi na čakalni listi na najvišjem nivoju. Če tak proces ne konča svoje naloge v času njegove časovne rezine, ga razvrščevalnik prestavi na rep čakalne vrste nižjega nivoja. Procesom, ki čakajo na čakalnih vrstah nižjih nivojev, razvrščevalnik dodeli časovno rezino le, če so čakalne vrste višjih nivojev prazne. Vrsta na najnižjem nivoju sama zase predstavlja spet klasični Round Robin algoritem, v njej pa končajo numerično intenzivni procesi.

Uvod v paralelne procese

Problemi paralelnih procesov

Sočasno izvajanje več programskih procesov odpira dodatne probleme, ki jih pri navadnih programih ne zasledimo, četudi so ti programi lahko zelo kompleksni. Večina teh problemov terja pravilno sinhronizacijo paralelnih procesov. Stvar postane še toliko težja, če ti programski procesi ne potekajo na istem računalniku. Oglejmo si najprej tipične probleme, zatem pa še mehanizme, ki jih moramo zato uporabiti.

10

Page 11: Handout Os 2

Problem kritičnih sekcij

Problem nastopi, ko več sočasnih procesov občasno terja dostop do skupnih računalniških virov ali skupnih podatkovnih struktur, ki jih želi spreminjati. Ko dobi proces dostop do takih skupnih podatkovnih struktur, je v takoimenovani kritični sekciji.

Zagotoviti moramo,da je v času, ko je nek proces v kritični sekciji, drugim procesom dostop v to sekcijo prepovedan.

Ostali procesi lahko medtem paralelno potekajo, v primeru zahteve po vstopu v zasedeno kritično sekcijo pa čakajo. Ob sprostitvi kritične sekcije lahko vanjo vstopi lepo en proces.

Medsebojno izobčenje sočasnih programskih procesov lahko zagotovimo s posebnimi konstrukti.

Primer:

Vzemimo sistem z več terminali. Sistem naj "šteje število vrstic, vtipkanih v enem dnevu". V ta namen imamo skupno sistemsko spremenljivko lineCount. Delo posameznih uporabnikov za terminali nadzorujejo ločeni procesi. Kadarkoli nek uporabnik na svojem terminalu vtipka vrstico, se izvedejo v sklopu njegovega programskega procesa stavki naslednje vsebine:

load lineCount add 1 store lineCount

Vzemimo primer, da lineCount že vsebuje vrednost 1234 in da proces A pravkar izvaja ukaz add, ki vrednost v akumulatorskem registru poveča na 1235. Naj v tem trenutku proces B (zaradi enakega štetja) prav tedaj izvede operacijo load. Podatke 1235 v akumulatorju se zato spet pokvari na 1234 in, če bi v tem hipu proces A izvedel še zadnjo operacijo (store), bi očitno shranil v spremenljivko lineCount zgrešeno vrednost.

Problem lahko rešimo, če je dostop posameznih programskih procesov do takih skupnih spremenljivk, kot je v našem primeru lineCount, ekskluziven. Podobne probleme zasledimo tudi na primer pri večuporabniškem dostopu do podatkov v podatkovnih bazah, pri (sistemskem) dostopu do skupnih podatkovnih struktur (operacijskega sistema) v večprocesnih operacijskih sistemih itd.

11

Page 12: Handout Os 2

Problem omejenega pomnilnika (Proizvajalec - porabnik)

To je v bistvu problem dveh sočasnih procesov, pri katerem en proces (proizvajalec) generira podatke, ki jih mora uporabljati drug proces (uporabnik). Da bi bilo izvajanje obeh procesov med seboj čimbolj neodvisno, shranjuje proces - proizvajalec podatke v skladišče (medpomnilnik, buffer), drug proces pa jih iz tega skladišča jemlje v istem zaporedju.

Tako sožitje dveh procesov zasledimo zelo pogosto v okviru modulov operacijskih sistemov, predvsem v modulih, ki so odgovorni za vhodno- izhodne operacije računalnika.

Seveda je "skladišče" omejeno (če drugega ne, že z velikostjo pomnilnika). Proizvajalec lahko medpomnilnik napolni le do neke meje. Pred nadaljnjim polnjenjem mora počakati, da ga "porabnik" vsaj malo izprazni. Prav tako ne sme proces - porabnik nič "vzeti iz medpomnilnika", če ni že vanj kaj vložil proces - proizvajalec. Potrebna je koordinacija delovanja obeh procesov.

Omejenemu pomnilniku pravijo včasih tudi krožni medpomnilnik (ring- buffer), saj ga začne proizvajalec, potem, ko je prišel do konca, spet pomniti "na začetku". Analogno se dogaja s porabnikom: Ko vzame z medpomnilnika zadnji element, gre naslednjega iskati spet na "začetek". V računalniškem smislu uporabljata oba procesa kazalca na tekoči element v tem medpomnilniku. Pomembno je, da kazalec procesa- porabnika ne prehiti kazalca proizvajalca (in obratno).

Problem pisalcev in bralcev

Imejmo več sočasnih procesov, ki lahko berejo ali popravljajo isto podatkovno strukturo. Struktura naj bo dovolj kompleksna, da je posamezen proces ne more prebrati ali zapisati v "enem koraku". To pomeni, da bi lahko nek proces začel zapisovati novo verzijo, med samim zapisovanjem pa bi lahko nek drug proces strukturo "prebral". Podatki, ki bi jih tako dobil, bi bili lahko delno že "novi", delno pa še "ta stari", skratka nekonsistentni. Da ne pride do nekonsistence podatkov, moramo zagotoviti, da v obdobju, ko nek proces zapisuje nove podatke, noben drug proces ne more ne brati, ne pisati v to strukturo. Seveda pa lahko več "bralcev" sočasno bere. Potrebna je torej pravilna koordinacija pisalcev in bralcev.

12

Page 13: Handout Os 2

Problem smrtnega objema

Obravnavali bomo različne tehnike medsebojne sinhronizacije paralelnih programskih procesov. Ta se doseže tako, da proces, ki naj bo sinhroniziran z nekim drugim, v danem trenutku počaka na nek dogodek (event). Prav možno je, da do tega dogodka iz različnih razlogov ne more priti. Pravimo, da se je en ali več paralelnih procesov znašlo v smrtnem objemu (deadlock). Oglejmo si nekaj možnih vzrokov za tak pojav ter ugotovimo, kako ga lahko preprečujemo.

Do smrtnega objema lahko pride, ko na primer dva procesa čakata drug na (dogodek) drugega. Ker pa sta oba s tem blokirana, do odrešilnega dogodka ne v enem ne v drugem procesu ne pride. Preprost zgled je lahko naslednji. Imamo dva programska procesa, ki za svoje delo potrebujeta dve periferiji. Vsak si že lasti eno in čaka na drugo. Problem ponazoruje slika.

Kateri pogoji so potrebni za nastop smrtnega objema? Kako preprečujemo nastop smrtnega objema?

Problem stradanja

Sorodni problem smrtnemu objemu je problem stradanja ali nedoločenega zapostavljanja. Včasih mu tudi rečemo problem živega objema (livelock). Nek proces čaka na neko sredstvo, vendar je (morda zaradi nižje prednosti) stalno zapostavljen in nikdar ne pride na vrsto. Tipičen primer živega objema lahko zasledimo pri slabo zasnovanem algoritmu razvrščanja procesov (scheduling). Nek proces z nizko prioriteto morda nikdar ne pride na vrsto, ker imajo prednost procesi z višjo prednostjo. Ta problem lahko rešujemo na primer tako, da s staranjem prednost takemu procesu zvišujemo.

Navedene probleme blokiranja nekega procesa (nedoločeno zapostavljanje, smrtni objem) zasledimo na primer pri operacijskih sistemih računalnikov. Operacijski sistem je predvsem "upravnik sredstev" (resource manager) računalniškega sistema. Za ta sredstva pa istočasno lahko konkurira večparalelnih programskih procesov.

13

Page 14: Handout Os 2

Semaforji

Za reševanje problemov sinhronizacije sočasnih procesov je Dijkstra uvedel koncept semaforjev in takoimenovanih operacij P in V. Oznake teh operacij izhajajo iz holandskih besedic vhod in izhod. Semafor je ščitena spremenljivka (pravzaprav podatkovna struktura), ki jo lahko inicializiramo ter dosežemo le z operacijami P in V. Binarni semaforji lahko zavzamejo le vrednosti 0 in 1, števni semaforji pa poljubne nenegativne vrednosti.

Operacijo P na semaforju S zapišemo kot P(S) in deluje tako:

if S>0    then S:= S-1    else (* pocakaj na S v ustrezni vrsti *);

Operacijo V na semaforju S pa zapiąemo kot V(S) in deluje tako

if (* eden ali vec procesov caka v vrsti  na S *)    then (* naj vstopi en proces *)else S:=S+1;

Procesi naj čakajo na zaključek P(S) v čakalni vrsti tipa FIFO (first in - first out). Zato je vsak semafor podatkovna struktura, ki vsebuje en integer in eno vrsto.

V literaturi označujejo operaciji P(S) in V(S) tudi z imeni wait(semaphore) in signal(semaphore), ki imata v bistvu enak pomen.

Operaciji P in V morata biti nedeljivi. Same konkretne implementacije semaforjev so lahko različne. Če imamo na voljo instrukcije tipa test-and-set, jih uporabimo, sicer pa ne dovolimo prekinitev (disable interrupts) med samim izvajanjem operacij wait in signal.

Sinhronizacija procesov s semaforji

Naslednji zgled uporabe semaforjev je sinhronizacija procesov. Vzemimo za primer vhodno-izhodne računalniške operacije. Proces, ki sproži vhodno-izhodno operacijo, se običajno sam blokira, da bi tako počakal na njen zaključek. Blokirani proces kasneje obudi nek dogodek v nekem drugem procesu. Pri taki interakciji imamo torej protokol blokiranje- bujenje. Ta je uporaben, kadarkoli želimo nek proces sinhronizirati z danim dogodkom v drugem procesu:

program sinhronizacija;var dogodek:semaphore;procedure process_A;begin  (*..predhodne operacije...*)  wait(dogodek); (* proces_A caka na dogodek v procesu B *)  (*...nadaljevanje procesa...*)end;

14

Page 15: Handout Os 2

procedure process_B;begin  (*...predhodne operacije ..*)  signal(dogodek);  (*..nadaljevanje procesa..*)end;

begin  initSemaphore(dogodek,0);  parbegin    process_A;    process_B;  parend;end.

Semaforji in problem proizvajalec - porabnik

Oglejmo si še uporabnost semaforjev za reševanje problema proizvajalec - porabnik. Proces A tvori podatke, ki jih proces B uporablja. Hitrost izvajanja posameznih procesov A in B se v splošnem ne ujema. Zagotoviti moramo, da ne prihaja niti do izgube podatkov niti do večkratnega branja in izpisa istega podatka. Oba procesa moramo torej sinhronizirati, kot to kaže naslednji zgled:

program proizvajalec_porabnik;var zasedeno:semaphore;    vpisano:semaphore;    buffer: integer;

procedure proizvajalec;var rezultat: integer;begin  repeat    racunaj(rezultat);    wait(zasedeno);  (* vstop v kriticno sekcijo *)    buffer:=rezultat;    signal(vpisano);  (* sinhronizacija *)    signal(zasedeno); (* sprostitev kriticne sekcije *)  until FALSE;end;

procedure porabnik;var podatek:integer;begin  repeat     wait(vpisano); (* blokiran proces, ce podatka se ni *)     wait(zasedeno);  (* vstop v kriticno sekcijo *)    podatek:=buffer;    signal(zasedeno);  (* sprostitev kriticne sekcije *)    izpis(podatek);  until FALSE;end;

15

Page 16: Handout Os 2

begin  initSemaphore(zasedeno,1);  initSemaphore(vpisano,0);  parbegin    proizvajalec;    porabnik;  parend;end.

Števni semaforji

Števne semaforje s pridom uporabimo, če želimo alokacijo enega sredstva (resource) iz zaloge enakih sredstev. Semafor inicializiramo na število sredstev v zalogi. vsaka operacija P (oziroma wait) zmanjša semafor za 1 in tako pokaže, da se je zaloga zmanjšala. Vsaka operacija V (oziroma signal) poveča semafor za 1 in tako nakaže povečanje zaloge za 1. Če uporabimo operacijo wait potem, ko je semafor dosegel 0, mora tak proces počakati, da se vsaj eno sredstvo sprosti z ustrezno operacijo signal.

Semaforji so zelo primitivni in z njimi težko izrazimo zelo kompleksne konkurenčne probleme. Tako si težko zapomnimo, kateri ščiteni strukturi smo priredili dani semafor. Mimogrede pozabimo uporabiti kakšno instrukcijo wait in prezgodaj vstopimo v kritično sekcijo. Procesi lahko tudi ostanejo neomejeno blokirani, ker (morda zaman) čakajo na odrešilno operacijo signal, ki bi jo moral uporabiti nek drug proces.

MonitorjiS semaforji so podobne programerske težave, kot s stavki "goto" ali s kazalci. Sicer delujejo, vendar je možnosti za napačno rabo veliko.

Poglejmo primere, ki vodijo v smrtni objem:

    V(S);    kriticnaSekcija(); V(S)        P(S); kriticnaSekcija(); P(S)

Ali tako gneznednje, ki prav tako vodi v smerni objem:

     P1: P(Q); P(S); ... V(S); V(Q);     P2: P(S); P(Q); ... V(Q); V(S);

Tveganje zaradi morebitne napačne uporabe semaforjev je veliko. Uvedli so zato monitorje. Ti so konkurenčni konstrukti (lahko tudi objekti), ki imajo vgrajene mehanizme za ekskluzivni dostop. Vsebujejo tako podatke kot procedure (tudi več procedur), ki omogočajo alokacijo skupnega sredstva (na primer nekega medpomnilnika, "bufferja"). Definirani so na nivoju jezika in  tako onemogočajo nepravilno kodiranje.

16

Page 17: Handout Os 2

Vstop v monitor doseže proces s klicem ustreznega monitorskega vhoda (monitor entry). Taki klici so podobni klicem funkcij ali procedur. Istočasno lahko vstopa v monitor le en proces (ali nit), ostali morajo počakati.

Čakanje procesov poteka izven monitorja (v ustrezni čakalni vrsti).

Podatki, ki so znotraj monitorja, so skriti vsem ostalim procesom. Sama implementacija monitorja mora preprečevati, da je v njem aktiven več kot en proces!! Zato je vsakemu monitorju prirejen en semafor. Vklučitev ustreznih operacij wait in signal je stvar prevajalnika, ne programerja, ki monitorje uporablja. Tako imamo zagotovljeno medsebojno izobčenje (mutual exclusion). To pa ni dovolj za sinhronizacijo pri konkurenčnih procesih. Tako lahko morda želimo uporabiti nek podatek (na primer "buffer"), ki še ni definiran. Četudi smo že "v monitorju", moramo počakati. Uvedli so zato dodaten pojem pogojne spremenljivke (condition variable). Operaciji na taki, pogojni spremenljivki sta prav tako operaciji wait in signal, podobno kot pri semaforjih.

Če nek proces želi alociranje nekega sredstva, ki je že zasedeno, kliče monitor proceduro wait.

Ko proces, ki zaseda neko sredstvo, želi le-tega vrniti, spet pokliče monitor za ta poseg. Monitor s pomočjo procedure signal nato omogoči dostop do sredstva naslednjemu procesu iz čakalne vrste. 

Primer:

Preprosto dodeljevanje (allocation) sredstev (resources) z monitorji:

Imejmo več procesov, ki kandidirajo za isto sredstvo, hkrati pa lahko to sredstvo uporablja le en proces. Preprost monitor, ki bi omogočal dodeljevanje in sproščanje tega sredstva, bi lahko imel obliko:

monitor allocResource;var zaseden:boolean;    prost: condition;

17

Page 18: Handout Os 2

procedure getResource;begin  if zaseden then wait(prost);  zaseden:=TRUE;end;

procedure returnResource;begin  zaseden:=FALSE;  signal(prost);end;begin  zaseden:=FALSE;end;

Zgled bi morali dopolniti še z definicijo dveh ali več procesov (na primer procesA, procesB, procesC,..), ki bi v svojem telesu uporabljali klice procedur getResource in returnResource.

Monitorji in problem krožnega medpomnilnika

Naslednji tipičen zgled, primeren za uporabo monitorjev, je primer krožnega medpomnilnika. Oglejmo si torej tehniko komunikacije preko krožnega medpomnilnika in z uporabo monitorjev. Krožni medpomnilnik (ringBuffer) naj vsebuje N elementov namišljenega tipa "data".

monitor ringBuffer;var Buffer: array[0..N-1] of data;    numUsed, nextFree, nextToUse: 0..N-1;    nonempty, nonfull: condition;

procedure putData(value:data);   begin      if numUsed= N then wait(nonfull);      Buffer[nextFree]:= value;      numUsed:= numUsed+1;      nextFree:= (nextFree + 1) mod N;      signal(nonempty);   end;    procedure getData(var value:data);   begin      if numUsed=0 then  wait(nonempty);      value:= Buffer[nextToUse];      numUsed:=numUsed-1;      nextToUse:= (nextToUse + 1) mod N;      signal(nonfull);   end;

begin   numUsed:=0; nextFree:=0; nextToUse:=0;end;

18

Page 19: Handout Os 2

Monitorji in problem Bralci - pisalci

Končno si oglejmo uporabnost monitorjev pri problemu bralci - pisalci. Več procesov- bralcev bere podatke, ki jih več procesov- pisalcev zapisuje. Ta problem srečamo na primer pri sistemih za delo s podatkovnimi bazami.

Velja, da

lahko ima istočasno dostop do skupnega podatka več bralcev, je v danem trenutku lahko aktiven kvečjemu le en pisalec, ne sme biti istočasno aktiven pisalec in en ali več bralcev.

Poglejmo si listanje programske rešitve problema z monitorji:

monitor readersWriters;var   readers:integer;   someonewriting:boolean;   readingAllowed,writingAllowed:condition;

procedure beginReading;   begin      if someoneWriting or queue(writingAllowed)         then wait(readingAllowed);         readers:=readers+1;         signal(readingAllowed);   end;procedure finishedReading;   begin      readers:=readers-1;      if readers=0 then signal (writingAllowed);   end;

procedure beginWriting;   begin      if readers>0 or someoneWriting         then wait(writingAllowed);      someoneWriting:=TRUE;   end;

procedure finishedWriting;   begin      someoneWriting:=FALSE;      if queue(readingAllowed)         then signal(readingAllowed)         else signal(writingAllowed);   end;

begin   readers:=0; someoneWriting:=FALSE;end;

19

Page 20: Handout Os 2

Zmenki

Osnovni koncepti

Naslednja tehnika, ki naj zagotovi medsebojno sinhronizacijo, je tehnika zmenkov, ki so jo najprej uvedli v programskem jeziku ADA. Srečamo se s pojmoma strežnik in klijent (kličoči in servisni proces). V razliko od monitorjev je to aktiven mehanizem. Tudi strežnik je namreč aktiven proces, ne le neka pasivna procedura. Servisni proces vsebuje več takoimenovanih vhodov (entry), ki jim ustrezajo stavki "accept". Take vhode pa lahko kliče proces, ki potrebuje zmenek s servisnim programom. Ne pozabimo, da je tudi strežnik proces, ki "živi". Če pride strežnik do nekega stavka "accept", tu počaka, da bo nek paralelni proces zahteval zmenek pri tem vhodu. Če pa nek paralelni proces kliče vhod strežnika, ko ta še ni prišel do stavka "accept", mora prav tako počakati.

Ko pride do zmenka, klicoči proces posreduje strežniku morebitne parametre in počaka, da strežnik izvede stavke znotraj telesa "accept". Strežnik še posreduje klicočemu programu morebitne rezultate in zmenek je končan. Oba procesa se nato odvijata naprej neodvisno.

Zanimivo je, da morajo klicoči programski procesi poznati vstopne točke v strežnik, slednji pa lahko "servisira" klic kateregakoli klicočega procesa (takih procesov pa je lahko tudi več). V tem smislu je tehnika zmenkov asimetrična.

Zmenki in problem proizvajalec - porabnik

Demonstracijski primer spet obravnava problem proizvajalec- porabnik. Komunikacija med procesom- proizvajalcem in procesom- porabnikom tu poteka posredno preko strežnega procesa. Proizvajalec pošilja zaporedje znakov ASCII, ki jih nato porabnik prevzema. To tehniko lahko praktično uporabimo pri programiranju komunikacije računalnika z nekim terminalom ali oddaljenim računalnikom. Primer predstavlja izvleček iz programa, kodiranega v Adi. Posameznim programskim procesom ustrezajo posli (tasks). Imamo strežni posel simpleBuffer in dva posla - klijenta: consumer in producer. Posel producer generira znake, posel consumer jih sprejema. Sinhronizirana komunikacija poteka preko strežnega posla simpleBuffer.

task simpleBuffer is  entry write(ch:in character);  entry read(ch:out character);end simpleBuffer;   task body simpleBuffer is      char:character;   begin      loop         accept write(ch:in character); do            char:=ch;         end write;         accept read(ch:out character); do            ch:=char;         end read;      end loop;

20

Page 21: Handout Os 2

- - - - - - - - - - - - - -  -task producer;          task body    producer is c1:character;       begin                 -- loop                   -- produce c1;                 simpleBuffer.write(c1);                 -- end loop       end producer; - - - - - - - - -    - - - - - - -task consumer;          task body    consumer is c2:character;       begin                -- loop               simpleBuffer.read(c2);                   -- use c2;             -- end loop       end consumer;

Praktično implementacijo ideje zmenkov zasledimo tudi pri danes običajnem medprocesnem komuniciranju s pomočjo vtičnic (sockets). Najprej so to tehniko uvedli pri BSD verziji UNIX, kasneje pa so jo osvojila tudi druga okolja za podporo porazdeljenih računalniških sistemov, med njimi tudi Java.

Kanali in sporočila

Kanali

Smisel kanala je, da zagotovi informacijski cevovod med dvema procesoma. Oba procesa potekata asinhrono, in nimata skupnega podatkovnega prostora. Zato mora sistem predvidevati tudi pomnjenje prenašanih podatkov (buffering). Prenašana informacija je normalno posredovana v nekem fiksnem podatkovnem formatu. Ta normalno vsebuje identifikacijske podatke (kot je na primer ime procesa - pošiljatelja). Poleg tega vsebuje še podatke ali pa vsaj kazalec na podatke.

Zelo pogosto so kanali implementirani kot vrste tipa FIFO. Podatek, ki ga posredujemo v kanal, bo prvi, ki ga bomo iz kanala prevzeli. Primer take vrste prikazuje slika.

21

Page 22: Handout Os 2

Sporočila

Vrste s sporočili niso nujno tipa FIFO. Posamezna sporočila namreč lahko imajo tudi različno prednost.

Proces- prejemnik jemlje sporočila z začetka take vrste, Proces- pošiljatelj pa vpisuje sporočila na konec vrste. Ker so to običajno dinamične podatkovne strukture, mora normalno najprej zaprositi operacijski sistem, da mu dodeli prostor za novo sporočilo. Glede na to lahko pride tudi do zasičenja sistema. Take situacije moramo preprečiti, lahko tudi tako, da dobi obdelava pretirano dolgih vrst večjo prednost v računalniškem sistemu.

Tak koncept komunikacije je izvedljiv tudi v porazdeljenem, večprocesorskem okolju.  

Porazdeljeni sistemi

S pojavom predvsem lokalnih računalniških mrež so se pojavile tendence po vzpostavitvi računalniškega sistema, ki bi lahko izkoriščal večje število CPE, ki jih povezujejo hitra omrežja. Programska oprema takega, decentraliziranega sistema pa je nujno drugačna. Lahko predstavlja mehko povezavo med sistemi (loosely coupled software), ki dopušča praktično avtonomno delovanje posameznih računalnikov, povezanih v mrežo. Na drugem ekstremu pa imamo tesno sklopljene multiprocesorske sisteme.

Med mrežnimi operacijskimi sistemi je zelo poznan Sunov sistem NFS (Network File System), ki pa danes podpira tudi druge, heterogene sisteme. Osnovna ideja NFS je, da dovoli izbrani množici odjemalcev in strežnikov uporabo skupnega datotečnega sistema. Odjemalci in strežniki so normalno v sklopu iste lokalne mreže, ni pa to nujno. Strežniki dovolijo odjemalcem dostop do direktorijev, če se ti nanje navežejo (montirajo).

NFS zagotavlja podporo heterogenim računalniškim sistemom z definicijo dveh protokolov odjemalec-strežnik. Prvi protokol definira montiranje, drugi pa je namenjen dostopu do direktorijev in datotek.

22

Page 23: Handout Os 2

Naslednja stopnja v razvoju porazdeljenih operacijskih sistemov je bil koncept, ki naj uporabniku (še vedno enake aparaturne infrastrukture) ustvarja iluzijo, da dela pravzaprav za enim sistemom (virtual uniprocesor). To je zahtevalo predvsem predelavo sistemskih klicev. Jedra posameznih računalnikov morajo sodelovati, pri čemer mora vsako jedro še vedno skrbeti za lokalne vire (upravljanje s pomnilnikom ipd).

Pri načrtovanju porazdeljenih sistemov je bilo potrebno najti odgovore na naslednja vprašanja:  

Transparentnost: Uporabnik ne ve, kje so locirani viri, ne ve, koliko kopij obstaja, Več uporabnikov morda uporablja iste vire, Aktivnosti se lahko dogajajo paralelno.

Fleksibilnost: Preprosto dodajanje in spreminjanje porazdeljenega sistema. Zanesljivost  Učinkovitost

Uvedli so pojem mikro-jedra (microkernel), ki je bolj fleksibilno, saj ne dela skoraj nič;. Prepuščeni so mu le nekateri najbolj osnovni servisi:

Medprocesna komunikacija,   Delno opravljanje s pomnilnikom,   Delno upravljanje s procesi,   Nizkonivojske vhodno-izhodne operacije

Ostale storitve, kot je na primer upravljanje z datoteč;nim sistemom, so prepuščene ustreznim strežnikom, kot to ponazoruje naslednja slika:

Splošno vodilo pri gradnji porazdeljenih operacijskih sistemov je tudi uporaba porazdeljenih podatkovnih struktur (na primer raznih tabel). Tudi algoritmi morajo biti decentralizirani. To pa pomeni, da:

Noben računalnik nima popolne informacije o stanju celotnega sistema,

23

Page 24: Handout Os 2

Računalniki sprejemajo odločitve na osnovi lokalnih informacij, Izpad enega stroja ne blokira algoritma Ni globalne "ure" (takta) in s tem sinhronizacije.

Komunikacija v porazdeljenih sistemih

Klic oddaljenih procedur

Pri uvedbi pojma klica oddaljenih procedur (RPC, remote procedure call) je potrebno predvsem razumeti delovanje klasičnih sistemskih klicev. Za primer vzemimo sistemski klic read( ), ki ima naslednjo splošno obliko:

count = read (fd, buffer, numBytes);

Kot je znano, pri takem klicu naloži kličoča funkcija parametre na sklad, vključno s povratnim naslovom (return address). Če so parametri kazalci, pomeni, da bo klicana funkcija spreminjala podatke naslovnem prostoru kličoče funkcije (oziroma programskega procesa). Pri povratku iz klicane funkcije se kličoča funkcija lahko nadaljuje zaradi restavracije povratnega naslova, ki je bil na skladu. Vse se dogaja v istem naslovnem prostoru danega procesa. To pa ne more veljati v primeru, ko so klicane funkcije locirane na drugem računalniku. Želimo pa, da so tudi taki klici čimbolj podobni klasičnim. Uporabimo lahko idejo "klica oddaljene procedure" (RPC), ki je ponazorjena s spodnjo sliko:

24

Page 25: Handout Os 2

Vzemimo za primer klic oddaljene funkcije read( ). Pri centraliziranih sistemih bi klic potekal v okviru istega procesa in s tem istega naslovnega prostora. Pri decentraliziranem sistemu potrebujemo na oddaljenem računalniku dodaten proces, strežnik. Oddaljena procedura read( ) bo delovala v naslovnem prostoru strežnika. V naslovnem prostoru kličočega procesa (odjemalca) moramo imeti na voljo malo drugačno proceduro, ki ji rečemo štrcelj odjemalca (client stub), ki igra vlogo nekakąnega vmesnika. Analogno proceduro, štrcelj strežnika (server stub) imamo na strani strežnika. Oddaljen klic procedure poteka nato na naslednji način:

Proces-odjemalec pokliče svoj štrcelj na normalni način (prenos parametrov in povratnega naslova na lastni sklad).

Štrcelj odjemalca formira obvestilo (message) tako, da vanj pakira parametre in s primernim sistemskim klicem pokliče jedro.

Jedro pošlje obvestilo oddaljenemu jedru. Oddaljeno jedro posreduje obvestilo štrclju strežnika. Štrcelj strežnika razpakira parametre v sprejetem obvestilu in kliče strežnik. Strežnik opravi zahtevano nalogo in vrne rezultat svojemu štrclju. Štrcelj strežnika zapakira rezultate v obvestilo in s sistemskim klicom pade v

(svoje, oddaljeno) jedro. Oddaljeno jedro posreduje obvestilo z rezultati jedru odjemalca. Jedro odjemalca pošlje obvestilo štrclju odjemalca. Štrcelj odjemalca razpakira rezultat in ga vrne odjemalcu.

Pakiranju parametrov v obvestilo pravijo po angleško marshalling (urejanje, pakiranje), obratni operaciji pa unmarshalling (razpakiranje).

Niti, nitkanje

Zamislimo si, da mora biti na primer nek datotečni strežni proces blokiran zaradi čakanja na disk. Če bi tak strežni proces imel več niti, bi med spanjem ene niti lahko potekala druga. Propustnost sistema bi bila večja. Tega ne moremo doseči z dvema (ali več) strežnima procesoma, ker si morata deliti isti medpomnilnik (v istem naslovnem prostoru). Uvedli so torej nov mehanizem.

Imejmo računalnik z nekaj procesi. Vsak proces si lasti programski števec in delovne registre, ima svoj sklad, ima svoj naslovni prostor. Taki procesi bi lahko medsebojno komunicirali le s pomočjo primitivnih medprocesnih mehanizmov. Uvedimo pojem "peresno lahkih" procesov, ki jim pravimo niti. Vsaka ima še vedno "svoje" delovne registre in svoj sklad, kar zadošča za informacijo o statusu takega mini-procesa.

Uporabljajo pa take niti isti naslovni prostor in s tem tudi iste globalne spremenljivke.

Medsebojne zaščite med nitmi ni, saj praviloma pripadajo vse take niti istemu "uporabniku" oziroma procesu.

25

Page 26: Handout Os 2

Niti si zato delijo tudi vse odprte datoteke, signale, semaforje in celo otroke, ki jih je generiral proces (lahko pa imajo tudi svoje otroke). Lastno vsaki niti je tudi njeno stanje, ki je lahko tekoče, blokirano, pripravljeno ali zaključeno (running, blocked, ready, terminated).

Niti tako omogočajo kombinacijo paralelnosti v sicer sekvenčnem izvajanju (in blokiranju) procesov v sistemskih klicih.

Organizacija sodelovanja niti je lahko različna, kot to ponazorujejo naslednje slike:  

V prvem primeru je ena nit dodeljevalec, ki izbere prosto (neblokirano) nit-izvajalca. Takega izvajalca zbudi. Ta nato pogleda, ali lahko izvede zahtevek..

Če ga ne more (na primer pri datotečnem strežniku morda mora počakati na dostop na disk), zaspi, razvrščevalnik pa sproži kakšno drugo nit, morda dodeljevalnik, ki pogleda, ali obstaja še kakšen zahtevek. Izkaže se, da je tak pristop učinkovit predvsem pri implementaciji namenskih strežnikov (na primer datotečnih strežnikov) na enem namenskem računalniku

V primeru teamske

26

Page 27: Handout Os 2

organizacije niti nimamo niti-dodeljevalca. Vsaka nit zase išče zahtevke. Tak sistem je predvsem smiseln, če so naloge posameznih niti specializirane.

Tu se lahko zgodi, da pride zahtevek do niti, ki ni sposobna izvesti naloge. Pred vsako nitjo se tako vzpostavi "čakalna vrsta" z nerešenimi nalogami, ki jo mora vsaka nit prej izprazniti, preden gre gledat v "nabiralnik zahtevkov". 

Tretji model organizacije niti je po principu cevovoda. Take organizacije ne moremo uporabljati na primer pri datotečnih strežnikih, pride pa v poštev tam, kjer imamo problematiko tipa proizvajalec-porabnik.

Koncept niti lahko uporabljajo tudi klijenti, ki želijo sodelovanje z več strežniki. Niti so pripravne tudi za procese, ki obravnavajo signale ali morda aparaturne prekinitvene zahtevke.

Končno omenimo še možnost, da pri večprocesorskih sistemih niti dejansko potekajo paralelno v istem naslovnem prostoru. (Slika kaže niti v sistemu Solaris).

27

Page 28: Handout Os 2

 

Implementacija niti

Uporabniku morajo biti na voljo primerni primitivi (na primer funkcijski klici) za delo z nitmi. Niti lahko realiziramo statično ali dinamično. V prvem primeru je število niti v nekem procesu določeno v fazi prevajanja. Vsaki niti je določen ločen sklad. Tak pristop je preprost a nefleksibilen. V drugem primeru niti nastajajo in se ukinjajo med izvajanjem programa. S primernim klicem definiramo tako glavni program niti (kazalec na primerno proceduro), kot tudi prostor za sklad, njeno prioriteto razvrščanja itd.

Ker niti delujejo na istih (skupnih) podatkih, se poraja problem kritičnih sekcij. Uporabimo lahko tehniko mutex ali pa sinhronizacijo s pomočjo pogojnih spremenljivk. Muteksi so pravzaprav binarni semaforji z dvema stanjema ((ne)zaklenjen). Pogojne spremenljivke pa so podobne pogojnim spremenljivkam za sinhronizacijo monitorjev. Ključna razlika med obema principoma je, da so muteksi bolj primerni za kratkotrajno zaklepanje, pogojne spremenljivke pa za dolgotrajna čakanja na sprostitev vira.

Primerni paket za delo z nitmi (thread package) je lahko implementiran v uporabniškem ali v sistemskem prostoru. Oboje ponazoruje naslednja slika:

28

Page 29: Handout Os 2

V prvem primeru jedro nič ne ve o nitih, še vedno upravlja enostavne, eno-nitne procese. Tak pristop je primeren predvsem za implementacijo na sistemih, ki nitkanja ne poznajo (primer starejše verzije UNIX). Niti tečejo nad posebnim modulom "run time", ki je pravzaprav zbirka procedur za rokovanje z nitmi. Preklop med nitmi je že na uporabniškem nivoju, kar je vsaj za razred hitrejše, kot če bi bil potreben prehod na nivo jedra. Dodatna prednost tega koncepta je, da ima vsak proces svoj algoritem razvrščanja procedur.

Po drugem principu upravlja z nitmi jedro. Zato ne potrebujemo modula "run-time". Tabele za delo z nitmi se nahajajo v jedru. Preklop med nitmi je precej bolj zahteven, saj blokiranje neke niti dosežemo le z bolj zahtevnim sistemskim klicem. Zato pa lahko jedro izbere za nadaljevanje poljubno nit (ne nujno od istega procesa). Implementacija paketov za delo z nitmi na uporabniškem nivoju je sicer bolj učinkovita, ima pa druge probleme. Nit v uporabniškem prostoru ne bi smela uporabljati sistemskih klicev, saj to povzroči zaustavitev vseh niti danega procesa. Druga slabost tega pristopa je tudi, da je delo drugih niti (v istem procesu) pogojeno s "prostovoljnim" preklopom trenutno izbrane niti (podobno kot pri korutinah). Če niti krmili jedro, je enakopravnost vseh niti zagotovljena z razvrščevalnikom.  

Niti in Java

29

Page 30: Handout Os 2

Niti v Javi in njihova stanja

Upravljanje s primarnim pomnilnikom

Asociacija naslovov

Programi so normalno shranjeni na nekem disku v binarni izvršljivi obliki. Pred izvedbo ustreznega procesa morajo biti (vsaj deloma) naloženi v pomnilnik računalnika. Skupina procesov, ki čaka na prepis v pomnilnik, tvori nekakšno čakalno vrsto.

Večina sistemov omogoča, da procesi leže kjerkoli v fizičnem pomnilniku. Čeprav se naslovni prostor računalnikovega pomnilnika začenja z naslovom 00000, je normalno prvi naslov uporabniškega procesa drugače alociran. Preden postane nek program izvršljiv, mora preiti več korakov. Naslovi v programu so pri tem različno (v začetku lahko povsem simbolično) predstavljeni. Ti naslovi se nato transformirajo običajno v relativne naslove (relocatable addresses). Tako kodiran program je premestljiv glede na fizični pomnilnik. Program z absolutnimi naslovi ni tako fleksibilen.

Tipično lahko pride do asociacije (binding) naslovov programskih instrukcij in podatkov s pomnilniškimi naslovi v enem od naslednjih korakov:

Čas prevajanja (compile time): Absolutno programsko kodo tvorimo le, če vnaprej vemo, kje v pomnilniku bo moral ležati program oziroma njegovi podatki. Če želimo kasneje spremeniti lokacijo programa, ga moramo ponovno prevesti.

Čas nalaganja (load time): Prevajalnik je moral tvoriti relativno (premestljivo) programsko kodo. Če se spremeni začetni naslov, moramo program ponovno naložiti.

Čas izvajanja (execution time): Proces lahko premikamo iz enega v drug pomnilniški segment celo med izvajanjem. Asociacijo naslovov v času izvajanja programa omogoča aparaturna oprema.

Naslovu, ki ga glede na programski proces pripravi CPE računalnika, pravimo logični naslov. Naslov, kot ga vidi pomnilnik, pa je fizični naslov. Pri asociaciji naslovov v času

30

Page 31: Handout Os 2

prevajanja in času nalaganja so logični naslovi enaki fizičnim, pri asociaciji v času izvajanja pa se ti naslovi običajno razlikujejo. Logičnemu naslovu tedaj pravimo tudi virtualni naslov.

Dinamično nalaganje in povezovanje

Dinamično nalaganje programov zagotavlja boljše izkoriščanje pomnilnika. Neko rutino naložimo v pomnilnik šele, ko jo potrebujemo. Prednost takega koncepta je, da programske module, ki jih ne potrebujemo, niti ne naložimo v pomnilnik.

Koncept dinamičnega povezovanja (dynamic linking) je podoben dinamičnemu nalaganju. Namesto, da prestavimo v čas izvajanja nalaganje, prestavimo v ta čas kar povezovanje (na primer knjižnic). Zato binarna (izvršljiva) kopija programa ne potrebuje že navezanih sistemskih rutin. Binarni zapisi programov na disku so zato krajši. Namesto potrebnih sistemskih rutin imajo taki zapisi le ustrezne štrclje (stubs). Tak štrcelj je kratek košček programske kode, s katero proces locira zahtevano rutino v pomnilniku (če se ta že nahaja v pomnilniku), po potrebi pa zahteva njeno nalaganje s knjižnice na disku. Ta koncept tudi omogoča, da vsi procesi uporabljajo isto kopijo sistemske rutine v pomnilniku.

Dinamično povezovanje (sistemskih) knjižnic ima še eno prednost. Ko dobimo novo verzijo takih knjižnic, ni nujna ponovna predelava (povezovanje) uporabniških programov, saj bodo avtomatsko uporabljali novo verzijo. Da pa ne pride do nekompatibilne uporabe novih verzij zagotavlja informacija o zahtevani verziji, ki se nahaja tako v štrclju kot v knjižnici rutin. Starejši programi bodo pač še vedno uporabljali starejše verzije knjižnic. Takemu sistemu pravimo sistem skupnih knjižnic (shared libraries).

Zamenjava (swapping)

Pri alociranju primarnega pomnilnika sistem skrbi po eni strani za souporabo pomnilnika (shared memory) in za zaščito privatnih naslovnih področij. Servis alociranja pomnilnika skrbi tudi za mehanizem prepisovanja procesa na sekundarni pomnilnik. Pri tem lahko uporablja tehniko ostranjevanja (paging) ali pa prepisovanja celotne slike procesa s primarnega na sekundarni pomnilnik in obratno (swapping).

Virtualni pomnilnik

Koncept virtualnega pomnilnika temelji na dejstvu, da normalno ne potrebujemo celotnega programa v primarnem pomnilniku. Virtualni pomnilnik tako temelji na abstrakciji uporabniškega logičnega pomnilniškega prostora (ki je lahko velik) od fizičnega pomnilnika (ki je normalno precej manjši). Programiranje je zato bolj preprosto, programi so lahko precej bolj obsežni.

Ne bomo se spuščali v same tehnike ostranjevanja pomnilnika. Navedimo le algoritme, ki jih lahko uporabljamo pri odločitvah o zamenjavi strani:

31

Page 32: Handout Os 2

Naključna zamenjava strani

V zalogi strani naključno izberemo eno in jo nadomestimo z novo. Ta algoritem jemljimo le kot referenco za ostale. Kasneje bomo spoznali, da je to najslabša možnost.

 

FIFO algoritem: 

Je najbolj preprost. Ko potrebujemo novo stran, izberemo v ta namen tisto ki je "najstarejša". Ta algoritem ni nujno najbolj optimalen. Tako lahko res zamenjamo stran, v kateri je tekel nek inicializacijski (in ne več potreben) modul. Lahko pa je v njej neka pogosto uporabljana podatkovna struktura.

32

Page 33: Handout Os 2

Optimalni algoritem: 

Naj bi zamenjal tisto stran, ki povzroča najmanj izpadov strani (page faults). V praksi pa ga ne moremo implementirati, saj ne moremo vnaprej poznati, katere strani bomo potrebovali.

 

LRU algoritem:

Je približek optimalnega algoritma. Za vsako stran vodimo evidenco, kdaj je bila nazadnje uporabljena. Ko potrebujemo novo stran, jo zamenjamo s tisto, ki je že najdlje nismo uporabili (Least Recently Used).

33

Page 34: Handout Os 2

     

Pogosto si pri tem pomagamo s takoimenovanim referenčnim bitom (za vsako stran), ki se nastavi ob vsakem naslavljanju te strani, sistem pa ga periodično resetira. 

Poznamo več izpeljank tega algoritma. Ena od njih je urni algoritem, ko ciklično gledamo strani. Če ima opazovana stran  referenčni bit (pravimo tudi umazani bit) enak 0, jo zamenjamo, sicer ne. 

Števni algoritmi:

Temeljijo na tem, da za vsako stran štejemo število referenc te strani (v danem časovnem intervalu). Imamo lahko več strategij. Tako imamo lahko za kriterij, da zamenjamo tisto stran, ki je bila najmanj pogosto uporabljena (LFU, Least Frequently Used). Argument za tako izbiro je, da so najbolj aktivne strani tiste z največ referencami. Inverzen je algoritem MFU (Most Frequently Used), ki pravi, da take strani ne smemo (takoj) zamenjati, saj morda še nima dovolj referenc, ker je bila vstavljena pred kratkim.

Krmiljenje bremena (Load control)

34

Page 35: Handout Os 2

Odločiti se moramo, koliko procesov naj v danem trenutku sploh konkurira za strani. Če jih vzamemo preveč, bo prevečkrat prišlo do napake strani. Če jih je premalo, je pomnilnik slabo izkoriščen.

Kot kriterij obremenitve je bolje, če opazujemo število napak strani kot pa obremenitev CPE. 

Opazujemo lahko tudi, koliko časa procesi čakajo na strani v pomnilniku. 

Sekundarni pomnilnikDisk je najbolj pogost sekundarni pomnilni medij. Kljub njegovi velikosti je optimizacija njegovega prostora zelo pomembna. Diskovne bloke lahko alociramo datotekam na tri različne načine:

Zaporedno alociranje Povezano alociranje Indeksirano alociranje

Zaporedno alociranje (Contiguous Allocation):

Pri tej metodi pomnimo podatke datoteke v linearno zaporedje blokov na disku. Datotečni direktorij mora za vsako datoteko vsebovati ime datoteke, številko začetnega bloka in dolžino datoteke.

35

Page 36: Handout Os 2

Prednosti: Enostavna implementacija Tako linearen kot sekvenčni dostop do podatkov sta enako preprosta.

Slabosti: Širjenje datotek ni enostavno. Tvegamo zunanjo fragmentacijo. Problem fragmentacije lahko rešujemo z zgoščevanjem, ki pa je časovno potratno. Jedro bi moralo alocirati in rezervirati zaporedne lokacije na disku že ob prvi

tvorbi datoteke.

Povezano alociranje (Linked Allocation):

Pri tej metodi so podatkovni bloki datoteke razpršeni po disku. Direktorij datoteke vsebuje ime datoteke in številko začetnega bloka. Vsak podatkovni blok pa porabi nekaj bajtov za kazalec na naslednji blok. Kazalec v zadnjem bloku ima posebno vrednost EOF (End Of File).

  Prednosti:

Ni zunanje fragmentacije. Uporabimo lahko katerikoli prosti blok.

36

Page 37: Handout Os 2

Datoteko lahko širimo tudi kasneje in ni potrebno deklarirati velikosti datoteke že ob njeni tvorbi.

Zgoščevanje diska ni potrebno.

Slabosti: Direkten dostop je zelo neučinkovit. Kazalci porabijo nekaj prostora v podatkovnih blokih. Razpršenost kazalcev po disku pomeni določeno nezanesljivost.

Indeksirano alociranje (Indexed Allocation):

Pri tej metodi alociramo za vsako tvorjeno datoteko indeksni blok. Ta blok vsebuje vse kazalce, ki kažejo na podatkovne bloke. Direktorij vsebuje ime datoteke in številko indeksnega bloka.

 

37

Page 38: Handout Os 2

Prednosti: Z združevanjem vseh kazalcev na enem mestu se zanesljivost poveča. Direktni dostop do podatkov je učinkovit. i-ti kazalec v indeksni tabeli kazalcev

že kaže na i-ti blok datoteke. 

Slabosti: Problem s porabo prostora na disku s kazalci je še večji, saj za vsako datoteko

porabimo cel blok, čeprav bi potrebovali le nekaj kazalcev

Uvod v datotečne sisteme

Atributi datotek

Datoteke so abstraktni podatkovni tipi, pravzaprav logične enote za pomnenje podatkov določenega tipa. Vsako datoteko opredeljujejo atributi, med katerimi tipično zasledimo naslednje:

Ime Tip Lokacija (kazalec na napravo in na lokacijo datoteke na tej napravi) Velikost

38

Page 39: Handout Os 2

Zaščita Čas (tvorbe, zadnje spremembe ali zadnje uporabe) Lastništvo

Operacije nad datotekami

Operacijski sistem normalno nudi na voljo sistemske klice za tvorbo, zapisovanje in branje, premeščanje po datoteki in brisanje datotek.

Tvorba datotek: Sistem mora najti prostor za novo datoteko in uvesti novo datoteko v ustrezno kazalo (direktorij). V kazalu pomnimo prej navedene atribute datoteke.

Zapisovanje: Sistem mora locirati datoteko. Pomniti mora kazalec na mesto bodočega zapisa v datoteko in ta kazalec po vsakem zapisu ustrezno povečati.

Branje: Je podobno zapisovanju. Pri branju in zapisovanju običajno uporabljamo isti kazalec, ki se pri vsaki operaciji ustrezno poveča.

Premeščanje: Temu ustreza datotečna operacija seek. Sam dostop do datoteke je enak kot pri zapisovanju ali branju, vendar tu s primernim sistemskim klicem le premestimo kazalec v datoteko in ne izvedemo nobene vhodno - izhodne operacije.

Odpiranje in zapiranje datotek: Da ne bi pri vsaki operaciji potrebovali zamudnega iskanja oziroma lociranja datoteke, moramo načeloma vsako datoteko najprej s primernim klicem odpreti. V jeziku C imamo v ta namen klic open ( ) . Tak klic tipično vrne kazalec na rubriko v tabeli odprtih datotek. V nadaljnjih datotečnih operacijah nato uporabljamo ta kazalec, kar je precej hitreje kot ponovno iskanje datoteke preko informacij v direktoriju. Ko datoteke ne potrebujemo več, jo z ustreznim sistemskim klicem (na primer close( ) ) zapremo. Pri sodobnih operacijskih sistemih lahko odpre isto datoteko tudi več procesov hkrati. Tipično ima vsak proces svojo tabelo odprtih datotek. V taki tabeli pomnimo tiste podatke o (odprti) datoteki, ki so specifični za dani proces (na primer kazalec na trenutno pozicijo v datoteki). Poleg tega imamo običajno še eno, skupno tabelo vseh odprtih datotek. Tu so vsi ostali podatki o datoteki in še števec, ki pove, kolikokrat je datoteka trenutno odprta. Ta števec se poveča pri vsakem klicu open( ) in zmanjša pri vsakem klicu close( ).

Brisanje datoteke: Sistem mora preko informacij v direktoriju poiskati datoteko, sprostiti njene podatkovne bloke in končno sprostiti tudi rubriko njeno rubriko v direktoriju.

Tipi datotek

 Eno od temeljnih vprašanj je, ali naj operacijski sistem razpozna vrsto datoteke in tako ustrezno ukrepa. Pogosto je tip datoteke razpoznaven iz njenega imena, lahko pa je tip skrit v kakšnem drugem atributu, ki se avtomatsko nastavi ob tvorbi datoteke. Tak atribut lahko uporabimo tudi za implicitno ponovno proženje programa (na primer urejevalnika ali programskega generatorja), ki je tako datoteko pripravil. 

39

Page 40: Handout Os 2

Vrste direktorijev

Datoteke na diskih morajo biti primerno organizirane. V nekaterih primerih je disk razdeljen v več logičnih enot (ponekod na primer particij, ponekod na primer obsegov (volumes) ). Takim logičnim enotam lahko pravimo tudi virtualni diski. Vsak tak virtualen disk mora pomniti informacijo o datotekah, ki so tu spravljene. Tipično so podatki o datotekah podani v obliki simboličnih tabel oziroma direktorijev.

40

Page 41: Handout Os 2

Pri organiziranju takih tabel je potrebno upoštevati operacije, ki pridejo v poštev. Te so:

Iskanje datoteke: Datoteke imajo pridruženo eno ali več simboličnih imen. Iz teh pa moramo priti do podatkovnih blokov.

Tvorba datotek: Dodajanje novih datotek v nek direktorij. Brisanje datoteke iz direktorija Preimenovanje datoteke. V nekaterih primerih pomeni to tudi premestitev imena

datoteke iz enega direktorija v drugega. Prehajanje po datotečnem sistemu: Imeti moramo dostop do vseh direktorijev in

datotek nekega datotečnega sistema.    

Zaradi velikega števila datotek mora datotečni sistem zagotavljati njihovo preglednost. Pogosto imamo zato direktorije organizirane drevesno, kot ilustrira leva slika:

Sodobni datotečni sistemi dopuščajo, da ima ista datoteka po več imen in da so ta v različnih direktorijih. To precej olajša souporabo datotek in direktorijev Imamo bolj splošno organizacijo direktorijev v obliki acikličnega grafa: 

41

Page 42: Handout Os 2

Pri nekaterih operacijskih sistemih (UNIX) dosežemo to tako, da dodajamo na isto datoteko nove simbolične vezi (symbolic links). Pri prehajanju po drevesu direktorijev operacijski sistem simbolične linke ignorira, saj bi lahko prišlo do cikliranja.

Ker je dostop do posameznih datotek tako možen preko več imen, mora biti zaradi konsistence datotečnega sistema brisanje datotek drugače urejeno. Datoteko lahko v resnici zbrišemo šele, ko brišemo zadnjo referenco nanjo. V ta namen imamo na primer pri sistemu UNIX za vsako datoteko števec povezav nanjo.

Porazdeljeni datotečni sistemi

Porazdeljeni datotečni sistem (DFS, distributed file system) je datotečni sistem, pri katerem so njegovi odjemalci, strežniki in pomnilne naprave razpršene po računalnikih porazdeljenega sistema.

Sistem ima lahko tudi več datotečnih strežnikov, ki so lahko med seboj lahko tudi različni. Vse to pa naj bi bilo za uporabnika nevidno oziroma nepomembno.    Cilj porazdeljenega datotečnega sistema: 

Uporabniki fizično ločenih računalnikov naj souporabljajo podatke in pomnilne naprave

42

Page 43: Handout Os 2

Uporabniki naj imajo dostop do oddaljenih datotek tudi iz naprav brez lastnih diskov

Sistem naj bo neodvisen od tipa računalnikov

Lastnosti porazdeljenega datotečnega sistema

Transparentnost:

Transparentnost lokacije: Ime datoteke naj ne ne bo odvisno od lokacije fizičnega pomnilnika. Odjemalci naj uporabljajo za dostop do lokalnih in oddaljenih datotek enake operacije.

Neodvisnost od lokacije: Ime datoteke naj se ne spreminja, če spremenimo lokacijo fizičnega pomnilnika. Govorimo o transparentnosti migracije in o dinamičnem preslikavanju imen datotek. Večina porazdeljenih datotečnih sistemov (vključno z NFS) uporablja statično transparentnost lokacije.

Mobilnost uporabnikov

Uporabnik ni vezan na določen računalnik temveč se lahko najavi na kateremkoli sistemu in uporablja svoje datoteke.

43

Page 44: Handout Os 2

Zmogljivost

Upoštevati moramo:

čas CPE + čas dostopa do diska + čas porabljen z mrežo

Zmogljivost porazdeljenega datotečnega sistema mora biti primerljiva navadnemu datotečnemu sistemu kljub temu, da mora reševati dodatne probleme, kot so: zaklepanje in sinhronizacija ter imenovanje (naming service).  

Toleranca izpadov

Izpadi komunikacije Izpadi računalnikov Okvare pomnilnih naprav Slabšanje pomnilnih medijev

Skalabilnost

Primer porazdeljenega datotečnega sistema: NFS

Strategije razvrščanja dostopov do diskaPropustnost sistema poveča tudi primerna strategija razvrščanja zahtevkov dostopov do diska.

Najbolj preprosta strategija je tipa FCFS (first come first served). Po tej se zahtevki za pomik glave diska obravnavajo v enakem vrstnem redu, v katerem tudi prihajajo. Nedvomno je tak algoritem tudi enako pravičen za vse zahtevke, zanesljivo pa s stališča propustnosti ni optimalen.

Druga strategija bi lahko kot kriterij za izbiro naslednjega zahtevka imela najkrajši pomik glave (in s tem povezan čas pomika). Taki strategiji pravimo SSTF (Shortest Seek Time First). Tak algoritem daje žal prednost notranjim sledem diska, zunanje pa pridejo manjkrat na vrsto. Obstaja celo nevarnost stradanja.

44

Page 45: Handout Os 2

Tretji princip je znan pod imenom SCAN. Glava se premika v dani (preferenčni) smeri in izpolnjuje zahtevke. Tudi tu pridejo zunanje sledi manjkrat na vrsto, kot notranje. Je pa varianca izpolnjevanja zahtevkov bolj stabilna.

Alternativa strategiji SCAN je strategija N-SCAN (Next scan). Pri tej obravnava sistem le tiste zahtevke v preferenčni smeri, ki jih že ima na seznamu, novinci pa morajo počakati naslednji obhod.

Končno imamo tudi strategijo C-SCAN (Circular scan). Pri tem se glava po vsakem obhodu takoj vrne za začetek, ne da bi pri tem pomiku obravnavala zahtevkov. Algoritem je zato do vseh zahtevkov enako pravičen.

Navedene strategije ponazoruje tudi spodnja slika. Predpostavimo, da so v čakalni vrsti zahtevki 1, 2, 3 in 4, zahtevek 5 pa se jim pridruži malo kasneje.    

45

Page 46: Handout Os 2

Vhodno - izhodni podsistem

V sklopu računalniškega sistema je več krmilnikov perifernih naprav (device controllers). Dovolj tipično so ti krmilniki priključeni na skupno vodilo, ki omogoča dostop do pomnilnika. Na posamezen krmilnik je lahko povezanih tudi več naprav. Primer takega krmilnika je SCSI krmilnik. (Small Computer System Interface). Naloga krmilnika je premik podatkov med periferno napravo in lokalnim pomnilnikom.

Za start posamezne vhodno-izhodne operacije mora CPE vpisati ustrezne kode v registre v perifernega krmilnika. Krmilnik nato izvede ustrezno operacijo (običajno prenos) in nato obvesti centralno procesno enoto, da je operacija zaključena. Temu dogodku pravimo prekinitveni zahtevek.

Tako situacijo normalno posredno sproži programski proces, ki zahteva prenos podatkov. Po takem zahtevku lahko program čaka, da se vhodno-izhodna operacija zaključi (sinhrona vhodno-izhodna operacija), ali pa program teče dalje hkrati s potekom vhodno-izhodne operacije. V tem primeru potrebujemo še primeren sistemski klic, ki omogoči procesu, da kasneje počaka na zaključek sprožene vhodno-izhodne operacije.

46

Page 47: Handout Os 2

Sistem mora imeti možnost istočasnega sledenja večjemu številu vhodno-izhodnih zahtevkov. Zato mora imeti tabelo z opisom stanja posameznih naprav (periferna statusna tabela, device status table). V taki tabeli so normalni podani: tip posamezne naprave, njeni naslovi, stanje).

Ko pride do prekinitvenega zahtevka, operacijski sistem ugotovi, katera naprava ga je povzročila, naslovi ustrezni element periferne statusne tabele in ustrezno popravi njegove podatke (status, števce podatkov ipd).   Ko je vhodno-izhodna operacija zaključena, pogleda sistem, kateri proces je čakal na njen zaključek, in ga sprosti za nadaljevanje. Tak način vhodno-izhodnih operacij je asinhron. 

Običajno so vse vhodno-izhodne inštrukcije zaščitene in normalnemu uporabniku prepovedane. Računalnik jih izvaja le, če je v takoimenovanem sistemskem stanju (kernel mode, system mode).

S stališča operacijskega sistema mora biti zagotovljena čim večja neodvisnost od posebnosti posameznih perifernih naprav oziroma njihovih krmilnikov. Zato vhodno-izhodni podsistem običajno sestavljajo naslednji podsklopi:

Ustrezno vmesno polje za pomnenje podatkov (pri sistemu UNIX so to bloki medpomnilnika pri diskih in drugih blokovnih napravah, c-liste pri terminalih in drugih znakovnih napravah),

Splošen vmesnik do gonilnikov perifernih naprav, Gonilniki (drivers) za posamezne vrste perifernih naprav.

Vsaki periferni napravi lahko ustreza poseben gonilnik, če pa je več naprav istega tipa, lahko imamo en gonilnik za vse take naprave (na primer diske). Sistem lahko podpira tudi takoimenovane programske naprave (software devices), katerim ni prirejena nobena fizična periferija. Tako bi lahko na primer obravnavali pomnilniške lokacije, ki so sicer procesu nedostopne.

47

Page 48: Handout Os 2

Gonilniki naprav

Namen gonilnika naprave

Namen gonilnika naprave je rokovanje z zahtevki, ki jih v zvezi z napravo danega tipa posreduje jedro operacijskega sistema.Vmesnik za jedro mora biti dobro definiran in konsistenten. Izoliranje  programske kode, specifične za dano napravo  od jedra  poenostavlja dodajanje novih naprav.    

Tipi gonilnikov naprav

Gonilnik naprave je programski modul, ki je lociran v jedru in predstavlja programski vmesnik do aparaturne naprave. taka naprava je na primer krmilnik diska ali traku ali omrežni krmilnik. Pri sistemu UNIX klasificiramo gonilnike glede na tipe naprav:

Gonilniki blokovnih naprav (Block device drivers)

Gonilniki znakovnih naprav(Character device drivers)

Gonilniki omrežnih naprav (Network device drivers)

Gonilniki lažnih naprav (Pseudodevice drivers)

Kdaj kličemo gonilnik naprave

   

48

Page 49: Handout Os 2

Nekateri zahtevki (na primer za vhodne ali izhodne operacije izhajajo neposredno iz sistemskih klicev v uporabnikovem programu. Nekateri drugi zahtevki, kot na primer konfiguriranje, pa so posledica aktivnosti med zagonom operacijskega sistema.      

Mesto gonilnika (pri UNIX)

Uporabniški program kliče jedro, nikoli pa ne direktno kliče gonilnika. Jedro komunicira s periferno napravo le posredno preko klicev njenega gonilnika. Gonilnik komunicira z napravo tako, da preko vodila (bus) piše v njene registre  ali bere vsebino teh registrov. Krmilnik naprave (device controller) je fizični vmesnik, ki krmili eno ali več naprav (običajno) enakega tipa.

Primer branja enega znaka

Primer predstavlja branje enega znaka s terminala v "surovem" načinu (raw mode).

Slika podaja zaporedje dogodkov od klica v uporabnikovem programu naprej .

Gonilniku je posredovan zahtevek za branje (C-1 do C-3).

49

Page 50: Handout Os 2

Periferija zajame znak (I-4 do I-5).

Pride do prekinitve (I-6).

Rokovalnik prekinitev (interrupt handler) servisira prekinitev (I-7 do I-9).

Uporabniški program dobi vrnjen prebrani znak (C-10 do C-13).

 

50

Page 51: Handout Os 2

   

Bralni zahtevek gonilniku

Uporabniški program pokliče sistemski klic read  (C-1).V sistemskem klicu pride do prenosa treh argumentov: opisnika datoteke(fd), kazalec na mesto,kjer pomnimo znak (buf) in celoštevilčno spremenljivko (vrednost 1), ki pove vmesniku read , koliko bajtov želimo prebrati. Proces  je blokiran v gonilniku, ker je medpomnilnik, kjer naj bi bil znak,prazen.  

Sprejem znaka

Kasneje vtipkamo na primer znak "k" (I-4). Koda znaka je pomnjena v podatkovnem registru naprave (I-5).    

Generiranje prekinitve

Ob vtipkanju znaka se spremeni status krmilnika naprave, ki poąlje procesorju (CPU) prekinitveni zahtevek. Ta sproži rokovalnik prekinitev (I-6). Trenutno tekoči proces je pred tem prekinjen in njegovo stanje shranjeno, da se bo lahko kasneje nadaljeval.    

Rokovalnik prekinitev servisira prekinitev

Rokovalnik prekinitev (včasih mu pravimo tudi prekinitvena servisna rutina) pomni znak v lokacijo, ki jo poznajo tudi ostali moduli gonilnika. Zatem obudi proces, ki je moral zaradi čakanja na znak zaspati. Končno izstopi in pri tem restavrira proces, ki je bil prekinjen ob servisiranju prekinitve.  

Vračamo znak

Ko kasneje razvrščevalnik procesov zbujenemu procesu dovoli nadaljevanje, je brani znak že v ustreznem medpomnilniku. Proces ga premesti v uporabniški naslovni prostor (C-11). Vmesnik read gonilnika naprave vrne nadzor jedru, ta pa uporabniškemu Programu (C-13).  

Povzetek

Zgled poenostavljeno  predstavlja branje znaka. Opazimo, kako uporabniški program terja servis jedra. Vidimo še, da je obravnava prekinitvenih zahtevkov asinhrona glede na druge aktivnosti gonilnika. 

51

Page 52: Handout Os 2

Zaščita in varnost OSZaščita je mehanizem nadzora dostopa programskih procesov ali uporabnikov do resursov računalniškega sistema. Varnost takega sistema je mera zaupanja, da bo ohranjena integriteta sistema in njegovi podatki.

Domena zaščite:

Računalniški sistem je nabor procesov in objektov. Objekti so lahko aparaturni (CPE, pomnilniški segmenti, periferne naprave) ali programski (datoteke, programi, semaforji itd.).

Proces deluje v domeni zaščite (protection domain), ki definira množico objektov in operacij nad njimi, ki so procesu dovoljene. Domena zaščite je lahko uporabnik, nek proces ali celo procedura. Posamezne domene si lahko pravice do dostopa (access rights) tudi delijo.

Asociacija med procesom in domeno je lahko statična ali dinamična. V slednjem primeru lahko proces prehaja iz ene domene zaščite v drugo.

Organizacija zaščite je lahko hierarhična (obročna) (tako je bil organiziran zaščitni sistem pri MULTICS). Kontroliran prehod med domenami nastopi pri prečkanju med obroči.

Bolj učinkovit model zaščite ponuja matrika dostopnosti (Access matrix).

52

Page 53: Handout Os 2

Komentar: Proces, ki se izvaja v domeni D3, ima pravico do branja objekta O2 in izvajanja objekta O3.

Vrste v matriki predstavljajo domene zaščite, kolone pa so posamezni objekti. Pri tvorbi novega objekta enostavno dodamo matriki dostopnosti novo kolono.

Matriki dostopnosti so dodane še kolone, ki določajo dopustne preklope med posameznimi domenami.

Komentar: Proces, ki se izvaja v domeni D2, lahko preide v domeno D3 ali D4. Najbolj preprosta implementacija matrike dostopnosti je z globalno tabelo, ki jo predstavlja urejena množica trojčkov <domena, objekt, pravice> . V tej tabeli iščemo trojček <Di,Oj,Rk>. Če ga najdemo, je operacija dovoljena, sicer pa ne. Slabost take implementacije je v velikosti (razpršenosti) tabele.

Drug način implementacije obravnava vsako kolono matrike kot seznam dostopnosti za en objekt. Prazne elemente lahko izpuščamo. Za vsak objekt dobimo tako urejene pare

<domena, pravice>.

Tretja različica predvideva, da namesto kolon (objektov) gledamo vrstice (domene). Tako dobimo za vsako domeno seznam zmožnosti (capability list). Operacijo na določenem objektu lahko izvedemo v dani domeni, če se v seznamu parov <objekt, pravice> za to domeno nahaja tudi tak par. Tako organizacijo zaščite zasledimo na primer pri sistemu MACH.

Tudi tak seznam je sam po sebi zaščiten objekt.

UNIX uporablja omejeno zaščito, ki se večinoma nanaša le na datoteke. Med sistemi, ki imajo implementiran seznam zmožnosti omenimo Mach. Ta razširja zaščitni mehanizem tudi na objekte, ki jih definira uporabnik.

Varnost sistemov

Medtem, ko je zaščita sistema interni problem operacijskega sistema, vključuje varnost tudi okolje, v katerem deluje. Zagotoviti moramo fizično zaščito sistema ter zaščito pred neavtoriziranimi dostopi, namernimi uničenji podatkov, naključnim vnašanjem nekonsistenc itd..

53

Page 54: Handout Os 2

ŠTUDIJ PRIMERA UNIX/LINUXStruktura operacijskega sistema UNIX

Ob zunanjem (aparaturnem) prekinitvenem zahtevku je dogajanje naslednje: Kontekst trenutno izvajanega procesa se shrani. Sistem ugotovi izvor prekinitvenega zahtevka, S pomočjo posebne podatkovne strukture - prekinitvenega vektorja pokličemo

ustrezno prekinitveno servisno rutino. Restavriramo prekinjeni procesni kontekst (lahko pa tudi s preklopom konteksta

preidemo na nek drug proces.

Sistemski klici so s stališča programerja klici funkcij. Tem posredujemo ob klicu številko sistemskega klica. Ob izstopu iz takega klica pa dobimo število, ki podaja uspešnost klica. Sama dogajanja ob sistemskem klicu so naslednja:

Parametri sistemskega klica se skopirajo v sistemsko področje procesa (u-struktura),

Shrani se kontekst procesa (saj lahko v sistemskem režimu pride do preklopa konteksta)

54

Page 55: Handout Os 2

Izvedemo ustrezno rutino (naslov te rutine dobimo s pomočjo "številke sistemskega klica" v ustrezni tabeli.

(morda pride pri tem do preklopa konteksta (če je na primer trenutni proces blokiran zaradi čakanja na izvedbo neke vhodno/izhodne operacije))

Povrnemo se v uporabniški režim.

Procesi pri sistemu UNIX

Življenje procesa

Proces zaživi, ko v procesu -očetu pride do klica fork( ). Vzemimo primer, ko je tak proces-oče lupina UNIX. Kaj se z obema procesoma dogaja, kaže spodnja slika.  

Proces - otrok najprej "podeduje" kopijo podatkov in programske kode od očeta, vendar nato običajno s klicem execve nadomesti to s svojo podatkovno strukturo in programsko kodo.

Primer fork( ) #include <sys/types.h>#include <sys/wait.h>#include <stdio.h>#include <errno.h>#include <unistd.h>     int main(int argc, char *argv[]){      int status;      int pid;      char *prog_arv[4];      /* Build argument list */      prog_argv[0] = "/usr/local/bin/ls";      prog_argv[1] = "-l";      prog_argv[2] = "/";      prog_argv[3] = NULL;      /*Create a process space for the ls  */      if ((pid=fork()) < 0){        perror ("Fork failed");        exit(errno);      }      if (!pid) {        /* This is the child, so execute the ls */         execvp (prog_argv[0], prog_argv);      }

55

Page 56: Handout Os 2

      if (pid){        /* We're in the parent; let's wait for the child to finish */        waitpid (pid, NULL, 0);      }    }

Stanja procesa

Posamezni programski procesi med svojim "življenjem" spreminjajo svoje stanje. Kaj se s posameznim procesom dogaja od njegovega rojstva (ki ga povzroči sistemski klic fork(), do njegovega zaključka, ponazoruje spodnja slika:    

Vsakemu programskemu procesu ustreza podatkovna struktura, ki vsebuje vse za restavracijo procesa po njegovem ponovnem zapisu (swap in) v pomnilnik. Strukture procesov, ki so pripravljeni za izvedbo (ready to run), so povezane v seznam (the ready queue), ki ga obravnava razvrščevalnik (scheduler).V posamezni procesni strukturi so tudi kazalci na tabele strani (page tables) z naslovi delov procesa, naloženega v pomnilnik, oziroma z naslovi procesa, prepisanega na začasen prostor na disku (swap device).

Struktura procesa:

56

Page 57: Handout Os 2

Virtualni naslovni prostor uporabniąkega procesa je razdeljen v tekstovni segment (programska koda), podatkovni segment in segment s skladom. Ker lahko večinoma tekstovni segment skupno uporablja več procesov (pomislimo na večkratno istočasno uporabo urejevalnika), poznajo taki procesi še posebno strukturo (struktura teksta), v kateri so kazalci na strani s programsko kodo ter števci, koliko procesov rabi to kodo.

Informacijo o procesu, ki jo potrebujemo le, ko teče proces v primarnem pomnilniku, hranimo v posebni "uporabniški" strukturi (u-structure, u-area). To strukturo sme spreminjati le jedro (kernel). Tudi ta struktura se lahko "umakne" na disk. V tej strukturi lahko pomnimo:

vsebine delovnih registrov (potrebno za restavracijo procesa), kopijo parametrov pri sistemskih klicih. opisnike vseh odprtih datotek interne vhodno - izhodne parametre podatek o tekočem direktoriju meje procesa in datotek

Iz spodnje slike je razvidno, katere strukture posameznega procesa so stalno rezidenčne v primarnem pomnilniku, katere pa lahko sistem umika na začasno področje (swap area na disku).

57

Page 58: Handout Os 2

Datotečni sistem UNIX

LINUX podpira sočasno uporabo več vrst  datotečnih sistemov. To transparentnost doseže z uvedbo  "vmesnega, virtualnega sistema VFS (Virtual File System).

Strukture datotečnega sistema UNIX prikazuje spodnja slika. Del teh struktur je rezidenčnih na disku, nekatere pa so v primarnem pomnilniku.

Na posameznem disku imamo več področij. Na začetku je normalno zagonski blok (bootstrap block). Ta vsebuje programsko kodo (zagonski nalagalnik, bootstrap loader), ki jo računalnik bere in nato izvede ob svojem zagonu.     struct ext2_super_block {   unsigned long  s_inodes_count;    unsigned long  s_blocks_count;    unsigned long  s_r_blocks_count;    unsigned long  s_free_blocks_count;   unsigned long  s_free_inodes_count;   unsigned long  s_first_data_block;   unsigned long  s_log_block_size;   long           s_log_frag_size;   unsigned long  s_blocks_per_group;

Temu sledi super-blok, ki določa stanje datotečnega sistema. Pove velikost sistema, koliko datotek lahko pomnimo, kje je še prostor na disku. 

V superbloku so tudi podatki o geometriji diska (število glav, cilindrov,..), glava seznama i-vozlov in seznam prostih blokov. 

58

Page 59: Handout Os 2

  unsigned long  s_frags_per_group;   unsigned long  s_inodes_per_group;   unsigned long  s_mtime;   unsigned long  s_wtime;   unsigned short s_mnt_count;   short          s_max_mnt_count;   unsigned short s_magic;   unsigned short s_state;   unsigned short s_errors;   unsigned short s_pad;   unsigned long  s_lastcheck;   unsigned long  s_checkinterval;   unsigned long  s_reserved[238]; };

Na levi strani je struktura super-bloka za primer operacijskega sistema LINUX 

Sledijo podatki o datotekah. Ti so spet shranjeni v dveh strukturah. Prva je seznam i-vozlov (inode list), Drugo pa predstavlja skupek podatkovnih blokov.    

Podatkovna struktura i-vozel vsebuje podatke o lastništvu in zaščiti datoteke, o času zadnjega dostopa in spremembe datoteke, pa tudi o tem, kje se nahajajo podatkovni bloki datoteke. Kot že rečeno, lahko vsaki datoteki ustreza več imen, ki so z vezmi (links) navezana na datoteko preko i-vozla. Imena datotek so pomnjena v direktorijih, ki so tudi datoteke. 

 

Kako pridemo iz i-vozla do podatkov v sami datoteki. Pri kratkih datotekah imamo direktno naslavljanje podatkovnih

59

Page 60: Handout Os 2

blokov, pri daljših pa indirektno, indirektno-indirektno ali celo preko trojne indirekcije.   

 

Zaradi večje učinkovitosti hrani sistem kopijo i-vozlov tudi v primarnem pomnilniku. Ta kopija ima še nekaj dodatnih informacij in sicer:

Ali je blok zaklenjen, Ali čaka kakšen proces na ta (zaklenjeni) blok, Ali se kopija i-vozla razlikuje od originalnega i-vozla, Logično številko enote, na kateri se nahaja datoteka, Številko i-vozla (originalni i_vozel tega nima, je element polja na disku), Kazalce na ostale pomnilniške (in core) i-vozle, Števec, kolikokrat je dana datoteka v danem trenutku odprta.

Poleg tega ima jedro tu še dva tipa podatkovnih struktur. Za vsak proces formira tabelo opisnikov datotek (User file descriptor table, UFD). Ta tabela vsebuje po en element za vsako datoteko, ki jo proces odpre ali tvori. Vsaka UFD ima najmanj tri elemente, ki ustrezajo standardnemu vhodu, standardnemu izhodu in standardnemu izhodu za obvestila o napakah. Poleg tega vzdržuje sistem še globalno tabelo datotek.

Vloga podatkovnih struktur pri stavku read( )

60

Page 61: Handout Os 2

 

Interna predstavitev datotek

Vsaki datoteki ustreza na disku tudi podatkovna struktura i_vozel. Ta sam po sebi ne vsebuje podatkov o poti (PATH) do datoteke, ki jo uporabniki normalno navajamo. Pri tem si pomagamo z navajanjem direktorija, v katerem se nahaja ime datoteke. Direktorij je tudi datoteka, ki ima tabelarično vsebino. En stolpec so imena datotek, drugi stolpec pa številke njim ustreznih i-vozlov. Prvi dve imeni datotek sta enaki nizu "." oziroma "..", v rubriki i_vozlov pa imata številke i_vozlov tekočega oziroma nadrejenega direktorija.  

Za datoteke, ki jih "zbrišemo", se v direktoriju na ustreznem mestu izniči številka vozla in s tem se zgubi povezava (link) s tem i-vozlom in posredno s podatki v datoteki. V samem i-vozlu se zmanjša števec povezav (links). Šele, ko ta števec pade na nič (ko so torej zbrisana vsa imena, ki kažejo na to datoteko), se sprosti i-vozel, pa tudi sami podatkovni bloki na disku.

Trde vezi

61

Page 62: Handout Os 2

Vsaka datoteka UNIX ima lahko več imen. Vsak element v direktoriju je takoimenovana trda povezava (hard link). 

Vsak i-vozel ima števec trdih povezav. Ta števec se poveča pri uporabi sistemskega klica 

link(obstoječe ime, novo ime)

Števec povezav se zmanjša pri sistemskem klicu

unlink(ime)

Ko pade števec na 0, se podatkovni bloki datoteke sprostijo.

Simbolične povezave

Unix pozna tudi simbolične, mehke povezave (soft links, symbolic links).  Tvorimo jih z ukazom 

symlink(obstoječe ime, novo ime)

Pride do nove datoteke, ki pa ima enako vsebino, kot prvotna.

Študijski primer z datotečnim sistemom

62

Page 63: Handout Os 2

V nadaljevanju bomo spoznavali, kaj se dogaja v računalniku med izvajanjem preprostega programa (dajmo mu ime copy), ki naj omogoča kopiranje datoteke. Koda takega programa je lahko naslednja:

#include <fcntl.h> char polje[1024]; /************************************************************/ void copyFile(int old, int new) {    int count;    while((count= read(old,polje,sizeof(polje))) > 0)       write(new, polje, count); } /************************************************************/ main( int argc, char **argv) {    int fdold, fdnew;    if (argc!= 3){       printf("Uporaba: copy oldfile newfile\n"); exit(1);    }    fdold = open(argv[1],O_RDONLY);    /* Vhodno datoteko odpremo le za branje */    if(fdold== -1){       printf("Ne morem odpreti datoteke %s\n",argv[1]); exit(2);    }    fdnew = creat(argv[2],066);    /* Tvorimo izhodno datoteko z dovoljenji rw */    if(fdnew==-1){       printf("Ne morem tvoriti datoteke %s\n", argv[2]); exit(3);    }    copyFile(fdold, fdnew);/* klicemo funkcijo za kopiranje datoteke */    exit(0); }

Program bi lahko v primeru kopiranja datoteke prog.c v datoteko prog1.c poklicali takole:

copy prog.c prog1.c

V programu nastopa poleg glavne funkcije še podfunkcija copyFile( ), čeprav bi lahko vse skupaj zakodirali krajše. V programu imamo tudi več sistemskih klicev (open( ), creat( ), read( ), write( ), exit( ) ).

63

Page 64: Handout Os 2

Kaj se skriva za sistemskim klicem open( )

Kaj se skriva za sistemskim klicem read ( )

64

Page 65: Handout Os 2

Medpomnilnik (buffer cache)Jedro poizkuša minimizirati frekvenco dostopov do diska tako, da vzdržuje zalogo internih podatkovnih blokov, ki jim pravimo medpomnilnik (buffer cache) Te bloke vzpostavi med zagonom sistema. Medpomnilnik vsebuje podatke diskovnih blokov, ki so bili uporabljeni v bližnji preteklosti (recently used). Ko pride do zahteve za branje podatkov z diska, pogleda jedro najprej, če nima kopije teh podatkov v medpomnilniku. Sistem ima lahko tudi višjenivojske algoritme, ki omogočajo predčasno branje ali zapis podatkov, kar naj bi še povečalo propustnost.

Spomnimo se našega študijskega programa copy. Opisali smo, kaj se skriva za znanim sistemskim klicem read( ) . V nakazanem algoritmu te rutine smo imeli tudi vrstico

65

Page 66: Handout Os 2

Beri podatkovni blok z diska v blok medpomnilnika

Poglejmo si rutino (naj ji bo ime bread( ) (block read)), ki opravi to nalogo:

bread( ) {     /* vhod: stevilka (naslov) bloka na disku */     /* izhod: vrne blok (v medpomnilniku) s podatki */     prevzemi podatkovni blok; /*to bo naredila rutina getblk */     if (podatki v bloku veljavni) return (podatkovni blok);     /* sicer pa se zgodi naslednje...*/     iniciacija branja z diska;     sleep (cakamo na konec I/O operacije z diskom);     return (podatkovni blok); }

Vsak blok v medpomnilniku je pravzaprav sestavljen iz dveh delov: iz polja, ki vsebuje podatke, ter iz zaglavja (header), ki identificira blok, vsebuje pa tudi več kazalcev.

Zaradi lažjega iskanja pomni sistem bloke (pravzaprav njihova zaglavja) v razpršenih seznamih, tako kot to prikazuje spodnja slika. S slike je razvidno še, da so prosti bloki dodatno povezani v seznam prostih blokov.

66

Page 67: Handout Os 2

Ko jedro išče zahtevani blok, najprej pogleda, če je ta že v ustreznem seznamu. Če ga ne najde, poizkusi prevzeti prvi možen blok iz seznama prostih blokov. Tak blok nato uvrsti v (njemu ustrezen) seznam.

Zahtevani blok je nato uporabljen za branje (na primer v sklopu sistemskega klica read()), ali za pisanje (na primer pri klicu write( ) ). Blok, ki naj bi bil zapisan, se ne zapiše takoj. V pričakovanju, da bo kmalu spet uporabljen, se le označi (status) da mora biti prepisan na disk (delayed write). Do samega zapisa pa pride šele, ko res sistem nujno rabi njegovo polje za kakšne druge podatke. Do zapisa vseh tako označenih blokov pride tudi ob zaustavitvi (shutdown) operacijskega sistema.

Oglejmo si še psevdo kodo algoritma za alokacijo podatkovnega bloka (dajmo ji ime getblk( ) ). To naj bi torej bila rutina, ki jo pokliče prej omenjena rutina bread( ).

getblk( ) {     /* vhod: stevilka periferne naprave, stevilka (naslov) bloka */     /* izhod: zaklenjen (zaseden) podatkovni blok, ki ga lahko uporabimo */     while (ne najdemo podatkovnega bloka) {         if (podatkovni blok v ustreznem seznamu ) {             if (podatkovni blok zaseden) {                 sleep (cakamo na sprostitev bloka);                 continue; /* se enkrat zaokrozimo v zanki */             }             zasedemo podatkovni blok; /* zapis v statusu */             umaknemo podatkovni blok iz seznama prostih;             return (podatkovni blok);         }         else {             /* v ustreznem seznamu ni podatkovnega bloka */             if ( na seznamu prostih ni nobenega podatk. bloka ) {                 sleep (cakamo na pod. blok v seznamu prostih);                 continue; 

67

Page 68: Handout Os 2

            }             umaknemo podatkovni blok iz seznama prostih;             if (podat. blok zaznamovan delayed write) {                 asinhroni prepis podatk. bloka z diska;                 continue;             }             umaknemo podatk. blok iz starega seznama;             vstavimo podatk. blok v ustrezni seznam;             return (podatkovni blok);         }     }

Iz podanega algoritma je razvidno, da pride do dejanskega, fizičnega prepisa naslovljenega bloka iz diska v podatkovni blok medpomnilnika (ali obratno) le v skrajnem primeru, ko ne gre drugače. To pa je že problematika nizkonivojskih rutin gonilnikov.

Vhodno - izhodni podsistem UNIX

Pri sistemu UNIX imamo takoimenovane posebne datoteke. Opisniki le-teh kažejo namesto na podatkovne bloke na  ustrezne krmilnike naprav, posredno preko takoimenovane stikalne tabele, ki se, tako kot sam gonilnik, nahaja v jedru.

   

Samo jedro vsebuje pravzaprav dve podatkovni strukturi, ki predstavljata vmesnik proti posameznim gonilnikom. To sta stikalni tabeli blokovnih oziroma znakovnih naprav (device switch tables). Njuno vlogo ponazoruje spodnja slika:

68

Page 69: Handout Os 2

   

UNIX pozna dva tipa naprav: blokovne (diski, trakovi) in znakovne (terminali in podobno). Dostop do naprav je preko datotečnega sistema. Vsaki napravi ustreza ime, podobno imenu datoteke. Kot vemo, pravimo takim "datotekam" posebne datoteke (special files).

Posebne datoteke lahko vzpostavlja sistemski administrator z ukazom mknod. Na primer:

mknod /dev/tty12 c 2 12

Pri tem je /dev/tty12 datotečno ime za periferijo, c pomeni, da gre za znakovno posebno datoteko, 2 je veliko število (major number) in 12 je malo število (minor number). Veliko število pove tip naprave in ustreza indeksu v ustrezno stikalno tabelo (0, 1, 2,..). Z malim številom pa so oštevilčene naprave danega tipa (definiranega z velikim številom. Malo in veliko število dane periferne naprave je pomnjeno v ustreznem i_vozlu. V razliko i_vozlov navadnih datotek ne smejo biti i_vozli posebnih datotek nikoli zaklenjeni, saj procesi v gonilnikih pogosto "spijo".

Nek programski proces lahko na primer odpre in nato bere iz zahtevane periferne naprave. Pri sistemskem klicu uporabi veliko število za ugotovitev naslova iskane

69

Page 70: Handout Os 2

rutine v ustreznem gonilniku, malo število pa posreduje tej rutini kot argument (gonilnik namreč lahko streže več enakim perifernim napravam). Prvi sistemski klic je seveda open, ki inicializira privatne podatkovne strukture v gonilniku, v jedru pa tudi alocira pomnilniško kopijo i_vozla.

Metoda komunikacije med gonilnikom in periferno napravo se od primera do primera razlikuje. Gonilnik vpisuje v registre krmilnika periferne naprave ustrezne kotrolne podatke, med njimi pogosto tudi bit za omogočanje (in na koncu preprečevanje) prekinitvenih zahtevkov. V redkih primerih zelo hitrih perifernih naprav lahko pride do prenosa podatkov direktno v uporabnikov naslovni prostor (v podatkovne strukture uporabnikovih podatkov. Bolj običajen je prenos posredno preko vmesnih pomnilnih polj. Pri blokovnih napravah imamo med že omenjenimi rutinami medpomnilnika in rutinami gonilnika še rutine za strategijo razvrščanja bralno-pisalnih zahtevkov. Slednje dobivajo od medpomnilniških rutin naslove fizičnih diskovnih blokov, vrstni red le-teh pa prerazporedijo s ciljem čim večje propustnosti sistema.

Terminalski gonilniki so po funkcijah enaki drugim gonilnikom. Hkrati jim je posebnost to, da so del vmesnika človek-stroj in morajo podpirati interaktivno delo. Zato interno vsebujejo vmesnike, ki jim pravimo vrstične discipline (line disciplines). Tak modul pretvarja surove (tipkane) vhodne podatke v prečiščene izhodne (upoštevanje tipkanih korekcij, tipkovnih kombinacij za ukinjanje procesov itd). Pri izhodu pa pretvarjajo taki moduli podatke, ki jih pošiljajo programski procesi, v obliko, ki jo pričakuje uporabnik (na primer ekspanzija tabulatorskih znakov).

Linijske discipline seveda potrebujejo za svoje delo preprosta vmesna polja. To so takoimenovane c- liste (c-lists, znakovni seznami), ki povezujejo takoimenovane c-bloke. Koncept c-list je bolj podrobno ponazorjen v poglavju s primerom gonilnika.

Povezovanje računalnikov v mreže je z uvedbo večnivojskih komunikacijskih protokolov postavilo gonilnikom dodatne naloge. S ciljem večje fleksibilnosti in modularnosti so za vhodno-izhodni sistem uvedli shemo tokov (streams). Tok je polna dupleksna povezava med procesom in perifernim gonilnikom. Predstavlja ga množica linearno povezanih dvojnih vrst. Ena vrsta je za vhod, druga za izhod kot to ponazoruje spodnja slika:

70

Page 71: Handout Os 2

Vsaka vrsta je podatkovna struktura, ki vsebuje naslednje elemente:

Proceduro open, ki je klicana ob sistemskem klicu open, Proceduro close, ki je klicana ob sistemskem klicu close, Proceduro put, ki je klicana, ko naj vrsta prejme obvestilo (message), Strežno proceduro, ki je klicana, ko je vrsta izbrana (scheduled) za izvajanje, Kazalec na naslednjo vrsto v toku, Kazalec na seznam obvestil, ki čakajo na servisiranje, Kazalec na privatne podatkovne strukture o stanju vrste, Zastavice o stanju "visoka voda", "nizka voda" (uporabljamo jih pri razvrščanju)

Naprava, ki ima tokovni gonilnik (stream driver), je znakovna naprava. V stikalni tabeli ima posebno polje, ki kaže na iniciacijsko strukturo toka. Pri prvem odpiranju take naprave alocira jedro pare vrst, enega za glavo toka, drugega za sam gonilnik. Po potrebi pa tudi za linijske discipline.

Tokovni moduli niso posebni procesi (ker bi jih bilo preveč), vendar je za njihovo izvajanje vgrajen poseben razvrščevalni mehanizem, ki upošteva stanje v vsaki vrsti (nizek ali visok nivo "vodne gladine").

Prekinitve in njihova obravnava

Spoznali bomo, kako jedro LINUX obravnava prekinitve. Večina te obravnave je odvisna od tipa računalnika.

71

Page 72: Handout Os 2

Večina modernih mikroprocesorjev obravnava prekinitve na enak način. Ko pride do prekinitve, CPE prekine izvajanje inštrukcij in nadaljuje potek na določeni pomnilniški lokaciji, kjer se nahaja rutina ali vsaj inštrukcija za skok na rutino za obravnavo prekinitve. To rutino normalno izvaja v posebnem režimu (interrupt mode), ki onemogoča obravnavo dodatnih prekinitev. Bolj točno: upoštevajo se le prekinitve na višjih nivojih.

Ko je bila prekinitev obdelana, CPE restavrira stanje in nadaljuje prej prekinjen program.

Inicializacija podatkovnih struktur za obravnavo prekinitev

Strukture za obravnavo prekinitev, ki se nahajajo v jedru, vzpostavljajo gonilniki naprav, ko zahtevajo nadzor sistemskih prekinitev. Pri tem uporabljajo več rutin jedra. Tako posamezni gonilniki kličejo take rutine zato, da registrirajo naslove svojih rutin za obravnavo prekinitev.

Pri prekinitvah, ki so določene že z arhitekturo računalnika, zasede gonilnik  že ob svoji inicializaciji. Tako na primer gonilnik za gibki disk vedno zahteva  IRQ 6. V nekaterih primerih pa gonilnik ne ve, katero prekinitev lahko uporabi (tak problem zasledimo pri gonilnikih naprav ISA). V teh primerih Linux dovoli gonilnikom, da sami preskusijo prekinitve.

Gonilnik mora najprej vzpodbuditi napravo, da povzroči prekinitev. Nato omogočimo vse nerazporejene prekinitve. Linux prebere statusni register prekinitev ( interrupt status

72

Page 73: Handout Os 2

register) in vrne njegovo vsebino gonilniku. če je prišlo do vsaj ene prekinitve, je ta vsebina različna od 0.  Tako lahko ugotovimo primerno število IRQ. Gonilnik nato le še ponovno onemogoči nerazporejene (nepovzročene) prekinitve.

Naprave  PCI  lahko souporabljajo prekinitve. Linux to podpira tako, da prvemu (gonilniku), ki zahteva neko prekinitev, dovoli, da določi, ali lahko to prekinitev uporabljajo tudi drugi gonilniki.  Souporaba prekinitev  pomeni več struktur  irqaction , ki jih naslavlja en vhod v vektorju irq_action vector. Ko pride do prekinitve, pokliče Linux vse gonilnike. Ti morajo predvideti tudi klic, ko prekinitve ne pričakujejo.

Obravnava prekinitev

 Linux mora preusmeriti prekinitve na pravo rutino.  Linux uporablja množico kazalcev na strukture z naslovi takih rutin. Te rutina pa pripadajo posameznim gonilnikom. 

Slika prikazuje vektor kazalcev   irq_action , ki kažejo na strukture  irqaction. Vsaka struktura  irqaction vsebuje podatke o rokovalniku (handler), vključno z naslovom prekinitvene servisne rutine. 

Gonilnik naprave mora ob prekinitvi prebrati statusni register naprave in ugotoviti vzrok prekinitve (morda je prišlo le do kakšne napake  ipd). Ko ugotovimo pravi vzrok, je morda potrebna še nadaljna obdelava, ki pa jo lahko prestavimo na poznejši čas in tako preprečimo pretirano zadrževanje CPE v prekinitvenem režimu.

73

Page 74: Handout Os 2

Primer gonilnika UNIXNa najnižjem nivoju vhodno-izhodnih komunikacij imamo gonilnike (drivers). Pri pisanju novega gonilnika je priporočljivo, da si za zgled vzamemo nek obstoječi gonilnik. Kot klasični primer si bomo ogledali gonilnik za tiskalnik. Primer velja za operacijski sistem SCO UNIX, ki ga normalno uporabljamo na PC kompatibilnih računalnikih. Za te računalnike je značilno, da poteka komunikacija s periferijami (oziroma njihovimi krmilniki) preko vrat (ports). Ustrezen krmilnik (controller) ima tri registre: podatkovnega, statusnega in krmilnega, kot to ponazoruje spodnja slika:

   

Predpostavimo, da bralec razume pomen posameznih bitov v navedenih registrih.

V nadaljevanju sledi koda gonilnika, ki ga bomo komentirali. Zgled bi moral biti zanimiv zaradi uporabljenih programerskih prijemov.

/* Line printer driver for SCO UNIX system */ #include <sys/param.h> #include <sys/errno.h> #include <sys/types.h> #include <sys/signal.h> #include <sys/dir.h> #include <sys/user.h> #include <sys/tty.h> #include <sys/sysmacros.h>#define LPPRIORITY PZERO+5 #define LOWATER 50 #define HIWATER 250 #define TOINT HZ/10#define LPBASE 0x378 #define LPDATA (LPBASE + 0) #define LPSTAT (LPBASE + 1) #define LPCTRL (LPBASE + 2)#define LPNERR 0x08 

74

Page 75: Handout Os 2

#define LPON 0x10 #define LPREADY 0x80#define LPSTROBE 0x01 #define LPLF 0x02 #define LPINT 0x04 #define LPSELECT 0x08 #define LPINTENABLE 0x10#define LPEXIST 0x01 #define SLEEP 0x02 #define LPBUSY 0x04 #define TOPEND 0x08 #define WAIT 0x10 #define EXCLOPEN 0x20 #define OPEN 0x40static unsigned short LpFlags = 0; static struct clist LpQueue;/*****************************************************************/ /* init( ) entry point.... */ /* 1. check if device controller responding */ /* 2. if device present: write corresponding message */ void lpinit( ) {     outb(LPCTRL, 0); /* clear LP control register */     if (inb(LPCTRL) != 0xE0) return;     outb(LPCTRL, 0xFE); /* test if control register answers */     if (inb(LPCTRL) != 0xFE) return;     outb(LPCTRL, 0);     printf("Line printer driver at address %x\n", LPBASE);     LpFlags = LPEXIST; /* set device exists flag */ }/*****************************************************************/ /* open( ) entry point ......*/ void lpopen(dev_t dev, int flags, int otyp) {     if ((LpFlags & LPEXIST) == 0) u.u_error = ENODEV; /* error: no device */     else if (LpFlags & EXCLOPEN) u.u_error = EBUSY; /* error: device busy */     else if (LpFlags & OPEN) {         if (flags & FEXCL) /* check if exclusive open requested*/         u.u_error = EBUSY;    }    else {         outb(LPDATA, 0);         outb(LPCTRL, LPLF | LPINIT | LPSELECT);         LpFlags |= OPEN; /* set device open flag */         if (flags & FEXCL) /* check if exclusive open requested*/         LpFlags |= EXCLOPEN;     } }/*****************************************************************/ /* close( ) entry point ...... */ void lpclose(dev_t dev, int flags, int otyp) {     int x; x = spl5( );     while (LpFlags & LPBUSY) {         LpFlags |= WAIT;         sleep(&LpFlags, LPPRIORITY);     } LpFlags = LPEXIST;     outb(LPCTRL, 0);     splx(x); 

75

Page 76: Handout Os 2

}/*****************************************************************/ /* write( ) entry point........ */ void lpwrite( dev_t dev) {     char c; int x;     extern void lpwork( );    while(u.u_count) {         if (copyin(u.u_base, &c, 1) == -1) {             u.u_error = EFAULT;             return;         }         u.u_base++; u,u_count--;         while (LpQueue.c_cc >HIWATER) {             x = spl5( ); lpwork( );             if (LpQueue.c_cc >HIWATER) {                 LpFlags |= SLEEP;                 sleep (&LpQueue, LPPRIORITY);             }             splx(x);         }         putc(c,&LpQueue);     }     x = spl5( ); lpwork( ); splx(x); }/*****************************************************************/ 

/* local driver routine, copy the data from the clist to the printer */ static void lpwork( ) {     int ch;     short spinLoop;    extern void lprestart( );    LpFlags |= LPBUSY; /* set printer status to BUSY */     while (1) {         /* infinite loop until break */         spinLoop = 100;         while ((inb(LPSTAT) & (LPNERR | LPON | LPREADY )) (LPNERR | LPON | LPREADY))            && --spinLoop) ;         if (spinLoop == 0) break; /* timeout: exit from loop */         if ((ch = getc(&LpQueue)) < 0) break; /* clist empty */         outb (LPDATA, ch); /* put data into printer data register */         /* then send the neccessary strobe signal into CTRL reg... */         outb (LPCTRL, LPSTROBE | LPLF | LPINIT | LPSELECT);         outb (LPCTRL, LPLF | LPINIT | LPSELECT);     }     /* if room in clist and process is sleeping waiting for room,        wake up sleeping process ... */     if ((LpQueue.c_cc <LOWATER) && (LpFlags & SLEEP)) {         LpFlags &= ~SLEEP;         wakeup (&LpQueue);     } if (LpQueue.c_cc <= 0) {         LpFlags &= ~LPBUSY;         if (LpFlags & WAIT) wakeup (&LpFlags);     }     else if (( LpFlags & TOPEND) == 0) {         timeout (lprestart, 0, TOINT);         LpFlags |= TOPEND; 

76

Page 77: Handout Os 2

    } outb (LPCTRL, LPLF | LPINIT | LPSELECT | LPINTENABLE); }

/************************************************************//* interrupt service routine */ void lpintr (dev_t dev); {     /* exit immediately if LP driver status set to busy.. */     if ((LpFlags & LPBUSY) == 0) return;     /* if some data waiting: write data to printer port */     if ( LpQueue.c_cc >0) lpwork(); }

/************************************************************/

/* when the timeout occurs: use restart routine */ static void lprestart( ) {     int x;     LpFlags &= ~TOPEND;     x = spl5( ); lpwork( ); splx(x); }

Modul začenja takoimenovani prolog, v katerem so navedeni stavki include in define. Prvi navajajo datoteke, v katerem so definirane strukture in funkcije v jedru (kernel). Tako so v datoteki tty.h definirane takoimenovane c-liste, v datoteki sysmacros.h pa makroji inb(0) in outb( ), ki jih uporabljamo za komunikacijo z vrati krmilnika (input-bute, output-byte).

S stavki define določamo naslove krmilnikovih registrov, ki si slede od nekega naslova (LPBASE) dalje. Prav tako definiramo razne maske za (re)setiranje oziroma testiranje posameznih bitov v registrih krmilnika. Tudi sam gonilnik bo imel svoj status (LpFlags), v katerem bomo setirali ali testirali posamezne bite. Ti bodo kazali, ali proces, ki uporablja gonilnik, trenutno spi (SLEEP), čaka (WAIT) oziroma ali je gonilnik zaseden (BUSY) itd.

Sam gonilnik ima več rutin. Vse začenjajo z dogovorjeno predpono, v našem primeru lp.

Prva rutina je lpinit( ), oziroma v sploąnem init( ). To kliče sistem ob zagonu operacijskega sistema. Njena naloga je, da preveri, ali je dana periferna naprava (pri nas tiskalnik) prisotna (ali lahko vplivamo na njene registre) in nato izpiše ustrezno obvestilo. Sledita rutini open( ) oziroma close( ) (v naąem primeru lpopen(0) in lpclose( ). Obe kličemo s primernim sistemskim klicem, na primer:

open("/dev/lp", O_WRONLY | O_EXCL);

S takim klicem odpremo tiskalnik za pisanje (saj ga drugače ne moremo) in zahtevamo ekskluzivni dostop do tiskalnika.

Znanemu sistemskemu klicu write( ) ustreza rutina lpwrite(), ki pomeni zahtevek za prepis nekega polja. Pri tem pa moramo rešiti več problemov.

77

Page 78: Handout Os 2

Gonilnik ima dostop le do tistega dela podatkov v uporabnikovem programu, ki so zanj pomembni. Ti so shranjeni v posebni strukturi u (user), ki ima v splošnem naslednje elemente:

u_error     Povratna koda ob morebitni napaki u_uid        Identifikacijska številka uporabnika (UID) kličočega procesa u_gid        Identifikacija uporabniške grupe (GID) kličočega procesa u_base      Naslov polja (buffer) v uporabniškem naslovnem prostoru u_count    Koliko bytov želimo prenašati u_offset    Trenutna pozicija v datoteki, s katero komuniciramo)

Kot vemo, imamo dva režima delovanja (user mode, kernel mode). Obema ustreza drug naslovni prostor procesa (user address space, kernel address space). S tem je zagotovljeno, da uporabnik ne more kar tako naslavljati ščitenih podatkovnih struktur jedra. Za prepis podatkov med obema naslovnima prostoroma potrebujemo dve posebni rutini:

copyout (kernelAddress, userAddres, count); copyin (userAddress, KernelAddress, count);

Prva omogoča prepis count bytov iz polja v naslovnem prostoru jedra v polje v naslovnem prostoru uporabnika. Druga ima inverzno nalogo.

Gonilnik mora tudi rešiti problem običajne počasnosti periferne naprave, s katero komunicira. Zato poteka prepis posredno preko primernega vmesnega polja. Zaradi boljše izkoriščenosti celotnega pomnilnika uporabljajo gonilniki posebno vrsto pomnilnih polj (character-liste -> c-liste), ki predstavljajo nekakšno skupno zalogo polj. V danem trenutku niso aktivni vsi gonilniki. Tako morda tudi po več tednov ne rabimo tiskalnika. Morda tudi ne uporabljamo vseh terminalov. Pomnilna polja (c-liste) naj bodo na voljo tistim gonilnikom, ki jih v danem trenutku potrebujejo. Organizacijo c-list kaže naslednja slika:

78

Page 79: Handout Os 2

C-liste so relativno kratka polja (nekaj 100 bytov). Zato v gonilniku prepisujemo v tak medpomnilnik znake iz uporabnikovega naslovnega prostora, dokler ne dosežemo dogovorjene kritične "gladine" (high water, HIWATER). V takem primeru rutina write( ) raje zaspi, dokler se medpomnilnik ne primerno izprazni (low water, LOWATER). Za slednje skrbi prekinitvena servisna rutina (v naąem primeru lpintr( ) ).

Sam prepis naslednjega znaka iz c-liste na tiskalnik je izveden v lokalni proceduri lpwork( ).

Zanimivo je, da imamo v gonilniku tudi nekaj zank, za katere pa moramo izkustveno ugotoviti, da niso predolge oziroma da nimajo preveč iteracij. Posebno kritična je v tem smislu rutina lpwork( ), ki jo kliče tudi lpintr( ). V tem času so namreč nadaljni prekinitveni zahtevki onemogočeni (ker jedro ob prekinitvi izvede instrukcijo "disable interrupts", kliče nato lpintr( ) in šele po povratku iz nje prekinitve spet omogoči.

Ko imamo gonilnik sprogramiran, ga moramo prevesti in vgraditi v jedro. V nekaterih primerih UNIX imamo za vgradnjo na voljo poseben program. Po ponovnem zagonu računalnika (reboot) se bo tako pognala nova verzija jedra z vgrajenim gonilnikom.

Na koncu še enkrat poudarimo, da je podani primer veljaven le pri določeni verziji SCO implementacije sistema UNIX. Iz njega lahko spoznamo le koncepte gonilnikov, podrobnosti pa se od primera do primera zelo razlikujejo.

Medprocesna komunikacija pri UNIX

Na voljo imamo naslednje oblike medprocesne komunikacije signali semaforji skupen pomnilnik (shared memories) sporočila (message queues) vtičnice (sockets)

Semaforji

S semaforji predvsem ščitimo kritične sekcije, na primer pri spreminjanju skupnega pomnilnika.

Semaforje imamo alocirane v skupinah. Vsaka skupina ima svojo številčno oznako, semaforji v njej pa so prav tako oštevilčeni, začenši z 0.

Na voljo imamo naslednje sistemske klice   semget() S tem klicem tvorimo novo skupino semaforjev ali dobimo oznako obstoječega

semaforjasemctl() Tako dobimo ali spreminjamo vrednost določenega semaforja v skupini

semaforjev.

79

Page 80: Handout Os 2

semop() Na izbranem semaforju izvedemo neko operacijo

Skupen pomnilnik

Skupen pomnilnik (shared memory) je metoda, ko dva ali več programov souporablja isti segment virtualnega pomnilnika. Da ne pride do nekonsistenc, si moramo pomagati še s semaforji.

Imamo naslednje sistemske klice  

shmget() S tem klicem tvorimo dostop do skupnega pomnilniškega segmenta ali tak segment sploh tvorimo

shmctl() tako dobimo ali spreminjamo podatke o skupnem pomnilniškem segmentu

shmat()Preden lahko nek proces uporabi skupen segment, se mora nanj najprej prilepiti (attach)

shmdt()Po koncu souporabe skupnega pomnilniškega segmenta se tako od njega odlepimo (detach)

Sporočila

Procesi si izmenjujejo sporočila preko sporočilnih vrst (message queues). Vsako sporočilno vrsto označuje celoštevilčna oznaka.

Na voljo imamo naslednje sistemske klice:   msgget() S tem klicem tvorimo novo vrsto ali dobimo oznako obstoječemsgctl() tako dobimo ali spreminjamo atribute obstoječe sporočilne vrstemsgsnd()  Pošljemo sporočilo v sporočilno vrstomsgrcv() Iz sporočilne vrste beremo sporočilo

Signali UNIX

Koncept signalov UNIX

Signali so v bistvu programske prekinitve in omogočajo obravnavo asinhronih dogodkov. V prvih verzijah UNIX so bili dokaj nezanesljivi in so se včasih “zgubljali".

UNIX verzije 7 ima 15, BSD-UNIX pa 31 (oštevilčenih) signalov. Zaradi jasnosti je vsakemu signalu prirejeno simbolično ime, ki začenja s SIG (na primer SIGKILL, SIGQUIT,..). Ta imena so definirana v datoteki <signal.h>. Posebno poznan je signal številka 9, ki mu pravimo SIGKILL. Z njim lahko ukinemo "zablodeli" proces, če le poznamo številko tega procesa. Omenimo še, da sta dva signala (SIGUSR1 in SIGUSR2) direktno namenjena uporabniku in nimata kakšnega "sistemskega" pomena.

80

Page 81: Handout Os 2

Signale generirajo dogodki na terminalu (na primer pritisk na tipko DELETE generira signal SIGINT), lahko jih povzroče aparaturne ali programske izjeme (na primer delitev z 0). Lahko jih tudi sprožimo iz komandne vrstice ali pa programsko z nekaterimi funkcijami (na primer kill( ) ).

Nekaj primerov tvorbe signala s komandne vrstice:

kill -9 125 # ukinjamo proces 125 kill -KILL 112 # ukinjamo proces 112, ukaz je ekvivalenten prejsnjemu kill -USR2 116 # procesu 116 posiljamo signal SIGUSR2

Jedru lahko damo dispozicijo, kako naj odgovori na signal. Možni so 3 tipi reakcij:  

Ignoriranje signala. To lahko velja za vse signale razen za SIGKILL in SIGSTOP. Ni pa priporočljivo ignoriranje signalov, ki jih generira aparaturna oprema (delitev z 0, nelegalna inštrukcija).

Signal ujamemo (catch). Jedru moramo povedati, katero funkcijo naj pokliče. Izvede naj se privzeta (default) akcija. Večinoma pomeni to ukinitev danega

procesa. Včasih povzroči to tudi izpis pomnilnika (core dump).

Funkcija signal( ) Je v bistvu vmesnik med mehanizmom signalov in našim programom. Njeno (precej splošno) definicijo zasledimo tudi v ANSI C. Na sistemih UNIX so lahko njeni ekvivalenti različni. Funkcija signal ( ) ima dva argumenta.. Prvi (signo) je številka signala. Drugi argument je kazalec na funkcijo, ki ji pravimo rokovalnik signalov (signal handler). To funkcijo sami napišemo.

Spodnji primer kaže definicijo rokovalnika signalov userFunc( ), ki se bo sprožil ob sprejemu (ujetju) enega od obeh "uporabniških signalov". Navezavo rokovalnika na oba signala smo vzpostavili s funkcijo signal( ) v funkciji main( ).   /* Program sigZgledA : primer definicije rokovalnika signalov */ /* in vzpostavitve zveze z njim s funkcijo signal */#include <signal.h>static void userFunc (int signo) {     /* isti rokovalnik za oba signala: argument je stevilka ujetega signala */     if(signo == SIGUSR1) {         printf("Prejel sem signal SIGUSR1\n");         signal(SIGUSR1,userFunc);     }     else if (signo == SIGUSR2) {         printf("Prejel sem signal SIGUSR2\n");         signal(SIGUSR2,userFunc);     } }int main(void) {             if (signal(SIGUSR1, userFunc)  == SIG_ERR) printf("Ne morem ujeti signala SIGUSR1\n");             if (signal(SIGUSR2, userFunc) == SIG_ERR) printf("Ne morem ujeti signala SIGUSR2\n");              for        (; ;) pause( ); /* smo blokirani v zanki */  

81

Page 82: Handout Os 2

}

Tak program poženimo "v ozadju" in mu posredujmo signale z ukazom kill. Pogovor z računalnikom bi imel naslednjo obliko (pri tem podajamo na desni strani komentar posameznih vrstic):

$sigZledA  &                               # Prozili smo program sigZgledA v "ozadju" [ 156]                                           # Racunalnik javi PID prozenega procesa $kill -USR1 156                            # Procesu s PID= 156 posljemo signal USR1 Prejel sem signal SIGUSR1           # Odgovor procesa 156, ki ostaja v ozadju ...

V nekaterih verzijah UNIX klic "našega" rokovalnika žal preklopi dispozicijo za dani signal na privzeto (default) alternativo. To pa pomeni, da bi naslednji signal naš proces verjetno ukinil. Problem rešimo tako, da v rokovalniku s ponovno uporabo funkcije signal( ) dispozicijo spet vzpostavimo tako, kot želimo.

Poudarimo še nekaj pojmov v zvezi s signali: Signal je generiran (oziroma poslan procesu), ko nastopi utrezen dogodek. Signal je sprejet (delivered), ko se sproži primerna akcija. Vmes signal visi (pending). Proces lahko blokira posredovanje signala (in ta ostane viseč). Pri nekaterih sistemih (POSIX.1) lahko taki procesi čakajo v vrsti.

Nezanesljivi signali

Problem, ki lahko nastopi v našem prejšnjem primeru, je v časovnem zamiku med sprejetjem signala in ponovno vzpostavitvijo rokovalnika. Ponovni nastop signala v tem času lahko povzroči ukinitev našega procesa. Te nerodnosti morda sploh ne zasledimo dokler se nam slučajno to ne zgodi.

Včasih si zaželimo, da bi sistemu rekli: "V danem hipu nas signali ne zanimajo (in naj nas morda ne motijo), vendar si zapomni, da so nastopili". To lahko naredimo z uvedbo primerne zastavice, ki jo sprejem signala nastavi, proces bo pa na to reagiral malo kasneje. To ponazoruje naslednji primer:   #include <signal.h>int flag=0; int sigNum;static void userFunc( ) {     signal(sigNum,userFunc); /* ponovna vzpostavitev */     flag = 1; /* zastavico bo testiral glavni program */ }main( ) {              sigNum        = SIGINT;       signal(sigNum,        userFunc);       for  (;;) {             flag = 0; /* brisanje        zastavice */              printf (" cakam na signal \n");              while (flag == 0) pause( ); /* cakamo na signal */              printf("Prejel signal\n");       }         }

82

Page 83: Handout Os 2

Tudi v tem primeru nastopa problem "časovnega okna" in s tem morebitne izgube signala med testiranjem zastavice in "spanjem" procesa. Proces je morda že testiral zastavico in ugotovil njeno vrednost 0. Če je nato prišlo do tvorbe signala pred vstopom v funkcijo pause() (tako nam lahko zagode razvrščanje procesov), bo proces zaspal za vedno, signal pa bo obvisel.

Problem prekinjenih sistemskih klicev.

Ta problem zasledimo predvsem pri "počasnih" sistemskih klicih. Imejmo proces, ki je trenutno blokiran zaradi sistemskega klica. Signal mora tak klic prekiniti (ker morda želimo prekiniti "obešen" program. To pa pomeni, da bi v našem programu morali po vsakem sistemskem klicu testirati vzrok povratka iz sistemskega klica (spremenljivko errno). Program postane zaradi dodatnih testov nepregleden. Pri sistemu 4.2BSD so v ta namen uvedli mehanizem avtomatskega restarta prekinjenih sistemskih klicev. UNIX sistem V tega mehanizma ne podpira.

"Reentrant" funkcije:

Zaradi asinhronosti dogodkov lahko pride do tega, da funkcija za rokovanje s signalom uporablja iste rutine kot prekinjani proces. Te rutine oziroma funkcije morajo zato biti "reentrant" oziroma v rokovalniku ne smemo uporabljati funkcij, ki uporabljajo statične spremenljivke, ki kličejo malloc( ) ipd. Upoštevati moramo tudi, da imamo za vsak proces le eno spremenljivko errno. Skrb rokovalne funkcije je zato, da errno shrani in nato restavrira. Pregled funkcij s signali

Funkcija kill( ) pošilja signal procesu ali skupini procesov. Podobna je funkcija raise( ), ki omogoča procesu, da si pošlje signal sam sebi.

int kill(pid_t pid, int signo);int raise(int signo);

V prvem primeru odloča argument pid, kateri procesi dobe signal. Signal lahko pošljemo določenemu procesu (pid>0) ali skupini procesov (pid=0), ki pripadajo isti skupini kot proces, ki signal tvori. Upoštevati pa moramo, da PID pri sistemu UNIX čez nekaj časa reciklirajo.

Funkcija alarm( ) nastavi timer, ki po izteku generira signal SIGALARM. Njena splošna oblika je naslednja:

unsigned int alarm(insigned int seconds);

Posredovanje signala SIGALARM bo (malo) po izteku časa, saj moramo upoštevati še delovanje razvrščevalnika. (Torej nikakor ne v realnem času).

Funkcija pause( ) suspendira proces, dokler ne pride do ulovljenja primernega signala.

83

Page 84: Handout Os 2

S kombinacijo alarm(0) in pause( ) lahko realiziramo ekvivalent klica sleep. Pri tem lahko pride do več problemov: Kaj, če je pred prvim alarmom bil klican še kakšen? Kaj če je sistem zelo zaseden in pride do prevelikega zamika med klicem alarm( ) in klicem pause( ) (med obema velja tekmovanje (race condition)).

Množice signalov (signal sets)

Sistem UNIX omogoča, da nastavljamo maske, s katerimi določamo, kateri signali lahko vplivajo na naš proces, katere lahko blokiramo (in tako ignoriramo). S temi maskami lahko tudi ugotavljamo, kateri signali zaradi nas visijo. Praviloma je taka maska dolga eno besedo, kar zadošča za pomnenje statusa 15 oziroma 31 signalov. Funkcije, s katerimi operiramo nad "množico" signalov, so naslednje: sigemptyset( )        Brisanje maske v celoti sigfillset( )             Setiranje maske v celoti sigaddset( )            Setiranje posameznih bitov v maski sigdelset( )             Brisanje posameznih bitov v maski sigprocmask( )       Blokiranje, deblokiranje signalov, nastavljanje maske sigpending( )          Ugotavljanje, kateri signali visijo sigaction( )             Preverjanje in spreminjanje akcij, ki so prirejene danemu signalu V nadaljevanju vidimo še primer uporabe teh funkcij:   #include <signal.h>static void sigQuit(int signo) {     printf("Ujet signal SIGQUIT\n");     if (signal(SIGQUIT,SIG_DFL)==SIG_ERR) printf("Ne morem resetirati SIGQUIT\n");     return; }int main(void) {            sigset_t        newmask, oldmask, pendmask; /* deklaracija treh mask */            if (signal(SIGQUIT,sigQuit)==SIG_ERR) printf("Napaka:Ne morem ujeti signala        SIGQUIT \n");     sigemptyset(&newmask);        /* resetiranje maske v celoti */     sigaddset(        &newmask, SIGQUIT); /* nastavimo bit, ustrezen signalu SIGQUIT*/             if(sigprocmask(SIG_BLOCK,        &newmask, &oldmask)<0)            printf("Napaka: SIG_BLOCK \n"); sleep(5); /* signal SIGQUIT bo obvisel,        ce pride v casu teh 5 sekund */      if (sigpending(&pendmask)        <0) printf(" Napaka: sigpending \n");     if (sigismember(        &pendmask, SIGQUIT))             printf("Visi signal SIGQUIT \n"); /* setirajmo signalno masko za deblokiranje        SIGQUIT */     if        (sigprocmask(SIG_SETMASK,        &oldmask, NULL) <0) printf(" Napaka: SIG_SETMASK\n");            printf("SIGQUIT        deblokiran \n");     sleep(5);        /* SIGQUIT bo koncal z datoteko core */     exit(0);         }

84

Page 85: Handout Os 2

Cevi (Pipes)

Lupine Linux omogočajo preusmerjanje (redirekcijo). Primer

$ ls | pr | lpr

poveže izhod iz ukaza ls (ki lista datoteke direktorija) na standardni vhod ukaza  pr (ki oblikuje ta izpis v strani). Končno je izhod ukaza  pr preusmerjen na standardni vhod ukaza  lpr, ki izpiše rezultat na tiskalnik. Cevi so torej enosmerni tokovi bajtov, ki povezujejo standardni izhod enega procesa s standardnim vhodom nekega drugega procesa.  Procesi se take preusmeritve ne zavedajo in se obnašajo tako, kot bi se v vsakem primeru. Začasne cevovode med njimi vzpostavi lupina.

V Linuxu je cev implementirana v obliki dveh datotečnih struktur, ki obe kažeta na isti začasni VFS vozel, ta pa kaže na fizično stran v pomnilniku.  Slika  kaže, da ima vsaka od obeh datotečnih struktur (file) kazalce na različne vektorje (sezname) datotečnih rutin, ena na pisanje v cev, druga na branje iz cevi. 

Tako skrijemo razlike med splošnim sistemskim klicem za branje oziroma pisanje v datoteke (read oziroma write). Ko pišoči proces piše v cev, se bajti kopirajo v skupno podatkovno stran. Ko bralni proces bere iz cevi, pride do kopiranja bajtov it te skupne

85

Page 86: Handout Os 2

podatkovne strani. Linux mora poskrbeti za sinhronoziran dostop do cevi. Pri tej sinhronizaciji uporablja zaklepanje, čakalne vrste in signale.

Ko oba procesa prenehata uporabljati cev, se vozel, dodeljen cevi, in souporabljena podatkovna stran sprostita.

Linux podpira tudi imenovane cevi (named pipes), ki delujejo po principu FIFO (First In, First Out). V razliko od navadnih cevi imenovane cevi niso le začasni objekti in jih tvorimo z ukazom  mkfifo. Procesi lahko tako cev uporabljajo, če imajo za to pravico. Odpiranje imenovane cevi (ki ji pravimo tudi FIFO) je drugačno od odpiranja navadnih cevi, saj pred uporabo že obstaja in jo moramo le odpreti in na koncu zapreti. Linux mora tudi upoštevati, da morda najprej odpremo bralne procese in šele nato pisalne. 

Primer: #include <sys/types.h>#include <sys/wait.h>#include <stdio.h>#include <errno.h>#include <unistd.h>        int main(int argc, char *argv[]){      int status;      int pid[2];      int pipe_fd[2];

      char *prog1_argv[4];      char *prog2_argv[2];

      /* Build argument list  */

      prog1_argv[0] = "/usr/local/bin/ls";      prog1_argv[1] = "-l";      prog1_argv[2] = "/";      prog1_argv[3] = NULL;      prog2_argv[0] = "/usr/ucb/more";      prog2_argv[1] = NULL;

      /* Create the pipe */      if (pipe(pipe_fd) < 0){        perror ("pipe failed");        exit (errno);      }

      /* Create a process space for the ls   */      if ((pid[0]=fork()) < 0){        perror ("Fork failed");        exit(errno);      }

      if (!pid[0]){          /* Set stdout to pipe   */          close (pipe_fd[0]);          dup2 (pipe_fd[1], 1);          close (pipe_fd[1]);

86

Page 87: Handout Os 2

        /* Execute the ls */         execvp (prog1_argv[0], prog1_argv);      }

      if (pid[0]) {        /*  We're in the parent  */

        /* Create a process space for the more  */        if ((pid[1]=fork()) < 0){          perror ("Fork failed");          exit(errno);        }        if (!pid[1]){          /* We're in the child */          /* Set stdin to pipe  */          close (pipe_fd[1]);          dup2 (pipe_fd[0], 0);          close (pipe_fd[0]);          /* Execute the more */           execvp (prog2_argv[0], prog2_argv);        }        /* This is the parent */        close(pipe_fd[0]);        close(pipe_fd[1]);        waitpid (pid[1], &status, 0);        printf ("Done waiting for more.\n");      }    }

Sistem NFSSistemu NFS pravijo včasih porazdeljen datotečni sistem, vendar je bolj pravilno, da mu rečemo mrežni datotečni sistem. NFS je običajno poseben dodatek k nabavljenemu operacijskemu sistemu. Omogoča programom na računalnikih - klijentih transparenten dostop (branje in pisanje) do datotek na računalnikih z ustreznim strežnikom NFS. Organizacija NFS je simetrična tako, da je lahko dani računalnik lahko istočasno klijent in strežnik.

87

Page 88: Handout Os 2

  Strežnikov je lahko tudi več. 

Taka je struktura na strani klijenta. Ko odpremo datoteko, kontaktira sistem vse strežnike. 

88

Page 89: Handout Os 2

Plast VFS (Virtual File System) pomni za vsako odprto datoteko tabelo virtualnih vozlov (v-node).

v-vozel kaže v primeru lokalnih datotek na i-vozel. V primeru oddaljenih datotek pa na r-vozel (remote i-node = r-node).

  Pri obravnavi NFS moramo ločiti med pojmoma produkt NFS in protokol NFS.

Strežnik NFS ne pomni stanja o klijentih in ne o predhodnih zahtevkih le-teh. Je torej brez stanja (stateless). Če pride do izpada strežnika, ni zato zgubljenega nič. Zgodovino predhodnih zahtevkov si morajo zapomniti klijenti, ki pač po potrebi zahtevke ponovijo. Sistem NFS naj bi sicer dopuščal ekvivalentne operacije, ki jih imamo na lokalnem datotečnem sistemu, vendar nekatere omejitve le veljajo.

Med bolj znanimi je brisanje odprte datoteke. Pri lokalnih datotečnih sistemih bi taka datoteka še fizično obstajala, dokler jo nek proces drži odprto. Tega pa strežnik NFS ne more vedeti.

Delno se taki problemi rešujejo z več inteligence na strani klijentov. Pa še pri tem veljajo omejitve (na primer da sta proces, ki datoteko odpre, in proces, ki datoteko briše, na istem računalniku - klijentu).

Prej navedeni problem se na strani klijenta na primer rešuje z začasnim preimenovanjem datoteke ( damo ji neko "sintetično" ime, na primer .xx12345). Datoteke pod iskanim imenom ne poznamo več, vendar fizično še obstaja. Tako zaznamovano (in nevidno) datoteko nato zbrišemo pri njenem zaprtju, lahko pa jih briše tudi neka procedura ob ponovnem zagonu računalnika.

89

Page 90: Handout Os 2

Podobne probleme imamo tudi pri spreminjanju lastništva in zaščit datotek. Probleme povzroča tudi pomnenje atributov direktorijev, ki so tako kot navadne datoteke pomnjeni v medpomnilniku klijenta. Problemi so lahko tudi zaradi slabe časovne sinhronizacije računalnikov (eden od atributov datoteke je tudi čas njene tvorbe ali dostopa).   Seveda so tudi performanse (propustnost) sistema NFS praviloma slabše od performans lokalnih datotečnih sistemov. Izboljšamo jih z uporabo medpomnilnikov (cache): 

Kako montiramo nek datotečni sistem na strežnik NFS

Pri zagonu sistema se v strežniku sproži (poleg demonskega procesa nfsd) tudi demonski proces mountd. Na strani klijenta uporabimo ukaz mount.

90

Page 91: Handout Os 2

Vzpostavi se povezava med procesoma mount in mountd. Slednji obdela sprejete podatke o poti do zahtevanega datotečnega sistema in vrne podatke o osnovi(root) sistema, ki ga želi montirati klijent. Te podatke kijent nato uporabi podobno kot pri lokalno montiranih datotečnih (pod)sistemih. V nadaljevanju bo strežniku pošiljal zahtevke v skladu s protokolom NFS.  mount ima pri lokalnih (neporazdeljenih) sistemih normalno naslednjo obliko:

/etc/mount [-r] specialFile directory

V primeru sistema NFS pa ima ta ukaz na primer naslednjo obliko:

/etc/mount -f NFS [,opcije] hostName:pathName directory

Pozor: NFS strežnik vsebuje le datoteke. Ne vsebuje nobenih prehodnih informacij o klijentih (katere datoteka je odprta, kakšni so trenutni odmiki (offset) odprtih datotek,..) Zato morajo zahtevki read() in write() vsebovati tudi ta podatek. Morebitni ponovljeni zahtevki se morajo ponoviti v celoti.

91

Page 92: Handout Os 2

ŠTUDIJ WINDOWS NT (Win 2000) Struktura op. sistema Windows NT/2000Strukturo Windows 2000 delimo v dva dela, tistega, ki pripada uporabniškem režimu in tistega, ki pripada sistemskem režimu.

 

Windows 2000 je prevzel dobre značilnosti tako večnivojskega koncepta kot koncepta klijent- strežnik. Sistemski del (kernel mode)  je takoimenovani izvajalnik (Executive). Vsebuje komponente, ki implementirajo:

Upravljanje z virtualnim pomnilnikom, Upravljanje z objekti (resursi), Vhodno izhodne in datotečne operacije (vključno z mrežnimi gonilniki), Medprocesno komunikacijo, Del varnostnega sistema.

Večplastnost zasledimo v izvajalniku, ki ima plast  jedra (Kernel) in plast abstrakcije aparaturne opreme (HAL, Hardware Abstraction Layer). Jedro opravlja nizkonivojske funkcije operacijskega sistema, HAL pa direktno upravlja aparaturno opremo. Vse druge plasti izvajalnika so tema dvema plastema nadrejene.

Strežniki Windows 2000 so tako imenovani zaščiteni podsistemi. Vsakemu je dodeljen en proces, ki uporablja pomnilnik, zaščiten pred ostalimi procesi. Vsak zaščiteni podsistem ima API rutine, ki jih lahko kličejo drugi programi (aplikacije ali strežniki). Pri takem klicu pride do izmenjave obvestil med kličočim programom in strežnikom preko takoimenovanega klica lokalne procedure (LPC, Local Procedure Call).

92

Page 93: Handout Os 2

Spodnja slika podaja bolj podroben bločni diagram operacijskega sistema Windows NT:  

 

In še struktura Windows 2000

93

Page 94: Handout Os 2

Upravnik objektov

Objekti izvajalnika

Primeri objektov v Windows NT/2000 so lahko procesi, niti, datoteke, dogodki in podobno.

Atributi objektov so podatkovna polja, ki definirajo stanje takega objekta. Pri objektu tipa sklad je na primer eden bolj pomembnih atributov kazalec na sklad.

Servisi objekta omogočajo rokovanje s temi atributi. V primeru objekta sklad je imamo na primer na voljo servis push. Koncept objektov omogoča delitev (sharing) resursov in podatkov med različnimi procesi in ščitenje teh resursov pred nepooblaščenim dostopom.

94

Page 95: Handout Os 2

Komponenta izvajalnika  je upravnik objektov (Object manager). Z njim je zagotovljen poenoten, standardiziran mehanizem uporabe sistemskih resursov, centralizirana zaščita vseh objektov, urejeno pa je tudi poimenovanje sistemskih objektov (kot so naprave, datoteke, direktoriji..).

Izvajalnik  predvideva dve vrsti objektov:    

Objekti izvajalnika (executive objects) so kot ščiteni podsistemi na voljo uporabniškemu režimu, uporablja pa jih lahko tudi sam izvajalnik. 

Objekti jedra (kernel objects) so bolj preprosti in so na voljo le izvajalniku. Nekateri objekti izvajalnika imajo vgrajenih tudi po več objektov jedra. 

  Oglejmo si pregled objektov izvajalnika:  

Tip objekta Definira ga: To je:

Proces (process)

Upravnik procesovPotek programa vključno z njegovim naslovnim prostorom in drugimi potrebnimi resursi

Nit (thread)

Upravnik procesov Izvedljiva entiteta znotraj procesa

Sekcija (section)

Upravnik pomnilnika

Območje souporabnega (shared) pomnilnika

Datoteka (file)

Upravnik vhoda - izhoda

Instanca odprte datoteke ali vhodno/izhodne naprave

Vrata LPC  (klic lokalne

Naslov za sporočila, ki potujejo med procesi

95

Page 96: Handout Os 2

(port) procedure)

Dostopni ľeton (Access token)

Varnostni sistemZanesljiv ID, ki vsebuje informacijo o logiranem uporabniku

Dogodek (event)

Servisi izvajalnika Najava sistemskega dogodka

Dogodkovni par

(event pair)Servisi izvajalnika

Najava, da je nit danega odjemalca kopirala obvestilo (message) strežniku Win32 ali obratno

Semafor (semaphore)

Servisi izvajalnika Števec, ki pove, koliko niti uporablja nek resurs

Mutant Servisi izvajalnikaMehanizem za medsebojno izobčenje zmoľnosti v okoljih Win32 in OS/2

Časovnik (timer)

Servisi izvajalnika Števec iztečenega časa

Direktorij objektov (object directory)

Upravnik objektov Shramba imen objektov

Simbolični link (symbolic link)

Upravnik objektov Mehanizem za indirektno naslavljanje imena objekta

Profil (profile)

JedroMehanizem za merjenje porazdelitve časa izvajanja znotraj bloka kode

Ključ (key)

Upravnik konfiguracije

Indeksni ključ za naslavljanje zapisov v konfiguracijski podatkovni bazi Windows NT

Vsi procesi, ki delujejo v uporabniškem režimu in želijo, da bodo imele njihove niti dostop do objektov , morajo imeti ročaj (handle) na objekt. Ročaje lahko tvori le upravnik objektov, ki prej preveri pravice take niti in seveda lahko tako ščiti objekte.

Ročaji na vse različne objekte izvajalnika NT so enaki, kar poenostavlja programiranje. Ni razlike med ročajem datoteke, ročajem procesa, ročajem dogodka,..

Struktura objektov Windows 2000

Vsak objekt  pripada določenemu tipu. Da lahko vse objekte enako obravnavamo, imajo v nekaj poljih standardizirane podatke. Vsak objekt ima dva dela: zaglavje objekta in telo objekta. Upravnik objektov uporablja podatke v zaglavju objekta ne glede na njegov tip. Drugi podatki so krmiljeni s strani drugih komponent izvajalnika.

96

Page 97: Handout Os 2

   

Upravnik objektov zagotavlja še nekaj osnovnih servisov, s katerimi lahko aplikacije krmilijo polja v zaglavju objekta. Nekateri od teh servisov so včasih seveda nesmiselni. Pregled teh osnovnih servisov je naslednji:  

Close  Zapre ročaj na objekt 

Duplicate Objekt bo deljen z drugim procesom tako,  da napravimo zanj duplikat ročaja

Query object  Vrne informacijo o standardnih atributih objekta

Query security  Vrne opisnik varnosti objekta

Set security  Spremeni zaščite objekta

Wait for a single object Sinhronizira izvajanje niti z objektom

Wait for multiple objects Sinhronizira izvajanje niti z več objekti

Za manjšo porabo pomnilnika in lažje rokovanje pomni upravnik objektov statične atribute, skupne za nek tip objektov v posebnem objektu, ki mu pravimo objekt "tip" (type object). Ta objekt tudi povezuje vse objekte istega tipa, kot to prikazuje spodnja slika:

97

Page 98: Handout Os 2

Objekti "tip" niso dostopni v uporabniškem režimu

Upravljanje z objekti

Upravljanje z objekti omogoča njihovo poimenovanje. Imena pomnimo v posebnem objektu z imenom direktorij objektov. Njegovo strukturo prikazuje spodnja slika:

Zanimivo je, da je organizacija imen objektov ravno tako drevesno (hierarhično) zasnovana, kot smo navajeni pri popularnem datotečnem sistemu MS DOS. Koren take strukture je tudi tu označen z "\". Koncept prikazuje spodnja slika:

98

Page 99: Handout Os 2

 

Uvedli so še pojem domen objektov (object domains), ki jih lahko vključujemo v druge domene in slednje tako širimo. Koncept ponazoruje slika, ki prikazuje domeno na disketi, vključeno v domeno upravnika objektov.

Po zgledu pri sistemu UNIX so tudi pri Windows NT uvedli simbolične povezave (symbolic links). Simbolična povezava v bistvu omogoča prečne povezave med direktoriji v sicer običajni hierarhično organiziranih datotečnih sistemih. Pri NT so v ta namen uvedli poseben objekt, imenovan "Symbolic link". Ta med svojimi atributi vsebuje nadomestni niz (Substitute string), s katerim nadomesti upravnik objektov ime simbolične povezave. To možnost uporablja izvajalnik NT tudi pri pretvorbi imen naprav MS-DOS (na primer disket in diskov) v imena objektov Windows NT.

99

Page 100: Handout Os 2

Imena objektov so sicer pomembna za shranjevanje in souporabo objektov, rokovanje z objekti pa poteka precej hitreje preko njihovih ročajev. Tako lahko upravnik objektov preskoči pregledovanje imenskega prostora in najde objekte neposredno.

Ročaj objekta NT je indeks v tabelo objektov, ki jo ima vsak proces. Taka tabela ima kazalce na vse objekte, ki jih je dani proces odprl.

Procesi lahko pridobe ročaje s tvorbo lastnih objektov ali z odpiranjem obstoječih. Ročaje lahko podedujejo od drugih procesov ali le-teh dobijo kopijo ročaja. Relacijo med procesi in tabelo objektov prikazuje spodnja slika.

 

Polje "dedovanje" pove, ali bodo procesi, ki jih dani proces tvori, dobili tudi kopijo ročajev iz njegove tabele. Več procesov lahko souporablja objekte tako, da imajo ročaje, ki kažejo na isti objekt.

Ko nek proces konča, pride lahko do brisanja njegovih objektov, vendar le, če nanje ne kažejo ročaji drugih procesov.

Upravnik objektov lahko centralno kontrolira število objektov (in s tem resursov), ki jih procesi izkoriščajo. To lahko primerja z nastavljenimi omejitvami (kvotami).

Zaščita objektov

Zanesljiv operacijski sistem mora ščititi uporabnikove datoteke, pomnilnik in druge resurse. Preprečevati mora poskuse "obvozov" varnostnega mehanizma. Nivoji zaščite so klasificirani na sedem nivojev. Na nivoju C2 so pred NT postavljene naslednje zahteve:

Najava (logon) uporabnikov zahteva identifikacijo z geslom Uporabnik mora imeti na voljo mehanizem, s katerim dovoli drugim uporabnikom

selekcioniran dostop do njegovih resursov

100

Page 101: Handout Os 2

Sistem mora odkrivati in zapisovati vse dogodke, ki so pomembni za varnost (tvorba, dostop, brisanje resursov. Pomni tudi, kateri uporabnik je tako akcijo izvedel.

Preprečiti mora branje informacije s pomnilnika drugim tudi potem, ko je pomnilnik sproščen. Zato ga mora po sprostitvi zbrisati. 

Sistemski administrator lahko te nastavitve tudi spreminja

Sistem tvori za vsakega verificiranega uporabnika po njegovem vstopu poseben objekt, dostopni žeton (access token) in ga prilepi na uporabnikov proces. Vsebina tega žetona je razvidna iz naslednje slike.

Ko hoče kasneje nek proces odpreti ročaj h kakšnemu objektu, pokliče upravnik objektov varnostni monitor referenc (Security reference monitor). Ta na osnovi žetona dostopa, prilepljenega na proces ugotovi, ali proces lahko rokuje z zahtevanim objektom. Kdo lahko pride do objekta in kaj lahko z njim počne, določi ob tvorbi objekta proces, ki ga je tvoril. Začetni seznam pravic je pomnjen v seznamu nadzora dostopov ACL (Access Control List). Poenostavljeno shemo takega seznama ACL vidimo na dnu spodnje slike:  

101

Page 102: Handout Os 2

Elementi seznama ACL, imenovani ACE (Access Control Entry), vsebujejo varnostni ID (ID uporabnika ali skupine) in množico dostopnih pravic. Dostop je lahko dovoljen, prepovedan ali dovoljen po preverjanju.

Levo zgoraj na sliki vidimo še primer dostopnega žetona. ki ga varnostni sistem pregleda, ko dani proces zahteva uporabo objekta.

Procesi in niti

Procesi

Procesi NT/2000 se deloma razlikujejo od procesov pri drugih operacijskih sistemih:  

Implementirani so kot objekti in do njih dostopamo preko upravnika objektov Imajo lahko več niti, ki se izvajajo v skupnem naslovnem prostoru Tako objekti - procesi kot objekti - niti imajo vgrajeno zmožnost sinhronizacije Upravnik procesov ne vzdržuje nobenih relacij oče - sin o procesih, ki jih tvori.

Proces vsebuje naslednje:

102

Page 103: Handout Os 2

Izvršljivi program, ki določa začetno kodo in podatke. Privatni naslovni prostor, ki je del virtualnega prostora, ki je na voljo procesu. Sistemske resurse, kot so semaforji, komunikacijska vrata in datoteke. Najmanj eno nit, sicer se proces ne more izvajati.

 Vsakemu procesu Windows 2000 ustreza v izvajalniku procesni blok (EPROCESS, executive process block). 

 Slika poenostavljeno prikazuje strukture, ki opisujejo proces.

Izvajalnikov procesni blok (EPROCESS) Procesni blok jedra Blok okolja procesa Izvajalnikov blok niti  (ETHREAD) Blok niti v jedru   (KTHREAD) Blok okolja niti

103

Page 104: Handout Os 2

Kako tvorimo proces

 

Odpremo datoteko file (.exe), ki naj bi se izvedla znotraj procesa.

Tvorimo izvajalnikov procesni objekt.

Tvorimo začetno nit (sklad, kontekst, objekt niti izvajalnika).

Obvestimo podsistem Win32 o novem procesu, da lahko tudi sam tvori potreben nov proces in nit

Sprožimo začetno nit.

V kontekstu novega procesa oziroma niti končamo iniciacijo naslovnega prostora (naložimo na primer potrebne DLL) in začnemo izvajati program.

104

Page 105: Handout Os 2

Niti

Niti pri Windows NT so objekti, ki imajo naslednje osnovne komponente oziroma atribute :

ID klijenta Vsebina registrov, ki predstavljajo stanje procesorja Dva sklada, enega uporablja nit v uporabnišken režimu, drugega pa v sistemskem

(kernel) Privatno pomnilno področje, ki ga uporabljajo podsistemi, in knjižnice (vključno

z dinamično povezanimi knjižnicami (DLL)) Dinamična prioriteta niti (to je prioriteta v danem trenutku) Osnovna (base) prioriteta (to je spodnja limita dinamične prioritete) Afiniteto niti, ki pove, na katerih procesorjih večprocesorskega sistema lahko nit

teče. Afiniteta niti je torej seznam, ki je podmnožica afinitete procesa. Opozorilna zastavica (alert status flag), ki pove, da mora nit izvesti asinhroni klic

procedure. Skupni čas izvajanja niti Število prekinitev (kolikokrat je bila nit prekinjena, ne da bi bil njen potek

obnovljen. Začasni dostopni žeton (impersonation token), ki omogoči, da nit izvede operacije

(servis) za nek drug proces. To uporabljajo podsistemi. Zaključna vrata (termination port), to je medprocesni komunikacijski kanal, po

katerem upravnik procesov pove, da je nit končala izvajanje. Izstopni status niti

  Registrom, skladoma in privatnemu pomnilnemu področju pravimo kontekst niti.

Poleg atributov ima vsak objekt niti še naslednje metode (servise):

Tvori nit (create) Odpri nit (open) Vpogled v stanje niti (query) Set stanje niti (set) Dobi kontekst niti (get) Nastavi kontekst niti (set) Tekoča (current) nit Zaključi (terminate) nit Prekini (suspend) nit Obnovi (resume) izvajanje niti Opozori (alert) nit Preveri opozorilno zastavico  niti (test alert) Registriraj zaključna vrata

 

105

Page 106: Handout Os 2

Najbolj preprosta in dokaj pogosta oblika komunikacije med nitmi je sinhronizacija, pri kateri lahko posamezna nit prekine svoje izvajanje in čaka na zaključek operacije neke druge niti.

Objekti, ki tako sinhronizacijo omogočajo, so:

Procesi Niti Datoteke Dogodki Dogodkovni pari Semaforji Časovniki (timer) Mutanti

  Prvi trije objekti imajo seveda druge osnovne naloge, ostali pa služijo le za sinhronizacijo. V vsakem trenutku je sinhronizacijski objekt v signaliziranem ali nesignaliziranem stanju. Pomen tega stanja se od tipa objekta razlikuje. Tako preide nit v signalizirano stanje, ko se izteče, Proces preide v signalizirano stanje, ko konča tudi zadnja od njegovih niti, Časovnik preide v tako stanje po preteku določenega časa. Sinhronizacija poteka tako, da neka nit čaka na signalizirano stanje enega ali več drugih objektov.  

Stanja niti

Initialized  Nit je bila pravkar vzpostavljena.

106

Page 107: Handout Os 2

Ready Nit čaka, da jo razvrščevalnik izbere.

Standby Nit je bila izbrana za izvajanje na danem procesorju.

Running Izveden je bil preklop konteksta na to nit. Tekla bo do prekinitve ali do konca.

Waiting  Nit je prešla v stanje čakanja, ker čaka na sinhronizacijo z nekim objektom, 

Transition  Nit je sicer pripravljena na izvajanje, vendar je njen sklad umaknjen iz pomnilnika. Nit čaka na pomnilnik. 

Terminated Nit se je pravkar zaključila. Njen objekt še obstaja. Izvajalnik bi jo še lahko ponovno inicializiral. 

V nekaterih primerih lahko nit  z opozorilom (alert) sporoči neki drugi niti, naj prekine svoje delo. Ta način sinhronizacije se uporablja pri asinhronem klicu procedur (APC).

Proces jedra in objekti niti

Implementaciji objekta proces ustreza v jedru minimiziran objekt, ki mu pravimo proces jedra (kernel process). Jedro ne pozna tabele objektov, ki jo srečamo pri procesu. Zato direktno dostopa do niti, ki pripadajo procesu jedra. Poleg tega vsebuje ta objekt tudi direktne kazalce na procesovo tabelo strani, na podatke o privzeti prioriteti procesa, na njegovo procesorsko afiniteto in na podatek o trajanju procesa.  

107

Page 108: Handout Os 2

   

Procesorska afiniteta je podatek, na katerih procesorjih lahko ta proces teče (če imamo večprocesorski sistem). Niti imajo svoje lokalne procesorske afinitete, ki so podmnožica procesorske afinitete danega procesa.

Procesorska afiniteta je pomembna pri razvrščanju niti (thread scheduling). Razvrščevalnik izbere posamezno nit glede na njeno prioriteto, nato pa pogleda, na katerem procesorju lahko teče.

Niti imajo (večinoma) spremenljivo prioriteto. Glede na trenutni prednosti nivo čakajo v ustrezni čakalni vrsti. Razvrščevalnik dvigne njen nivo, ko nit zapusti  stanje čakanja na nek vir (waiting state). Vsakič, ko nit prekine, ji prednostni nivo zniža. Tako preidejo računsko intenzivne niti na najnižji (to je osnovni) prednostni nivo.

Ko je nit izbrana za izvajanje, preide končno v tekoče (running) stanje. Pri tem mora priti do preklopa konteksta (context switching). To pomeni, da se vsebina registrov uporabljenega procesorja shrani na sistemski sklad niti (kernel stack). Iz sistemskega sklada izbrane niti pa se rekonstruira nova (torej nekdaj prej shranjena) vsebina registrov.

To zadošča, če  pripadata prekinjena in novoizbrana nit istemu procesu in torej delujeta v istem naslovnem prostoru). V nasprotnem primeru pa mora priti še do rekonstrukcije naslovov strani.

Razvrščanje niti in procesov

Sistem Windows 2000 uporablja  32 prednostnih nivojev:

Šestnajst nivojev realnega časa (16-31)

Petnajst spremenljivih nivojev (1-15)

108

Page 109: Handout Os 2

En sistemski nivo (0), rezerviran za  nit ničelne strani (the zero page thread)

  Niti podedujejo osnovno prednost procesa (base priority).

Tekoča prednost procesa je dinamično spremenljiva v območju 1-15. 

  Razvrščevalnik uporablja čakalno vrsto (dispatcher ready queue), ki je pravzaprav skupina čakalnih vrst, po ena za vsak nivo prednosti. 

109

Page 110: Handout Os 2

 Sistem dvigne prednost niti pa prehodu iz stanja čakanja (na primer po vhodno izhodni operaciji).

Po vsakem izteku časovne rezine (kvantuma) prednost niti zniža (a ne pod bazni nivo)Kvantum časa je časovna rezina, ki je na voljo posameznim nitim v stanju, ko so tekoče.

Še nekaj o scenarijih razvrščanja

 Nit sama preide v stanje čakanja (ker morda čaka na nek objekt)

Nit nadomesti nit z višjo prednostjo, še preden porabi kvantum časa. (zato kasneje nadaljuje s preostankom kvantuma).

110

Page 111: Handout Os 2

Niti je kvantum časa pošel (zato se uvrsti na konec čakalne vrste z novim kvantumom)

Struktura procesov

NT  omogoča sočasno izvajanje aplikacij, pripravljenih za različna okolja (Win32, MS-DOS, OS/2, POSIX). Pri tem si pomaga s takoimenovanimi okoljskimi podsistemi (environment subsystems), ki kot nekakšen vmesnik (API) emulirajo okolje, ki ga nek aplikacijski program pričakuje. Koncept si lahko ogledamo na primeru sistemskega klica za tvorbo novega procesa:

Okna in zaščiteni podsistemi

Uvod v zaščitene podsisteme

Zaščiteni podsistemi  Windows NT so strežni procesi, ki tečejo v uporabniškem režimu. Tvori jih operacijski sistem ob svojem zagonu. Imamo okoljske (environment) podsisteme, ki implementirajo vmesnik zahtevanega operacijskega sistema (takoimenovan API, Application Program Interface), ter skupne (integral) podsisteme, ki

111

Page 112: Handout Os 2

opravljajo naloge osnovnega operacijskega sistema. Tak skupni podsistem je na primer varnostni podsistem. Tako organizacijo ponazoruje spodnja slika:

 

Podsistemi komunicirajo med seboj  s posredovanjem obvestil (message passing). Ključen mehanizem je klic lokalne procedure (LPC), ki je izveden iz  koncepta RPC (klic oddaljene procedure), znanega pri porazdeljenih računalniških sistemih. Vsak podsistem zato vzpostavi komunikacijski kanal (vrata, port), ki je - dosledno s filozofijo Windows NT - realiziran kot objekt.

Ker tečejo podsistemi v uporabniškem režimu, ne morejo direktno spreminjati struktur izvajalnika NT.

Potek komunikacije med klijentov (v našem primeru aplikativnim programom Win 32) in strežnim procesom (v našem primeru podsistemom Win32) z uporabo mehanizma LPC je razviden tudi iz naslednje slike:

112

Page 113: Handout Os 2

   

 Windows NT ohranja koncept dinamično povezanih knjižnjic (DLL). Te imajo med drugim vstopne točke klicanih rutin API (takoimenovane štrclje, stubs). Tako aplikativni program čuti, kot da bi tekel v svojem naravnem okolju. Koncept DLL omogoča tudi delno optimizacijo celotnega sistema, saj ni potrebno prav za vsak servis (posebej) klicati izvajalnika NT.  

Podsistem Win32

113

Page 114: Handout Os 2

Upravnik oken krmili okna na zaslonu, usmerja uporabnikove vhodne interakcije k aplikacijam, prenaša podatke v odložišče (clipboard) ali iz njega in izvaja še več drugih nalog.

Vmesnik grafičnih naprav (Graphics Device interface, GDI) zagotavlja množico rutin API (Application program Interface) za risanje črt, slik, simbolov in teksta na grafičnih napravah (prikazovalniku, tiskalniku,..) Rutine GDI kličeta konzola (za izpis besedil) in Upravnik oken, te rutine pa nato kličejo  gonilnike grafičnih naprav.

Pri Windows  NT 5.0 in Windows 2000 so vmesnik  grafičnih naprav (GDI) in gonilniki grafičnih naprav locirani na nivoju izvajalnika.

Funkcije operacijskega sistema zagotavljajo sinhronizacijo - na splošno večnitnih- aplikacij z dogodki in z drugimi aplikacijami. Zagotavljajo tudi upravljanje s pomnilnikom  skupaj z izvajalnikom, katerega servise lahko direktno kliče.

Virtualni stroj DOS (VDM)

Virtualni stroj DOS (VDM, Virtual DOS Machine) je seja, ki jo odpre uporabnik, ko kliče aplikacijo DOS.

Sistem dopušča  sočasno izvajanje več aplikacij DOS.

Aplikacije DOS so pogosto pisane v zbirnem jeziku in predvidevajo prost dostop do pomnilnika in perifernih naprav ter dostop do funkcij operacijskega sistema DOS. Vsaka taka aplikacija predvideva, da teče sama zase na nekem MS_DOS stroju. VDM daje takim aplikacijam ekvivalentno okolje s privatnim virtualnim naslovnim prostorom. VDM vsebuje v bistvu navidezni operacijski sistem DOS z navideznimi (virtualnimi) gonilniki naprav. Koncept navideznega stroja DOS (VDM) ponazorujeta spodnji sliki:

114

Page 115: Handout Os 2

Koda pod mejo 16MB temelji na 16-bitnih segmentiranih naslovih. Virtualni gonilniki naprav delujejo kot vmesnik med aplikacijo DOS in aparaturno opremo, ki jo krmili sistem.

WOW

(Windows on Windows) / 16- bitne okenske aplikacije

115

Page 116: Handout Os 2

Posredovanje obvestil s klicem lokalne procedure

Niti v različnih procesih lahko med seboj komunicirajo z mehanizmom LPC (Local Procedure Call), ki oponaša uveljavljeni princip klica oddaljene procedure (RPC), poznan pri porazdeljenih sistemih. Pri tem je postopek pri procesih, ki potekajo na istem sistemu NT, optimiziran. Aplikacijski program kliče API rutino v navezani DLL (Dynamic Linked Library), ta pa preko mehanizma LPC (ki je del izvajalnika NT)  pošlje obvestilo  ustreznemu zaščitenemu podsitemu, ki mora izvesti zahtevani servis.

Upravnik virtualnega pomnilnikaFizični ali resnični pomnilnik računalnika je organiziran kot zaporedje bytov, ki so oštevilčeni  od 0 do števila, ki pove zgornjo mejo pomnilnika (minus 1).

Logični pomnilnik (tudi virtualni pomnilnik) je pogled programa na pomnilnik. Naslovi virtualnega pomnilnika so oštevilčeni od 0 do zgornje meje naslovljivega prostora.

Virtualni naslovni prostor je unikaten naslovni prostor, na voljo posameznemu procesu.

116

Page 117: Handout Os 2

  Normalno imajo procesi NT 2GB privatnega naslovnega prostora, operacijski sistem pa preostalih 2GB.

V nekaterih primerih imamo vključeno opcijo, ki omogoča velikost 3GB uporabniškega naslovnega prostora na račun sistemskega

Da bi bilo prepisovanja na disk in nazaj čimmanj, je virtualni naslovni prostor razdeljen v bloke enake dolžine, imenovane strani.

Če neka nit dostopa do neveljavne strani, pride do izpada strani (page fault). V tem primeru naloži sistem v pomnilnik stran, ki je povzročila napako, in še nekaj strani v njeni okolici.

Ko  je zapolnjen že ves fizični pomnilnik, pride do zamenjave strani po principu LRU (Least Recently Used) oziroma FIFO (First in-First out). Prva strategija je uporabljena na enoprocesorskih, druga pa na večprocesorskih sistemih. 

Uporabniške aplikacije uporabljajo 32-bitne virtualne naslove. Vsakemu virtualnemu naslovu ustreza sistemska struktura PTE (Page Table Entry), ki vsebuje fizično adreso, dodeljeno temu virtualnemu naslovu.

117

Page 118: Handout Os 2

Tabele strani torej vsebujejo PTE. Te imajo dve polji: Takoimenovani PFN (Page Frame Number), ki pove  stran, kjer se nahajajo podatki, ter vrsto zastavic, ki opisujejo status in zaščito strani.

  Izgled strukture PTE pri implementaciji Windows NT na Intelovi arhitekturi.  Vsak proces ima en direktorij strani (Page directory), ki ga sestavljajo elementi PDE (Page Directory Entries) 

Posamezni PDE kaže na neko tabelo strani danega procesa. Takih tabel je več, saj se tvorijo po potrebi med izvajanjem procesa.

Imamo tabele strani, ki opisujejo sistemski naslovni prostor, in tabele strani, ki opisujejo privatni naslovni prostor procesa.

Primitivi, ki jih uporablja upravnik navideznega pomnilnika, so sekcije  (section objects).  Take sekcije uporablja en proces, lahko pa so v souporabi več procesov.  Tako  Windows NT omogoča koncept souporabljenega pomnilnika (shared memory). Po tem konceptu lahko določeno stran, ki je enaka v  virtualnih naslovnih prostorih dveh ali več procesov, le-ti vidijo in souporabljajo.

Strani, ki so sproščane s strani procesov, se vračajo v seznam "standby", če niso bile spremenjene, sicer pa končajo najprej v seznamu spremenjenih strani, dokler jih sistem (modified page writer) ne zapiše na disk. Ta zapisovalec se zbudi, če postane seznam

118

Page 119: Handout Os 2

spremenjenih strani predolg ali pa če postaneta seznama prostih oziroma zbrisanih strani prekratka.

Prekinitve in izjeme

Kaj so prekinitve?

Windows 2000 poznajo dve vrsti dogodkov, ki spremenijo potek izvajanja ukazov. Prekinitve (interrupts) in izjeme (exception). Prekinitve so asinhroni dogodki, ki niso povezani s tem, kar procesor trenutno izvaja. Prekinitve najpogosteje sprožijo vhodno/izhodne enote, ura..... Lahko so omogočene ali pa onemogočene.

Izjeme pa so sinhroni dogodki, ki so povezani s trenutnim programom. Primeri izjem: deljenje z nič, kršenje pomnilniškega prostora....

Obe vrsti prekinitev lahko sproži tako strojna oprema kot programska oprema. "Bus error exception" je primer izjeme, ki jo je sprožila strojna oprema. Deljenje z nič pa je primer izjeme, ki jo je sprožil program. Prav tako lahko vzhodno/izhodna naprava sproži prekinitev ali pa samo jedro (kernel) sproži prekinitev (APC ali DPC).

Pod pastjo razumemo mehanizem, s katerim procesor ob pojavi prekinitve ali izjeme ujame tekočo nit in preskoči iz uporabniškega v sistemski režim ter skoči na izvajanje kode na neki vnaprej definirani  lokaciji.

Delovanje prekinitev in izjem?

Ko se zgodi dogodek, ki povzroči prekinitev izjemo ali pa klic sistemskega servisa, prevzame nadzor rokovalnik pasti(trap handler). Le ta začasno prepove nove prekinitve. Tvori okvir pasti (trap frame), v katerega shrani stanje prekinjene niti in omogoči prekinitve. Glede na vrsto zahteve, ki je povzročila klic rokovalnika pokliče ustrezen modul. Če je bila vzrok prekinitev potem pokliče prekinitveni distributor. V primeru sistemskega klica prepusti nadzor sistemskemu distributorju. V primeru ostalih pasti pa prepusti izvajanje distributorju izjem.

119

Page 120: Handout Os 2

   

Aparaturne prekinitve

Distributor prekinitev, ki je del rokovalnika pasti se torej odziva na prekinitve. Distibutor najprej ugotovi izvor prekinitve in potem prenese nadzor v zunanjo rutino ki potem servisira prekinitev ali pa v notranjo kernel rutino. Zunanjo rutino morajo zagotavljati gonilniki naprave, notranje rutine pa zagotavlja kernel sam. Različni procesorji prepoznajo različno veliko in raazlične tipe prekinitev. Kernel definira tabelo IRQL (interrupt request level). V tej tabeli so urejene prekinitve po prioriteti. Višja prekinitev ima višjo prioriteto. Procesor ima svoj kazalec IRQL, ki kaže v to tabelo in se spreminja glede na prekinitve. Prekinitve, ki ležijo pod tem kazalcem so onemogočene, dokler se kazalec IRQL ne pomakne navzdol.    

120

Page 121: Handout Os 2

   

Podobno vlogo, kot jo ima pri nekaterih drugih operacijskih sistemih prekinitveni vektor, igra pri Win 2000  distribucijska tabela prekinitev IDT (Interrupt Dispatch Table). IRQL procesorja služi kot kazalec tudi v to tabelo. IDT je  struktura, na katero kaže processor control region(PCR).

Pri večprocesorskih sistemih imamo ločeno tabelo IDT.  

Prekinitve za klice zamaknjenih procedur DPC (deferred procedure call)

Periferne naprave povzročajo aparaturne prekinitve. Jedro  pa tvori programske prekinitve. Posebnost Win 2000 so prekinitve za klice zamaknjenih procedur (DPC, Deferred Procedure Call). DPC so sistemske funkcije, katerih izvedba ima nižjo prednost kot obravnava aparaturnih prekinitev in  lahko malo počaka.

121

Page 122: Handout Os 2

Tipična uporaba DPC je v gonilnikih aparaturnih naprav. Pri teh po vsaki aparaturni prekinitvi sistem v servisni rutini (ISR) samo shrani stanje naprave, vse ostalo pa opravi ustrezna DPC (tudi ta v sistemskem (kernel) načinu), ko bo računalnik za to našel čas.

Sistem DPC je predstavljen z DPC objektom, kateri vsebuje naslov sistemske funkcije, ki jo bo klical kernel, ko bo izvajal DPC prekinitev. DPC objekti shranjeni v vrsti in čakajo, da se bo zgodila DPC prekinitev. V vrsto najpogosteje nalagajo goniliniki naprav, ki se izvajajo z višjim IRQL-om procedure, ki se lahko izvedejo kasneje. Ko IRQL pade pod nivo DPC kernel sam sproži DPC prekinitev in zamaknjene procedure se začnejo izvajati v sistemskem načinu.  

Prekinitve za klice asinhronih procedur APC (asynchronous procedure call)

Podoben mehanizem so klici asinhronih procedur (APC, Asynchronous Procedure Call), ki jih lahko izvajamo bodisi v sistemskem, bodisi v uporabniškem režimu. V razliko od DPC se APC izvajajo v naslovnem prostoru določene uporabniške niti. Uporabljamo jih na primer za zaključek neke vhodno-izhodne operacije, ki jo je zahtevala neka aplikacija.

122

Page 123: Handout Os 2

 

Sama koda tako ISR, kot DPC in APC je običajno del nekega gonilnika naprave (device driver), podatkovni del, ki je spravljen (vsaj za DPC in APC) v obliki ustreznega (DPC oziroma APC) objekta.

APC zagotavljajo izvedbo code v  kontekstu posamezne uporabniške niti. Prav tako so predstavljene z APC objektom in čakajo na izvršitev v APC vrsti. Za razliko od DPC, ki ima eno vrsto za cel sistem, ima vsaka nit svojo APC vrsto. Ko zaprosimo za uvrstitev APC procedure v vrsto, kernel sam uvrsti vrsto v nit, v kateri se bo izvajala. APC procedure lahko izvajamo v uporabniškem ali pa sistemskem načinu. Največkrat se uporabljajo, da se zapiše I/O informacija v pravo nit.

Programske prekinitve

Če je do programske prekinitve prišlo v sistemskem režimu (kernel mode), razvrščevalnik izjem (exception dispacher) enostavno pokliče ustrezno rutino.  

123

Page 124: Handout Os 2

Če pa pride do izjeme v uporabniškem režimu, kliče ta razvrščevalnik ustrezna vrata (debugger port ali exception port). Tako so na primer realizirane prekinitvene točke (breakpoints) razhroščevalnikov.

Vhodno - izhodni sistem

Komponente vhodno izhodnega sistema

Upravnik vhodno izhodnega podsistema (IO manager) povezuje aplikacije in sistemske komponente  na virtulne, logične in fizične naprave in določa infrastrukturo, ki podpira gonilnike naprav.

124

Page 125: Handout Os 2

Gonilnik naprave predstavlja vmesnik do določene naprave.  Lahko pa posredujejo preko upravnika (IO) ukaze drugim gonilnikom naprav.

PnP upravnik (Plug and Play) sodeluje z upravnikom IO in posebnim gonilnikom "bus driver" za nadzor aparaturne opreme in odkrivanje ter odzivanje na dodajanje in odklapljanje naprav. 

PnP upravnik in gonilniki vodila skrbe za nalaganje gonilnikov takih naprav. "power manager" sodeluje tako z upravnikom IO kot s posameznimi gonilniki

naprav pri vklopu in izklopu napajanja. Rutine  WMI (Windows Management Instrumentation)  s pomočjo WDM

(Windows Driver Model)   omogočajo gonilnikom komunikacijo s servisom WMI  v uporabniškem režimu

"Registry"  je nekakšna podatkovna baza z opisom osnovnih naprav, ki so priključene na sistem in služi za nastavitve ter za pravilno iniciacijo gonilnikov.

Datoteke INF  so instalacijske datoteke gonilnikov.  

Pregled

Spomnimo se zgradbe operacijskega sistema in se posvetimo upravniku vhoda oziroma izhoda! Ta sam po sebi ne opravlja nobenih vhodno-izhodnih operacij. Njegova naloga je, da za vsak vhodno-izhodni zahtevek sestavi podatkovni paket IRP (I/O request packet) in ga posreduje ustreznemu gonilniku. Ko le-ta opravi svoje delo, prejme od njega podoben paket in ga posreduje naprej ali pa razpakira in vrne  rezultat aplikaciji.

Potek vhodno izhodnih operacij

125

Page 126: Handout Os 2

Aplikacije (Win32, POSIX ali OS2) kličejo  dogovorjene funkcije sistema, te pa upravnik IO.  Vse podatke beremo ali pišemo kot preproste tokove bajtov. 

Programi izvajajo vhodno izhodne operacije na virtualnih datotekah.  Šele upravnik IO kliče ustrezen gonilnik naprave. S tem dosežemo abstrakcijo in tudi fleksibilnost. 

Upravnik IO formira za vsako zahtevano operacijo paket IRP (I/O request packet) in ga posreduje ustreznemu gonilniku.

Vrste gonilnikov

Imamo gonilnike na nivoju jedra in gonilnike na uporabniškem nivoju. Kernel-mode gonilniki, so edini, ki direktno dostopajo do naprav  

Gonilniki na nivoju jedra

Imamo več tipov gonilnikov kernel-mode: Nizkonivojski gonilniki aparaturne opreme Gonilniki dane vrste naprav (Class drivers) Gonilniki, specifični glede na vrsto vrat in adapterjev (Port drivers, Miniport

drivers)

126

Page 127: Handout Os 2

Gonilniki datotečnih sistemov (File system drivers) Gonilniki za dodatno predelavo vhoda/izhoda (File system filter drivers)

Gonilniki datotečnega sistema (File system drivers)  sprejemajo zahtevke za datoteke in sami naprej posredujejo zahtevke gonilnikom pomnilnih periferij in omrežnim gonilnikom.

Gonilniki  Windows 2000  so gonilniki, ki se po potrebi lahko povežejo  z upravnikoma PnP in  "power manager". Vključujejo tudi gonilnike za pomnilno periferijo in omrežne adapterje.

"Legacy drivers" so gonilniki, pisani za Windows NT, ki nespremenjeni tečejo tudi na  Windows 2000. V razliko od gonilnikov Windows 2000 ne podpirajo krmiljenja napajanja in dela z upravnikom PnP.

"Win32 subsystem display drivers" pretvarjajo aparaturno neodvisne grafične zahtevke  v aparaturno odvisne. Za popolno grafično podporo potrebujejo še ustrezne gonilnike  v jedru (kernel-mode video miniport driver).  Ti gonilniki (v jedru) skrbe na primer za resolucijo zaslona, osveževalno frekvenco, značko (cursor) na zaslonu ipd.

Gonilniki WDM spoštujejo takoimenovani "Windows Driver Model" (WDM), ki je implementiran na sistemih  Windows 2000, Windows 98 in Windows Millennium Edition. Taki gonilniki imajo kompatibilno izvorno kodo, pogosto pa so tudi binarno kompatibilni.

V skupino gonilnikov WDM sodijo gonilniki vodil ( bus drivers)  (primeri takih vodil so: PCMCIA, PCI, USB, IEEE 1394, ISA), funkcijski gonilniki in filterski gonilniki)  

Gonilniki v uporabniškem režimu

127

Page 128: Handout Os 2

Poleg navedenih podpira sistem Windows 2000 še več gonilnikov v uporabniškem režimu:

Tiskalniški gonilniki Win32 preslikajo aparaturno neodvisne grafične zahtevke v ukaze tiskalniku in jih posredujejo ustreznemu gonilniku v jedru.   Gonilniki virtualnih naprav (Virtual device drivers ,VDD)  služijo za emulacijo 16 bitnih aplikacij  MS-DOS. Prestrezajo naslavljanja vrat in jih preslikajo v klice funkcij Win32, te pa šele kličejo ustrezni gonilnik naprave

Vhodno- izhodne operacije

Vhodno izhodne funkcije:

klasične funkcije: open, close, read, write

Poleg tega še asinhron vhod/izhod ter preslikane (maped) datoteke.

Preslikan (maped) vhod/izhod pomeni zmožnost, da gledamo na datoteko na disku kot na del virtualnega pomnilnika procesa.  

128

Page 129: Handout Os 2

   

Obstoja še možnost hitrega vhoda/izhoda, kjer sistem lahko preskoči mehanizem IRP in kliče takoj gonilnik naprave ali upravnik medpomnilnika.

Plasti gonilnikov naprav

129

Page 130: Handout Os 2

Struktura gonilnika

130

Page 131: Handout Os 2

Gonilnik ima naslednje tipične rutine:

Inicijacijsko rutino: To pokliče sistem ob naložitvi gonilnika

Začetno rutino: S to rutino sproži gonilnik postopke za začetek prenosa podatkov.

Skupino dispečerskih rutin (na primer open, close, read, write,..): To so v bistvu glavne rutine, ki jih nudi gonilnik  navzven. Ko želimo izvedbo neke vhodno izhodne operacije, tvori upravnik vhoda-izhoda nov paket IRP in ga posreduje primerni dispečerski rutini.

Prekinitveno servisno rutino (ISR) : opravi le najnujnejše, saj dela v režimu, ko ni prekinjana. Zato nato uvrsti v posebno čakalno vrsto "rutino z zamaknjenim klicem"  (DPC, Deferred Procedure Call), ki bo kasneje opravila preostalo delo. Prekinitveno servisne rutine imajo le gonilniki prekinitveno gnanih naprav. Gonilnik datotečnega sistema  na primer take rutine nima.

Rutino z zamaknjenim klicem (DPC):  Ta opravi večino vhodno - izhodnega dela, ki ji ga je zapustila prekinitveno servisna rutina.

Eno ali več zaključnih rutin

Eno ali več rutin za prekinitev vhodno izhodne operacije

Odlagalno (Unload) rutino: Ta sprosti sistemske resurse, ki jih zaseda gonilnik. Gonilnike lahko nalagamo ali odlagamo med delovanjem sistema.

Rutino za čiščenje pri zaustavitvi računalnika

"Error logging" rutino. Ta obvešča o napakah upravnika vhoda/izhoda, ta pa povzroči zapis informacije o tem dogodku v "log" datoteko.

131

Page 132: Handout Os 2

Problem sinhronizacije

Gonilniki morajo imeti sinhroniziran dostop do skupnih podatkov, sicer lahko pride do napak.

   

Na enoprocesorskih sistemih zagotavlja sinhronizacijo dvig IRQL pred spreminjanjem neke strukture. Pri večprocesorskih sistemih pa to ne zadošča in se uporablja tehnika "spinlock".

Podatkovne strukture

Vhodno izhodne zahtevke predstavljajo štiri osnovne strukture: Objekte datoteka, objekte gonilnik, objekte naprava in vhodno-izhodne pakete (IRP) (file object, driver object, device object)

Objekt file

Ta objekt je pomnilniška predstavitev souporabljivega (sharable) vira in ne vir sam po sebi.

Kako ga odpremo:

132

Page 133: Handout Os 2

 

Objekt gonilnik in objekt naprava

Ko neka nit odpre ročaj na objekt datoteka (file)¸ mora upravnik vhoda/izhoda ugotoviti,katere gonilnike bo moral poklicati za izpolnjevanje zahtevkov. Gonilnik objekt predstavlja posamezni gonilnik v sistemu, objekt naprava pa predstavlja fizično,logično ali virtualno napravo in opisuje njene lastnosti.

133

Page 134: Handout Os 2

Paketi vhodno izhodnih zahtevkov

Ko neka nit terja od vhodno-izhodnega sistema neko storitev, tvori upravnik vhodno izhodnih zahtevkov paket z vhodno-izhodnim zahtevkom (IRP = I/O Request Packet). Tak paket vsebuje dva dela:

Fiksni del (zaglavje) vsebuje podatke o tipu in velikosti zahtevka, ali je zahtevek sinhron ali asinhron, kazalec na mmorebitni medpomnilnik in informacijo o stanju.

Dinamični del (stack location) vsebuje funkcijsko kodo, funkcijsko specifične parametre in kazalec na objekt datoteka (file) kličočega programa.

Sistem pomni IRP-je  v vrsti, ki ustreza niti, ki je tak zahtevek sprožila.    

134

Page 135: Handout Os 2

135

Page 136: Handout Os 2

Servisiranje vhodno-izhodnega zahtevka

Uvrščanje in zaključek sinhronega zahtevka

   

136

Page 137: Handout Os 2

Servisiranje prekinitvenega zahtevka naprave

       

137

Page 138: Handout Os 2

   

Zaključek vhodno izhodnega zahtevka

Sistem mora kopirati podatke iz sistemskega dela pomnilnika v virtualni naslovni prostor klicočega programa. Zato mora upravnik vhoda/izhoda  prepisati podatke v okolje (kontekst) niti kličočega programa To naredi tako, da  niti uvrsti "kernel mode" asinhroni klic procedure (APC). Ta procedura se namreč izvaja v kontekstu klicoče niti. DPC pa

138

Page 139: Handout Os 2

lahko teče v kateremkoli kontekstu, vendar ne more uporabljati uporabniškega naslovnega prostora.

 Ko kličoča nit spet dobi besedo, se izvede viseča AFC, ki kopira morebitne podatke  in povratni status v naslovni prostor kličočega programa in sprosti IRP, ročaj objekta datoteke pa se sprevrže v "signalizirano" stanje.

139

Page 140: Handout Os 2

140

Page 141: Handout Os 2

Vhodno izhodni zahtevki in plastni gonilniki

Upravnik medpomnilnikaUpravnik medpomnilnika (cache manager) je množica funkcij in niti v sistemskem (kernel)) režimu. Te so na voljo lokalnim in omrežnim sistemskim gonilnikom. Pri vmesnem pomnenju podatkov uporablja tehniko virtualnih blokov (odmikov znotraj datoteke), medtem ko precej drugih podobnih sistemov uporablja tehniko logičnih blokov (odmikov v particiji diska).

Koherenca vmesnega pomnenja

Upravnik medpomnilnika mora zagotavljati, da dobi vsak proces, ki dostopa do njega, najbolj sveže podatke. Zagotavljati mora to, da obstaja le ena predstavitev odprtih (mapiranih datotek).

141

Page 142: Handout Os 2

  Koherenca vmesnega pomnenja je nekoliko bolj zahtevna pri dostopu do omrežnih podatkov, ker ti terjajo pogostejše brisanje in shranjevanje (purge, flush).   Sistem NTFS omogoča tudi popravljanje okvar v primeru izpadov. To pomeni, da moramo imeti možnost, da vse vhodno-izhodne operacije v primeru prekinitve ali povsem pozabimo ali v celoti rekonstruiramo.  Sistem zato beleži vse operacije, ki jih namerava storiti, v posebno datoteko (Log file). Srečamo se s pojmom metapodatkov (metadata), ki so namenjeni le spremembam datotečnega sistema (ne pa podatkom samim). Seveda mora biti beležka o predvideni spremembi zapisana na disk pred samo spremembo.

Struktura medpomnilnika

Medpomnilnik uporablja območje sistemskih virtualnih naslovov namesto območja fizičnega pomnilnika.

Naslovni prostor je razdeljen v 256 KB velike rezine, ki jim pravimo pogledi (views).

142

Page 143: Handout Os 2

  Pri prvi vhodno-izhodni informaciji preslika tak pogled na področje datoteke, ki je poravnano na 256 KB v prosto rezino medpomnilnika. Sledi pogled na drugo področje itd.

Sicer pa uporablja pri teh preslikavah princip Round-Robin. 

Med samim branjem ali zapisovanjem je tak pogled aktiven. Ko porabimo vso zalogo pogledov, pri nadaljnjih pogledih zasede upravnik medpomnilnika z novim pogledom tistega, ki je bil najdlje neaktiven.

Tudi sam medpomnilnik uporablja tehniko delovne množice strani. Virtualna velikost sistemskega   medpomnilnika je odvisna od velikosti fizičnega pomnilnika in je tipično več 10MB (privzeto 64 MB).

143

Page 144: Handout Os 2

NTFS

Interna struktura NTFS

NTFS in drugi datotečni sistemi so predstavljeni kot naložljivi gonilniki (loadable drivers). Aplikacije jih kličejo posredno. 

 

 

Okoljski podsistemi NT kličejo sistemske servise NT, ti pa nato ustrezne gonilnike  Aplikativni programi dostopajo do datotek tako, kot do drugih objektov: preko ročajev na objekte. 

Slika prikazuje podatkovne strukture, ki povezujejo ročaj datoteke z datotečno strukturo na disku.   

144

Page 145: Handout Os 2

NTFS - struktura na disku

Osnova strukturi NTFS je zvezek (volume). Ta ustreza logični particiji na disku in ga dobimo s formatiranjem (dela) diska za NTFS. 

         

145

Page 146: Handout Os 2

Disk ima lahko enega ali več zvezkov. lahko pa imamo zvezek, ki zaseda več diskov (na primer fault tolerant volume).  Za NTFS je osnovna alokacijska enota na disku grozd (cluster) in ne sektor. Zato je NTFS neodvisen od fizične velikosti diska. 

NTFS naslavlja fizične lokacije na disku preko takoimenovanih LCN (Logical Cluster Numbers).

 

Do podatkov v posameznih datotekah pridemo preko takoimenovanih VCN (Virtual Cluster Numbers), ki se za vsako posamezno datoteko štejejo od 0 naprej. VCN niso nujno zvezni in jih preslikujemo na poljubno število LCN v danem zvezku

   Srce strukture NTFS v zvezku (na disku) je glavna tabela datotek (MFT, Master File table). 

To je polje datotečnih zapisov. Vsak tak  zapis je dolg 1k, ne glede na velikost grozdov. Za vsako datoteko na disku ima MFT eno vrstico, vključno z vrstico za samo MFT.

146

Page 147: Handout Os 2

Poleg tabele MFT je na zvezku še množica metadata datotek.

NTFS - toleranca napak

Volume set uporabljamo za konsolidiranje večjega števila neizkoriščenih prostorov na diskih v enoten zvezek. Volume set  je en logični zvezek, ki ga sestavlja do 32 področij prostora na enem ali več diskih. 

Z orodjem "Windows NT Disk Administrator" združimo ta področja v enoten volume set. in ga formatiramo za izbrani datotečni sistem.

Slika kaže tak volume set, ki je označen kot pogon D:

147

Page 148: Handout Os 2

Stripe set (stripe =  proga) je zaporedje več particij (vsaka particija na svojem disku), ki skupaj predstavljajo en logični zvezek. Vse particije morajo biti enako velike.  Sistem tak  zvezek optimizira glede na čase dostopa tako, da podatke primerno porazdeli po več fizičnih diskih. Primer take porazdelitve ponazoruje naslednja slika.

 Taka organizacija je primerna predvsem pri sistemih z veliko gostoto dostopov do diskov.   

 

Zrcalne množice (mirror sets) imajo vsebino particije enega diska zrcaljeno v enako veliki particiji na drugem disku.

Stripe set s parnostjo zagotavlja tolerantnost do napak tako, da rezervira ekvivalent enega diska za vsak stripe. Vidimo, da parnost kroži med diski, kar povečuje hitrost prenosa podatkov. 

148

Page 149: Handout Os 2

Ukrepi v primeru okvarjenih grozdov.  Če sistem odkrije slab sektor, restavrira podatke in slab sektor nadomesti, če se da.   

   Ko NTFS odkrije slab sektor, preveže celoten grozd, v katerem se tak sektor nahaja. 

V primeru, da se je to zgodilo med branjem na redundančnem zvezku, lahko restavrira podatek, sicer pa le vrne ugotovitev, da je podatek napačen, v bodoče pa tak slab sektor ne bo več klican. 

149

Page 150: Handout Os 2

     

150