proiectarea sistemelor de operare

64
1 PROIECTAREA SISTEMELOR DE OPERARE SUB 1MEMORIA CACHE; STRUCTURI DE DATE Structura unui buffer Un buffer consta in doua parti: - o zona de date (contine datele de pe disc) - un antet (identifica bufferul) Antetul unui buffer contine: - un camp numar de dispozitiv (reprezinta numarul sistemului de fisiere logic) - un camp numar de bloc - un camp de stare - un pointer la zona de date a bufferului - doua seturi de pointeri, folositi de algoritmi de alocare a bufferelor o pointer la bufferul anterior din lista de hash o pointer la bufferul urmator din lista de hash o pointer la bufferul anterior din lista bufferelor libere o pointer la bufferul urmator din lista bufferlor libere Starea unui buffer Este o combinatie intre urmatoarele conditii: - bufferul este momentan blocat (locked, busy) - bufferul contine date valide - kernelul trebuie sa scrie continutul bufferului pe disc inainte de a realoca bufferul (delayed- wait) - kernelul momentan citeste sau scrie continutul bufferului pe disc - un proces asteapta ca bufferul sa devina liber Lista bufferelor libere Bufferele din listele hash

Upload: adrian0921

Post on 20-Jan-2016

112 views

Category:

Documents


1 download

DESCRIPTION

Proiectarea Sistemelor de Operare

TRANSCRIPT

Page 1: Proiectarea Sistemelor de Operare

1

PROIECTAREA SISTEMELOR DE OPERARE

SUB 1MEMORIA CACHE; STRUCTURI DE DATE Structura unui buffer

Un buffer consta in doua parti:

- o zona de date (contine datele de pe disc)

- un antet (identifica bufferul)

Antetul unui buffer contine:

- un camp numar de dispozitiv (reprezinta numarul sistemului de fisiere logic)

- un camp numar de bloc

- un camp de stare

- un pointer la zona de date a bufferului

- doua seturi de pointeri, folositi de algoritmi de alocare a bufferelor

o pointer la bufferul anterior din lista de hash

o pointer la bufferul urmator din lista de hash

o pointer la bufferul anterior din lista bufferelor libere

o pointer la bufferul urmator din lista bufferlor libere

Starea unui buffer

Este o combinatie intre urmatoarele conditii:

- bufferul este momentan blocat (locked, busy)

- bufferul contine date valide

- kernelul trebuie sa scrie continutul bufferului pe disc inainte de a realoca bufferul

(delayed- wait)

- kernelul momentan citeste sau scrie continutul bufferului pe disc

- un proces asteapta ca bufferul sa devina liber

Lista bufferelor libere

Bufferele din listele hash

Page 2: Proiectarea Sistemelor de Operare

2

Scenarii pentru regăsirea unui buffer:

1. Kernel-ul găseşte blocul în lista hash şi buffer-ul său este liber.

2. Kernel-ul nu găseşte blocul în lista hash şi alocă un buffer din lista buffer-elor libere

( free list ).

3. Kernel-ul nu găseşte blocul în lista hash şi, în încercarea de a aloca un buffer din free

list( ca în scenariul 2 ), găseşte un buffer marcat ca ―delayed-write‖. Kernel-ul trebuie să

scrie acest buffer pe disc şi să aloce alt buffer.

4. Kernel-ul nu găseşte blocul în lista hash şi lista buffer-elor libere este goală.

5. Kernel-ul găseşte blocul în lista hash dar buffer-ul este momentan ocupat ( ―busy‖ ).

Page 3: Proiectarea Sistemelor de Operare

3

SUB 2MEMORIA CACHE; ALGORITMUL GETBLK Algoritmul getblk

intrari:numarul sistemului de fisiere

numarul blocului

iesire:buffer blocat care poate fi asociat blocului

{

while(bufferul nu este gasit)

{

if(blocul este in lista hq)

{

if(buffer ocupat) /*scenariul5*/

{

sleep(evenimentul buffer devine liber);

continue; /*salt la while*/

}

marcheaza bufferul ocupat; /*scenariul1*/

sterge bufferul din FLB;

return buffer;

}

else /*blocul nu este in lista hq*/

{

if(nu exista buffere in FLB) /*scenariul4*/

{

sleep(pana cand orice buffer devine liber);

continue; /*salt la while*/

}

Starge bufferul din FLB;

if(bufferul marcat pentru scriere intarziata) /*scenariul3*/

{

scriere asincrona a bufferului pe disc;

continue; /*salt la while*/

}

/*scenariul2—gasirea unui buffer liber*/

sterge bufferul din lista hq;

pune bufferul in noua lista hq;

return buffer;

}

}

}

Cand citeste date dintr-un anumit bloc disc,nucleul verifica daca blocul este in pool.

Daca nu este ii asigneaza un buffer liber. Cand scrie datele unui anumit bloc disc, nucleul

verifica daca blocul este in pool-ul de buffere, iar daca nu este, asigneaza un buffer liber pentru

acest bloc. Algoritmii pentru citirea si scrierea blocurilor disc utilizeaza algoritmul getblk pentru

alocarea de buffere de pool.

Page 4: Proiectarea Sistemelor de Operare

4

Exista cinci scenarii tipice pe care nucleul le urmeaza in algoritmul getblk pentru

alocarea unui buffer pentru un bloc disc:

1. Nucleul gaseste blocul in lista hq, iar bufferul este liber;

2. Nucleul nu gaseste blocul in lista hq, astfel ca el alocaun buffer din FLB;

3. Nucleul nu gaseste blocul in lista hq si incercand sa aloce un buffer din FLB (ca in

scenariul 2), il gaseste marcat delayed-write. Nucleul trebuie sa scrie acest buffer pe disc

si sa aloce alt buffer;

4. Nucleul nu poate gasi blocul in lista hq, iar FLB este goala;

5. Nucleul gaseste blocul in lista hq, dar bufferul este momentan ocupat

Page 5: Proiectarea Sistemelor de Operare

5

SUB 3ALG. BREAD, BREADA, BWRITE

După prezentarea algoritmului de alocare a bufferelor, procedurile pentru citirea şi scrierea

blocurilor disc vor fi mai uşor de înţeles. Pentru a citi un bloc disc , un proces foloseşte

algoritmul getblk pentru a-l căuta în buffer cache, nucleul îl poate returna imediat fără citirea

fizică a blocului de pe disc. Dacă nu este în memoria cache nucleul apelează driverul de disc

pentru a "planifica" o cerere de citire şi se pune în aşteptare până la terminarea operaţiilor de I/O.

Driverul de disc specifică controlerului de disc că doreşte să citească date, iar acesta transmite

apoi datele la buffer. În final, controlerul de disc întrerupe procesorul când s-au terminat

operaţiile de I/O şi rutina de tratare a întreruperii de disc trezeşte procesele care aşteaptă,

conţinutul blocului disc fiind acum în buffer. Algoritmul bread

algoritm bread /* citire bloc */

intrare: numărul blocului din sistemul de fişiere;

ieşire: buffer conţinând date;

{

obţine buffer pentru bloc (algoritm getblk);

if (datele din buffer sunt valide)

return (buffer);

iniţiază operaţia de citire a discului;

sleep (până la încheierea operaţiei de citire)

return (buffer); }

Modulele de nivel înalt ale nucleului (cum ar fi subsistemul de fişiere) pot anticipa

necesitatea unui al doilea bloc disc când un proces citeşte secvenţial un fişier.

Modulele solicită a doua operaţie asincronă de I/O în speranţa că datele vor fi în memorie

când va fi nevoie de ele, sporind astfel performanţele sistemului. Pentru a realiza aceasta, nucleul

execută algoritmul de citire în avans a blocului, breada :nucleul verifică dacă primul bloc este în

memoria cache şi, dacă nu este, invocă driverul de disc pentru a citi acel bloc. Dacă al doilea

bloc nu este în bufferul cache, nucleul instruieşte driverul de disc să-l citească asincron. Apoi

procesul se pune în aşteptare până când operaţiile de I/O cu primul bloc s-au terminat.

Algoritmul breada

algoritm breada /* citire bloc şi citire în avans */

intrări: (1) numărul blocului din sistemul de fişiere pentru citire imediată;

(2) numărul blocului din sistemul de fişiere pentru citire asincronă;

ieşire: buffer cu date din citirea imediată;

{

if (primul bloc nu este în memoria cache);

{

obţine buffer pentru blocul (1) (algoritm getblk);

if (datele din buffer nu sunt valide)

iniţiază citirea de pe disc;

}

if (blocul (2) nu este în memoria cache)

{

obţine buffer pentru al doilea bloc (algoritm getblk);

if (datele din buffer sunt valide)

Page 6: Proiectarea Sistemelor de Operare

6

eliberează bufferul (algoritm brelse);

else

iniţiază citirea de pe disc;

}

if (blocul (1) era iniţial în memoria cache)

{

citeşte blocul (1) (algoritmul bread);

return buffer;

}

sleep (până când primul buffer alocat conţine date valide);

return buffer;

}

Nucleul informează driverul de disc că are un buffer al cărui conţinut ar trebui scris, iar

driverul planifică blocul pentru operaţii de I/O.

Dacă scrierea este sincronă, procesul apelant se pune în aşteptare până la terminarea

operaţiilor de I/O, iar la trezire eliberează bufferul.

Dacă scrierea este asincronă, nucleul începe scrierea pe disc, dar nu aşteaptă terminarea

acesteia. Nucleul va elibera bufferul la terminarea operaţiilor I/O.

Algoritmul bwrite

algoritm bwrite /* scriere bloc */

intrare: buffer;

ieşire: niciuna;

{

iniţiază scrierea pe disc;

if (operaţiile de I/O sunt sincrone)

{

sleep (până la terminarea operaţiilor de I/O);

eliberează bufferul (algoritm brelse);

}

else if (bufferul este marcat pentru scriere întârziată)

marchează bufferul să fie pus în capul FLB;

}

Page 7: Proiectarea Sistemelor de Operare

7

SUB 4INODURI

Fiecare fisier Unix are un sinur inod. I-nodurile sunt structuri ale sistemului de operare

care contininformatii necesare unui proces despre fisierul respectiv, cum ar fi: proprietarul

fiserului, drepturile de acces, marimea fisierului si localizarea datelor din fisier in sistemul de

fisiere.

Procesele acceseaza fisierele cu ajutorul apelurilor sistem(system callc) si a numelui

fisierului.

Fiecare nume indica un singur fisier, iar kernelui converteste acest numein nr, inode-ului

fisierului specificat

Definirea INODE-URILOR

Inode-urile exista intr-o forma statica pe disk(disk inode) iar kernelul le citeste intr-un inod din

memorie(in-core inode) pentru a le putea manipula(modifica).

Disk inode contine urmatoarele campuri:

Identificatorul proprietarului fisierului

Tipul fiserului: fisierul poate fi de tip regular, director, caracter sau bloc special,FIFO( la pipe)

Permisiunile de acces asupra fisierului:sunt de 3 tipuri: pentru proprietar, pentru grup si pentru

restul utilizatorilor. Permisiunea de executie la directoare da de fapt dreptul de a cauta un fisier in

directorul respectiv;

Timpii de acces ai fisierului-cand a fost modificat ultima data, cand a fost accesat ultima data,

cand a fost modificat ultima data inodul

Numarul de linkuri catre acel fisier-nr de nume de directoare din ierarhia sa

Tabela de continut-adresele de pe disk ale datelor din fisier

Marimea fisierului

IN-CORE INODE

Copia inode-ului de pe disk in memorie(in-core inode) mai are catevacampuri in plus fata de

inode-ul de pe disk :

statutul in-core inode-ului :

daca inode-ul este blocat (locked);

daca un proces asteapta ca inode-ul sa devina liber;

Page 8: Proiectarea Sistemelor de Operare

8

reprezentarea in-core inode-ului difera de inode-ul de pe disk datoritaschimbarii datelor

din inode;

-reprezentarea in-core inode-ului difera de inode-ul de pe disk datoritaschimbarii datelor

din fisier;

-daca fisierul este un punct de montare (mount point);

numarul logic al device-ului;

numarul inode -ului;

pointeri catre alte in-core inode-uri -folositi pentru urmatorul inode din

hash queue sau din free list;

reference count -indica numarul de instante ale fisierului care sunt

active.

INODE-URI

Multe campuri din in-core inode sunt asemanatoare cu cele din buffer (cache) header, din

aceasta cauza si manipularea inodeurilor este la fel cu cea a buffer-elor.

Blocarea unui inode previne celelalte procese ca nu pot accesa

inode-ul ,acestea setand un flag prin care arata ca sunt in asteptarea eliberarii inode-ului.

Marea diferenta intre in-core inode si buffer (cache) header este

in-core reference count-ul,care contorizeaza instantele active ale unui fisier.

Un inode este activ cand un proces il aloca,asemenea cu deschiderea unui fisier.

Un inode este in free list daca reference count-ul sau este 0 , ceea ce inseamna ca se poate

reaaloca in-core inode-ul pentru alt disk inode (alocarea acestui in-core inode o face

kernel-ul).

Page 9: Proiectarea Sistemelor de Operare

9

SUB 5ALOCAREA IN-CORE INODE-URILOR--ALG IGET intrare: număr inod din sistemul de fişiere

ieşire: inod blocat

{

while (execuţia nu s-a încheiat)

{

if (inodul este în cache)

{

if (inodul este blocat)

{

sleep (până la deblocarea inodului);

continue; /* salt la while */

}

/* execuţie specială în cazul în care este punct de montare (Capitolul 5) */

if (inodul este în FLI)

şterge inodul din FLI;

incrementează contorul de referinţă al inodului;

return (inod);

}

/* inodul nu este în cache-ul de inoduri (listele hq) */

if (nu este nici un inod în FLI)

return (eroare);

şterge noul inod din FLI;

resetează numărul inodului şi sistemul de fişiere;

şterge inodul din vechea listă hq, plasează-l în cea nouă;

citeşte inodul de pe disc (algoritm bread);

iniþializează inodul (de exemplu, contorul=1);

return (inod);

}

}

ACCESAREA INODE-URILOR

� Kernelul identifica inode-ul dupa numarul sau si dupa numarul file system-ului si ii aloca un

in-core inode la cererea algoritmilor de nivel inalt.

� Algoritmul iget aloca un in-core inode inode-ului de pe disk;este aproape identic cu algoritmul

getblk pentru gasirea unui bloc in buffer cache.

� Algoritmul iget cauta numarul inode-ului si il cauta in hash queue.Daca nu il gaseste ,aloca un

inode din free list si il blocheza .

� Kernelul gaseste numarul blocului unde se afla inode-ul cu formula:

block num = ((inode num. -1)/number of inodes per block)+start block of inode list

� Offset-ul inode-ului in block se afla cu ajutorul formulei :

offset=((inode num. -1) modulo(number of inodes per block))*size of diskinode

� Kernel-ul manipuleaza independent blocarea inode-ului si reference count-ul.

� Blocarea care se face pe timpul executarii unui apel sistem este

necesara pentru a preveni celelalte procese ca nu pot accesa inodeul.

Kernel-ul va elibera inode-ul la sfarsitul apelului sistem.

Page 10: Proiectarea Sistemelor de Operare

10

ELIBERAREA INODE-URILOR ALGORITMUL IPUT algoritm iput /* eliberează un inod */

intrări: pointer la un inod din memorie

ieşiri: niciuna

{

blochează inodul dacă nu este deja blocat;

decrementează contorul de referinţă;

if (contorul de referinţă == 0)

{

if (contorul de legături == 0)

{

eliberează blocurile disc ale fişierului (algoritm free);

setează tipul fişier la 0;

eliberează inod(algoritm ifree);

}

if (fişierul a fost accesat sau inodul modificat sau fişierul modificat)

actualizează conţinutul inodului disc;

pune inodul în FLI;

}

deblochează inodul;

}

Cand kernel-ul elibereaza un inode ( prin algoritmul iput ) ,decrementeaza reference

count-ul din in-core inode-ulcorespunzator .

Atunci cand reference count-ul ajunge la 0 , kernel-ul,kernel-ulscrie inode-ul pe disc in

cazul in care in-core inode-ul a fostmodificat ( cand datele din fisier au fost modificate ,

timpiiacessului la fisier au fost modificati , s-a schimbat proprietarulsau permisiunile de

acces .

Kernel-ul pune apoi inode-ul in lista inode-urilor libere , putandsterge toate datele

asociate fisierului in cazul in care numarullink-urilor catre fisier este 0 .

Page 11: Proiectarea Sistemelor de Operare

11

SUB 6CONVERSIA NUME FIŞIER-INODE � Accesul iniţial la un fişier se face precizând numele căii sale (vezi apelurile sistem open, chdir

şi link). Deoarece nucleul operează intern cu inoduri (şi nu cu numele căii), pentru a accesa un

fişier converteşte numele căii sale în inod.

� Algoritmul namei analizează numele căii componentă cu componentă, convertind fiecare

componentă pe baza numelui ei şi a directorului în care se execută căutarea, şi returnează

ventual inodul corespunzător numelui căii dat ca intrare

� Fiecare proces are asociat un directorul curent, iar zona sa u area conţine un pointer către

inodul directorului curent. Directorul curent al primului proces din sistem (procesul 0) este

directorul rădăcină. Directorul curent al oricărui alt proces este directorul curent al procesului

părinte din momentul creării.

� Procesele schimbă directorul lor curent folosind apelul sistem chdir. Căutarea începe din

directorul curent dacă primul caracter din cale nu este "/", altfel va începe din directorul rădăcină.

În ambele situaţii nucleul găseşte uşor inodul din care începe căutarea, deoarece directorul curent

se regăseşte în zona u area a procesului, iar inodul rădăcinii sistemului este memorată într-o

variabilă globală.

algoritm namei /* converteşte nume cale într-un inod */

intrare: nume cale

ieşire: inod blocat

{

if (numele căii începe din rădăcină)

inod de lucru = inodul rădăcină (algoritm iget );

else

inod de lucru = inodul directorului curent (algoritm iget );

while (mai sunt componente neparcurse)

{

citeşte următoarea componentă din nume cale;

verifică dacă inodul de lucru este al unui director, permisiunile de acces

în regulă;

if (inodul în lucru este al rădăcinii şi componenta este "..")

continue; citeşte directorul (inodul de lucru) prin folosirea

repetată a algoritmilor bmap, bread şi brelse;

if (componenta se potriveşte cu numele unei intrări în director (inodul de

lucru))

{

citeşte numărul inodului din intrarea corespunzătoare

componentei identificate;

eliberează inodul de lucru (algoritm iput );

inodul de lucru = inodul componentei din intrare (algoritm iget);

}

else /* componenta nu este în director */

return (nici un inod);

}

return (inodul de lucru);

}

Page 12: Proiectarea Sistemelor de Operare

12

OBSERVAŢII LA ALGORITMUL NAMEI

� Algoritmul namei utilizează inoduri intermediare în analiza unui nume de cale, numite inoduri

de lucru (working inode).

� Primul inod de lucru, este cel din care se începe căutarea.

� Pe durata fiecărui ciclu din namei, nucleul se asigură că inodul de lucru este al unui director.

Altfel, sistemul ar încălca aserţiunea că fişierele care nu sunt directoare pot fi doar

noduri frunză în arborele de fişiere.

� Procesul trebuie să aibă şi permisiunea de a căuta în director (permisiunea de citire nu este

suficientă). Pentru aceasta identificatorul utilizator (UID) al procesului trebuie să se potrivească

cu identificatorul proprietarului sau grupului (GID) fişierului, sau fişierul trebuie să permită

tuturor utilizatorilor căutarea.Astfel căutarea eşuează.

Page 13: Proiectarea Sistemelor de Operare

13

SUB 7 ACCESUL LA INF.FISIERELOR; ALG. BMAP, TABELA DE

CUPRINS � Kernel-ul poate minimiza fragmentarea spaţiului de memorare prin executarea periodică a

unui set de proceduri destinate compactării spaţiului disponibil, însă această operaţie ar

diminuează din puterea de procesare.

� Pentru o mai mare flexibilitate, nucleul alocă unui fişier câte un bloc la un moment dat, şi

elimină necesitatea păstrării contigue a datelor fişirului, permitând ca acestea să fie memorate

peste tot în sistemul de fişiere.

� Dar această schemă de alocare complică sarcina localizării datelor.

� Pentru a nu fi nevoie sa se aloce dinamic saptiu pentru tabela de cuprins s-a folosit o

gestionare a spatiului prin adresare directa sau prin simpla , dubla sau tripla indirectare

BLOCURI DIRECTE SI INDIRECTE

DIMENSIUNEA BLOCURILOR

� Presupunand că un bloc logic din sistemul de fişiere ocupă 1ko şi că un număr de bloc este

adresabil pe 32 de biţi, un bloc poate conţine până la 256 numere de bloc.

� Dimensiunea maximă a unui fişier poate depăşi 16 Go prin utilizarea tuturor celor 13 intrări .

� Intrucât câmpul din inod în care se păstreză dimensiunea fişierului are 32 biţi, dimensiunea

unui fişier este limitată practic la 4 Go (232).

OBTINEREA NUMARULUI BLOCULUI DIN SISTEMUL DE FISIERE PE BAZA

DEPLASAMENTULUI

� Procesele accesează datele unui fişier specificând deplasamentul.

� Dacă utilizatorul vede fişierul ca pe un şir de octeţi, nucleul îl vede ca un şir de blocuri,

realizând o conversie. Fişierul începe de la blocul logic 0 şi continuă până la un număr de bloc

logic corespunzător dimensiunii fişierului.

� Nucleul accesează inodul şi converteşte numărul de bloc logic în numărul de bloc disc. In

continuare vom prezenta algoritmul bmap care determină blocul fizic de disc corespunzător

deplasamentului în fişier.

Page 14: Proiectarea Sistemelor de Operare

14

ALGORITMUL BMAP alg. bmap

input : inode

byte offset

output : (1) block number in file system

(2) byte offset into block

(3) bytes of I/O in block

(4) read ahead block number

{

calculate logical block number in file from byte offset ;

calculate start byte in block for I/O ; /*output 2*/

calculate number of bytes to copy to user ; /*output 3*/

check if read-ahead applicable , mark inode ; /*output 4*/

determine level of indirection ;

while (not at necessary level of indirection)

{

calculate index into inode or indirect block from logical block number in

file ;

get disk block number from inode (or indirect block) ;

release buffer from previous disk read , if any (alg. brelse) ;

if (no more levels of indirection)

return (block number) ; /*output 1*/

read indirect disk block (alg. bread) ;

adjust logical block number in file according to level of indirection ;

}

}

CONCLUZII ASUPRA ACCESULUI LA FIŞIERE

� Accesul la sistemul de fişiere este cu atât mai rapid cu cât nucleul accesează mai multe date de

pe disc în decursul unei operaţii, altfel spus, cu cât dimensiunea blocurilor disc este mai mare.

Folosirea blocurilor de dimensiuni mari (4 ko, 8 ko) aduce pe lângă avantajul creşterii vitezei, şi

un dezavantaj: creşterea fragmentării blocurilor (mari porţiuni de spaţiu de pe disc nu pot

fi utilizate).

� Implemetarea Berkeley BSD 4.2 remediază aceasta situaţie prin introducerea blocurilor

fragment ce conţin ultimele date (care nu completează un bloc) din diferite fişiere. Aceste blocuri

au tot dimensiunea de 4 ko sau 8 ko, dar sunt organizate ca o succesiune antet-date, unde antetul

păstrează informaţii referitoare la fişierul căruia îi aparţine fragmentul de date care-l urmează.

Pentru a identifica blocul fragment care-i păstrează partea finală, fişierul păstrează în ultima

intrare adresa acestui bloc. Această soluţie va introduce o încetineală la accesul ultimului a

fragment.

Page 15: Proiectarea Sistemelor de Operare

15

SUB 8DIRECTOARELE � Directoarele sunt fişiere care dau sistemului de fişiere o structură ierarhică .

� Ele joacă un rol important în conversia numelui unui fişier într-un număr de inod.

� Un director este un fişier ale cărui date sunt o secvenţă de intrări, fiecare fiind alcătuită dint-un

un număr de inod şi numele fişierului conţinut în director.

� Un nume de cale este un şir de caractere terminat cu caracterul null , ale cărui componente

sunt separate prin caracterul ‗/‘ . Fiecare componentă, excepţie făcând ultima, trebuie să fie

nume de director.

� System V restricţionează dimensiunea maximă a unei componente la 14 caractere.

dimensiunea unei intrări în director este astfel de 16 octeţi- 2 pentru numărul inodului, iar restul

de 14 pentru numele fişierului conţinut în director.

STRUCTURA DIRECTORULUI "ETC"

• Orice director conţine fişierele numite "." şi "..", ale căror numerede inod sunt cel al

directorului curent, respectiv al directoruluipărinte.

• Numărul de inod al fişierului "." din "/etc" este plasat la deplasamentul 0 în fişier, şi are

valoarea 83. Numărul inodului pentru "..‖ este plasat la deplasamentul 16, şi are valoarea 2.

• O intrare în director este neocupată dacă numărul de inod este 0. De exemplu, intrarea de la

deplasamentul 224 este neocupată, şi a conţinut o intrare pentru fişierul numit "crash".

• La iniţializarea sistemului de fişiere (folosind programul mkfs) numerele inodurilor fişierelor

"." şi ".." ale directorului rădăcină primesc valoarea inodului rădăcină al sistemului de fişiere.

Nucleul stochează datele pentru un director la fel cum le stochează pentru un fişier obişnuit,

utilizând structura de inod şi nivelele de blocuri directe şi blocuri indirecte.

DREPTURI DE ACCES IN DIRECTOARE

• Procesele pot citi directoarele în acelaşi mod în care citesc fişierele obişnuite, dar nucleul îşi

rezervă dreptul exclusiv de a scrie un director, asigurându-i astfel o structură corectă.

• Permisiunile de acces la un director au următoarele semnificaţii:

- Cea de citire permite unui proces să citească un director.

- Cea de scriere permite unui proces să modifice conţinutul unui director.Se pot crea intrări noi în

director sau se pot ştearge din celevechi (folosind apelurile sistem creat, mknod, link şi nlink).

- Cea de execuţie permite unui proces să caute un nume de fişier îndirector.

SUB 9SUPERBLOCUL Superblocul conţine următoarele câmpuri:

• dimensiunea sistemului de fişiere;

• numărul blocurilor libere în sistemul de fişiere;

• o listă a blocurilor libere disponibile în sistemul de fişiere;

• indexul următorului bloc liber din lista blocurilor libere;

• dimensiunea listei de inoduri;

• numărul de inoduri libere în sistemul de fişiere;

• o listă cu inoduri libere în sistemul de fişiere;

• indexul următorului inod liber din lista inodurilor libere;

• câmpuri de blocare pentru lista inodurilor libere şi lista blocurilor libere;

• un bit de semnalizare care indică dacă superblocul a fost modificat

Periodic, nucleul scrie pe disc superblocul în cazul în care au survenit modificări

Page 16: Proiectarea Sistemelor de Operare

16

PROBLEMA

Page 17: Proiectarea Sistemelor de Operare

17

SUB 10. ALOCAREA/ELIBERAREA BLOCURILOR DISC; ALG.

ALLOC/FREE

Când un proces scrie date într-un fişier nucleul trebuie să aloce blocuri disc din sistemul

de fişiere (folosite ca blocuri directe de date sau ca blocuri de indirectare).

Superblocul sistemului de fişiere conţine o listă în care sunt păstrate numerele de blocuri

disc libere din sistemul de fişiere.

� Programul utilitar mkfs (make file system) organizează blocurile de date ale sistemului

de fişiere într-o listă înlănţuită, fiecare element fiind un bloc disc care conţine o listă de numere

de blocuri disc libere, şi o intrare din această listă reprezintă numărul următorului bloc din lista

înlanţuită.

� Când nucleul intenţionează să aloce un bloc dintr-un sistem de fişiere alocă următorul

bloc disponibil din lista aflată în superbloc. Odată alocat, blocul nu poate fi realocat până când el

nu devine liber.

� Dacă blocul alocat este ultimul bloc disponibil din superbloc, nucleul îl tratează ca un

pointer la un bloc care conţine o altă listă de blocuri libere.

ALOCAREA BLOCURILOR DISC

ALGORITMUL ALLOC

algoritm alloc /* alocarea unui bloc din sistemul de fişiere */

intrare: numărul sistemului de fişiere

ieşire: buffer pentru noul blocul

{

while (superblocul este blocat)

sleep (până superblocul devine liber);

şterge un bloc din lista liberă din superbloc;

if (s-a şters ultimul bloc)

{

blochează superblocul;

citeşte blocul care tocmai a fost luat din lista liberă (algoritm bread );

copiază în superbloc numerele de bloc din blocul citit;

eliberează bufferul alocat blocului (algoritm brelse);

deblochează superblocul;

trezeşte procesele(care aşteaptă deblocarea superblocului);

}

obţine buffer pentru blocul şters din superbloc(algoritm getblk );

conţinutul bufferului este pus cu 0;

decrementează contorul total al blocurilor libere;

marchează faptul că superblocul a fost modificat;

return buffer;

}

Page 18: Proiectarea Sistemelor de Operare

18

Algoritmul free pentru eliberarea unui bloc este invers celui de alocare a unui bloc.

Dacă lista din superbloc nu este plină, numărul blocului eliberat este plasat în

listă.

Dacă lista este plină, blocul eliberat devine bloc de legătură, adică nucleul scrie

lista din superbloc în bloc, iar blocul pe disc.

Page 19: Proiectarea Sistemelor de Operare

19

SUB 11 ALOCAREA UNUI INODE LA UN FIŞIER NOU � Algoritmul ialloc asignează (alocă) un inod disc unui fişier nou creat.Pentru a evita condiţiile

de concurenţă, nucleul verifică mai întâi dacăalte procese nu au blocat accesul la lista de inoduri

libere dinsuperbloc.

� Dacă lista cu numere de inoduri din superbloc nu este goală, nucleulasignează următorul

număr de inod, alocă un inod liber în memoriainternă pentru inodul disc asignat folosind

algoritmul iget (citind inodulde pe disc dacă este necesar), copiază inodul disc în inodul din

memoria internă, iniţializează câmpurile inodului şi returnează inodulblocat. Actualizează inodul

disc pentru a arăta că acum este folosit: ovaloare diferită de zero a câmpului din inod ce conţine

tipul fişieruluiindică faptul că inodul disc este asignat.

� Dacă lista inodurilor libere din superbloc este goală, nucleul citeştebloc cu bloc lista de

inoduri de pe disc şi umple lista din superbloc cunumere de inoduri libere, memorând totodată

cel mai mare număr deinod găsit. Acesta, numit şi inod memorat, este ultimul salvat în

superbloc. La fiecare asignare a unui inod disc, nucleul decrementează contorul cu

numărul inodurilor libere aflat în superbloc.

ALGORITMUL IALLOC

algoritm ialloc /* asignează un inod */

intrare: sistemul de fişiere

ieşire: inod blocat

{

while (operaţia nu s-a încheiat)

{

if (superblocul este blocat)

{

sleep (până superblocul devine liber);

continue; /* salt la while */

}

if (lista de inoduri din superbloc este goală)

{

blochează superblocul;

determină inodul memorat folosit în căutarea inodurilor libere;

caută pe disc inoduri libere până se umple lista din superbloc sau nu mai

sunt inoduri libere (algoritmi bread şi brelse );

deblochează superblocul;

trezeşte procesele ce aşteptau ca superblocul să devină liber;

if (nu s-au găsit inoduri libere pe disc)

return (nu există inod);

stabileşte valoarea inodului memorat pentru următoarea

căutare de inoduri libere;

}

/* lista inodurilor din superbloc nu e goală */

obţine un număr de inod din lista de inoduri din superbloc;

obţine inod (algoritm iget);

if (inodul nu e liber nici acum) /* a fost alocat altui fişier !!! */

{

Page 20: Proiectarea Sistemelor de Operare

20

scrie inodul pe disc;

eliberează inodul (algoritmul iput);

continue; /* salt la while */

}

/* inodul este liber */

iniþializează inod;

scrie inodul pe disc;

decrementează contorul inodurilor libere din sistemul de fişiere;

return (inod);

}

}

ALGORITMUL IFREE

algoritm ifree /* eliberare inod */

intrare: numãr inod din sistemul de fiºiere

iesire: niciuna

{

incrementeazã contorul inodurilor libere;

if (superblocul este blocat)

return;

if (lista de inoduri este plinã)

{

if (numãrul inodului este mai mic decât al inodului memorat)

inodul memorat pentru cãutare = numãr inod de intrare;

}

else

pune numãrul inodului în lista inodurilor libere;

return;

}

Apoi, plasează numărul blocului nou

eliberat în lista din superbloc, el fiind

singurul element al listei.

În exemplul din figura 4.20 se

prezintă o secvenţă de operaţii alloc şi free

asupra listei

libere din superbloc care iniţial conţine un

singur număr (109) (vezi figura 4.20 (a)).

Nucleul eliberează blocul numărul 949 şi

plasează numărul acestuia în lista liberă

(vezi figura 4.20 (b)). După aceea, se

solicită două blocuri. Nucleul asignează

Page 21: Proiectarea Sistemelor de Operare

21

întâi blocul numărul 949 (vezi figura 4.20 (c)), după care alocă şi şterge blocul numărul 109 din

listă liberă. Deoarece lista liberă din superbloc este acum goală, nucleul copiază în lista din

superbloc conţinutului blocului 109 (de fapt următorul element din lista înlănţuită) (vezi figura

4.20 (d)), iar următorul bloc de legătură devine blocul 211.

APELURI SISTEM

Acest capitol tratează apelurilesistem utilizate de sistemul de fişiere folosindu-se algoritmii

studiaţi în capitolulanterior. Sunt prezentate apeluri pentru:

• accesarea fişierelor existente: open, read, write, lseek, close;

• crearea de noi fişiere: creat şi mknod;

• modificarea datelor referitoare la inod: chdir, chroot, chown, chmod, stat, fstat;

• implementarea pipe-urilor: pipe şi dup;

• extinderea sistemului de fişiere vizibil utilizatorului: mount şi umount;

• modificarea ierarhiei sistemului de fişiere: link şi unlink.

Page 22: Proiectarea Sistemelor de Operare

22

SUB 12APELUL SISTEM OPEN Apelul sistem open este primul pas ce trebuie efectuat de către un proces pentru a

putea accesa datele unui fişier. Sintaxa apelului sistem open este:

fd = open (nume_cale, flaguri, moduri);

unde nume_cale este un nume de fişier, flaguri indică tipul de deschidere (pentruscriere sau

citire), iar moduri specifică permisiunile de acces în cazul creării fişierului.Apelul sistem

returnează un întreg numit descriptor de fişier (fd). Toatecelelalte operaţii cu fişierul, cum ar fi

citirea, scrierea, poziţionarea offsetului fişierului,duplicarea descriptorului de fişier, modificarea

parametrilor de I/O ai fişierului,determinarea stării fişierului şi închiderea fişierului, folosesc

descriptorul de fişier pecare îl returnează apelul sistem open.

Structurile de date după execuţia aplelurilor open.

algoritm open

intrări: numele fişierului

tipul de deschidere

permisiuni de acces /* precizate doar la creare */

ieşire: descriptorul de fişier

{

determinarea inodului folosind numele fişierului (algoritm namei);

if (fişierul nu există sau accesul nu este permis)

return (eroare); /* uzual -1 */

alocă o intrare în GFT pentru inod, iniţializează contorul şi offsetul;

alocă o intrare în UFDT, setează pointerul către intrarea corespunzătoare

din GFT;

if (tipul de deschidere presupune rescrierea fişierului)

eliberează toate blocurile fişierului (algoritm free);

deblochează (inodul); /* blocat în namei */

return (descriptorul de fişier); }

Nucleul caută fişierul în cadrul sistemului de fişiere folosind algoritmul namei(vezi figura

5.2). După ce găseşte inodul din memoria internă, se verifică permisiunilede acces la fişier, iar

dacă acestea sunt corespunzătoare, se alocă o intrare în GFTpentru fişierul ce este deschis. O

intrare în GFT conţine: un pointer către inodulfişierului deschis, tipul deschiderii fişierului (citire

şi/sau scriere), deplasamentul(offsetul) de la care nucleul urmează să execute următoarea citire

sau scriere. Nucleuliniţializează această valoare cu 0 pe durata aplelului open, ceea ce înseamnă

că primacitire sau scriere se va face, implicit, de la începutul fişierului. De asemenea, un

procespoate deschide un fişier pentru adăugare, caz în care nucleul va iniţializa offsetul

cuvaloarea lungimii fişierului.

Nucleul alocă o intrare în UFDT, iar valoarea indexului din tabelă corespunzător

acestei intrări este descriptorul de fişier returnat utilizatorului. Intrarea din UFDTconţine un

pointer către intrarea corespunzătoare din GFT.

Page 23: Proiectarea Sistemelor de Operare

23

Apelul sistem close Sintaxa aplelui sistemclose este:

close(fd);

• fd - descriptorul fişierului returnat deopen;

• modifică intrările din tabela de fişiere şi tabela de

inoduri corespunzătoare descriptoruluifd;

• intrările nu sunt şterse, ci doar eliberate (cândcontoarele ajung la 0 se invalidează legăturile

întretabele);

• intrările pot fi utilizate de acelaşi fişier (dacă seredeschide imediat) sau realocate altui fişier ce

va fideschis.

Page 24: Proiectarea Sistemelor de Operare

24

SUB 13APELUL SISTEM READ Sintaxa apelului sistem read este:

număr = read(fd, buffer, contor);

unde fd este descriptorul de fişier returnat de către open, buffer este adresa de memorie din

spatiul procesului utilizator care va conţine datele în caz de reuşită a apelului, contor este

numărul de octeţi pe care utilizatorul doreşte să-i citească, iar număr este numărul de octeţi citiţi

în urma apelului.

Exemplu: fd1 = open("/etc/passwd", O_RDONLY);

fd2 = open("local", O_WRONLY);

fd3 = open("/etc/passwd", O_RDWR);

algoritm read

intrări: descriptorul de fişier

adresa bufferului din spaţiul de memorie al procesului utilizator

numărul de octeţi ce se doreşte a fi citit

ieşire: numărul de octeţi copiaţi în spaţiul utilizator

{

găseste intrarea din GFT corespunzătoare descriptorului de fişier;

verifică drepturile de acces la fişier;

stabileşte parametrii din u area implicaţi în operaţia de I/O; /* adresadin spaţiul

utilizator, contorul cu numărul de octeti ce trebuie R/W,modul de I/O */

găseşte inodul corespunzător din intării din GFT;

blochează inodul;

stabileşte offsetul din u area la valoarea existentă în intrarea din GFT

while (nu s-a ajuns la numărul dorit de octeţi citiţi)

{

converteşte offsetul în fişier în număr de bloc disc ( algoritm

bmap);

calculează offsetul în bloc, numărul de octeţi ce vor fi citiţi;

if (numărul de octeţi ce vor fi citiţi este 0)

/* încercare de a citi sfârşitul fişierului */

break; /* se iese din ciclu */

citeşte blocul; /* algoritmul breada sau bread */

copiază datele din bufferul sistem la adresa din spaţiul utilizator;

reactualizează câmpurile din u area; /* offsetul în fişier, contorul,

adresa utilizator */

deblochează bufferul; /* blocat în bread */

}

deblochează inodul;

actualizează offsetul din GFT pentru următoarea operaţie de citire;

return (numărul total de octeţi citiţi); }

Page 25: Proiectarea Sistemelor de Operare

25

Apelul sistem write

Sintaxa apelului sistem write este:

număr= write(fd, buffer, contor);

unde semnificaţia variabilelor număr, fd, buffer, contor este cea prezentată în

descrierea apelului read.

Algoritmul pentru scrierea unui fişier regulat este similar celui de citire. Dacă fişierul

nu conţine un bloc corespunzător offsetului la care trebuie efectuată scrierea, atuncinucleul alocă

un nou bloc folosind algoritmul alloc şi înscrie numărul blocului în poziţiacorespunzătoare a

tabelei de conţinut din inod. Dacă offsetul corespunde unui bloc deindirectare, nucleul va trebui

să aloce un număr corespunzător de blocuri ce vor fiutilizate ca blocuri de indirectare şi blocuri

de date. Pe durata operaţiei de scriereinodul este blocat, deoarece nucleul poate schimba inodul

când alocă blocuri noi.Permiţându-se altor procese accesul la fişier s-ar putea corupe inodul dacă

mai multeprocese ar aloca simultan blocuri pentru acelaşi offset. Dacă câmpul din inod ce

conţine dimensiunea fişierului a fost modificat, la încheierea operaţiei de scrierenucleul îl

actualizează.

Să presupunem că un proces scrie într-un fişier octetul cu numărul 10.240, care este

totodată octetul cu cel mai mare număr de ordine. Când accesează octetul (folosindalgoritmul

bmap), nucleul determină că lipseşte blocul de date şi cel de indirectare corespunzătoare acelui

octet. Astfel, el alocă un bloc disc ce va fi utilizat ca bloc deindirectare şi scrie numărul blocului

în inodul din memorie. Apoi, alocă un bloc disc ceva fi utilizat ca bloc de date şi scrie numărul

blocului în prima poziţie a blocului deindirectare anterior alocat.

Scrierea se face întru-un ciclu intern, asemănător algoritmului read. Pe durata unei

iteraţii nucleul va scrie un singur bloc disc. În acest sens, va determina dacă va scrieînteg blocul

sau numai o parte din el. Dacă scie doar o parte, va trebui mai întâi săcitească blocul de pe disc,

pentru a conserva datele ce nu se vor modifica. Citirea numai este necesară în cazul scrierii

întregului bloc, deoarece se va modifica totconţinutul său. Nucleul utilizează scrierea întârziată a

blocurilor pe disc (delayed write, vezi 3.4), păstrându-le în cache cât mai mult timp posibil,

pentru a oferi şi altorprocese posibilitatea de a le scrie sau citi fără a mai executa operaţii de I/O

cu discul.

Folosirea scrierii întârziate este utilă în cazul pipes-urilor deoarece un alt proces

va citi datele şi le va şterge (vezi 5.12), şi chiar în cazul fişierelor regulate ce suntcreate

temporar. De exemplu, multe programe cum ar fi cele de poştă electronică,editoarele de texte,

crează fişiere temporare în directorul ―/temp‖, pe care le ştergdupă puţin timp. Utilizarea scrierii

întârziate, poate reduce numărul de scrieri pe discpentru fişierele temporare.

Page 26: Proiectarea Sistemelor de Operare

26

SUB 14SINTAXA APELULUI SISTEM LSEEK poziţie= lseek(fd, offset, referinţă);

fd - descriptorul de fişier (returnat de open);

referinţă - indică originea faţă de care se stabileşte deplasamentul;

offset - un număr care indică poziţia finală a deplasamentului faţă de referinţă;

poziţie- deplasamentul de la care va începe următoarea operaţie de citire/scriere.

• Pentru a implementa apelul lseek nucleul modifică practic valoareadeplasamentului din

tabela de fişiere;

• Apelul lseeknu are nimic de a face cu operaţiaseekcare efectueazăpoziţionarea braţului

discului pe un anumit sector. Apelurile read şi write descrise anterior asigură un acces secvenţial la un fişier. Prinutilizarea

apelului sistem lseek procesele pot modifica valoarea offsetului din GFT,asigurându-se astfel un acces

aleator la fişier, utilizatorul având posibilitatea să scriesau să citească de la orice offset.

SUB 15APELUL SISTEM CREAT Sintaxa apelului sistem creat :

fd = creat (nume_cale, moduri);

• nume_cale - un nume de fişier;

• moduri - permisiunile de acces;

• fd – un intreg numit descriptor de fisier.

• Dacă nu există nici un fişier cu numele specificat, atunci nucleul crează unnou fişier cu numele

şi permisiunile de acces (modurile) precizate;

• Dacă fişierul există deja, şi permisiunile de acces sunt corespunzătoare,nucleul trunchiază

fişierul (eliberează toate blocurile sale şi seteazădimensiunea fişierului la 0).

algoritm creat

intrări: numele fişierului

permisiunile de acces

ieşire: descriptorul de fişier

{

determină inodul pentru fişier (algoritm namei);

if (fişierul deja există)

{

if (accesul nu este permis)

{

inodul (algoritmul iput);

return (eroare);

}

}

else /* fişierul nu există încă */

{

asignează un inod liber din sistemul de fişiere (algoritm ialloc);

crează o nouă intrare în directorul tată în care se înscriu numelenoului fişier şi

numărul inodului aneterior asignat;

}

alocă o intrare în GFT pentru inod, iniţializează contorul;

Page 27: Proiectarea Sistemelor de Operare

27

if (fişierul exista în momentul creerii)

eliberează toate blocurile fişierului (de date şi de indirectare)

(algoritmul free);

deblochează inodul;

return (descriptorul de fişier);

}

Dacă fişierul deja exista înaintea apelului creat, nucleul găseşte inodul său întimp ce

caută fişierul. Vechiul fişier trebuie să ofere permisiunea de scriere procesuluice doreşte să

creeze un ―nou‖ fişier cu acelaşi nume, deoarece conţinutul fişierului vafi modificat (se

eliberează toate blocurile fişierului, acesta arătând ca un fişier noucreat). ïntrucât conţinutul

directorului tată nu va fi modificat, nucleul nu va maiverifica dacă este permisă scrierea

directorului.

SUB 16APELUL SISTEM MKNOD Sintaxa apelului sistem mknod

mknod (nume_cale, tip şi permisiuni, dev)unde

• nume_cale - numele nodului care va fi creat;

• tip şi permisiuni - tipul nodului (de exemplu director) şi permisiunilede acces pentru noul fişier

ce va fi creat;

• dev - numerele major şi minor ale dispozitivului pentru fişierelespeciale bloc şi caracter

• dacă fişierul nu există, nucleul asignează un nou inod pe disc şi scrienumele noului fişier şi

numărul inodului alocat în directorul părinte;

• Iniţializează câmpul din inod care specifică tipul fişierului;

• Dacă fişierul este de tip dispozitiv special caracter sau bloc, atunci sescriu în inod numerele

major şi minor de dispozitiv.

algoritm make new node

intrări: numele fişierului

tipul fişierului

permisiunile de acces

număr major şi minor al dispozitivului (pentru fişierele speciale bloc şicaracter)

ieşire: niciuna

{

if (noul nod nu este pipe numit şi utilizatorul nu este super user )

return(eroare);

determină inodul tatălui noului nod (algoritmul namei);

if (noul nod deja există)

{

eliberează inodul tatălui (algoritmul iput);

return (eroare);

}

alocă un nod liber din sistemul de fişiere pentru noul nod (algoritmul ialloc);

crează o nouă intrare în directorul tată şi o completează cu numele nodului şi

numărul de inod anterior asignat;

eliberează inodul directorului tată (algoritmul iput);

Page 28: Proiectarea Sistemelor de Operare

28

if (noul nod este fişier special bloc sau caracter)

scrie numărul major şi minor al dispozitivului în structura inodului;

eliberează inodul noului nod (algoritmul iput);

}

Nucleul caută în sistemul de fişierefişierul cu numele ce urmează să fie creat. Dacă

fişierul nu există încă, nucleul alocăun nou inod pe disc şi scrie nume noului fişier şi numărul

inodului alocat în directorultată. Iniţializează câmpul din inod care specificå tipul fişierului (pipe,

director sau fişierspecial). Dacă fişierul este de tip dispozitiv special caracter sau bloc, atunci se

scriu îninod numerele major şi minor de dispozitiv. Algoritmul prezentat mai trebuiecompletat în

cazul creării directoarelor, deoarece nu sunt create şi iniţializate intrăriledirector pentru ―.‖ şi

―..‖.

SUB 17APELURI SIST PT PIPE-URI ANONIME;ALG PIPE - sunt fişiere de tip FIFO;

- permit transferul de date între procese, cât şi

incronizarea execuţiei proceselor;

- există două tipuri de pipe-uri:

• pipe-uri numite si • pipe-uri nenumite (anonime).

- cele nenumite sunt create cu apelul sistem pipe şi nu pot fi folosite încomun decât de procesele

descendente din procesul ce a creat pipe-ul.

- cele numite ocupă un loc în ierarhia sistemului de fişiere, se deschidca orice fişier (folosind

aplelul sistem open) şi pot fi folosite încomun deprocese în funcţie de permisiunile lor de acces

la fişier

Sintaxa apelului pipe

pipe (fdptr) ;

unde fdptr este un pointer către un şir de doi întregi ce va conţinedescriptorii de fişier pentru

citirea şi scrierea pipe-ului .

Deoarece nucleul implementează pipe-urile însistemul de fişiere, acestea neexistând

înaintea utilizării lor, nucleul va asigna un inodşi va aloca doi descriptori în UFDT (un descriptor

pentru citirea din pipe şi altul pentruscrierea în pipe) şi intrările corespunzătoare în GFT.

Utilizarea GFT face ca interfaţaapelurilor sistem de scriere, citire a pipe-urilor să fie aceeaşi cu

cea pentru fişiereleregulate. Astfel, procesele nu trebuie să ştie dacă citesc/scriu un pipe sau un

fişierregulat.

Algoritmul de creare a unui pipe nenumit:

intrare: nici una

ieşiri: descriptorul pentru citire

descriptorul pentru scriere{

Asigneaza un nou inod din dispozitivul pentru pipe (algoritmul ialloc);

aloca 2 intrari în tabela de fişiere (una pentru citire, una pentru scriere,care vor pointa catre

inodul anterior asignat);

aloca 2 descriptori de fişier (unul pentru scriere, unul pentru citire) şi initializeazå pointerii catre

intrarile corespunzatoare din tabela de fişiere;

valoarea contorului de referintå corespunzator inodului este stabilit 2 ;}

Page 29: Proiectarea Sistemelor de Operare

29

SUB 18APELUL SISTEM DUP Apelul sistem dup copiază un descriptor de fişier în primul slot (intrare) liber din UFDT,

returnând utilizatorului noul descriptor. Apelul poate fi folosit pentru toate tipurile defişiere. Este

utilizat în construcţia programelor complexe pornind de la programe maisimple Sintaxa apelului

este:

fd_nou = dup(fd);

• fd este descriptorul de fişier care va fi duplicat;

• fd_nou este noul descriptor care va referi fişierul;

Mod de execuţie:

• Contorul intrării din tabela de fişiere corespunzătoare lui fd va fiincrementat, deoarece şi

intrarea din tabela descriptorilor de fişierutilizator a lui fd_nou va pointa către aceeaşi intrare în

tabela de fişiere.

Page 30: Proiectarea Sistemelor de Operare

30

SUB 19STĂRI ŞI TRANZIŢII

Timpul de viaţă al unui proces poate fi conceptual divizat într-un set de stări care descriu

procesul :

1. Procesul este în execuţie în modul utilizator.

2. Procesul este în execuţie în modul nucleu.

3. Procesul nu este în execuţie dar este gata pentru execuţie îndată ce nucleul îl planifică.

4. Procesul este în aşteptare şi se găseşte în memoria principală.

5. Procesul este gata de execuţie, dar încărcătorul ( procesul 0) trebuie să încarce procesul în

memoria principală înainte ca nucleul să-l poată planifica pentru execuţie.

6. Procesul este în aşteptare şi încărcătorul a transferat procesul la un dispozitiv de memorare

secundar făcând loc pentru alte procese în memoria principală.

7. Procesul se întoarce din modul nucleu în modul utilizator, dar nucleul îl întrerupe şi face o

comutare de context pentru a planifica alt proces. Diferenţa între această stare şi starea 3 (―ready

to run‖) va fi descrisă ulterior.

8. Procesul este de curând creat şi se află într-o stare de tranziţie; procesul există dar nu este gata

de execuţie şi nici în aşteptare. Aceasta este o stare de început pentru toate procesele, cu excepţia

procesului 0.

9. Procesul a executat apelul sistem exit şi este în starea zombie. Procesul nu va mai exista mult,

dar el lasă o înregistrare ce conţine codul de ieşire şi câteva statistici de timp pentru a fi folosite

de procesul părinte. Starea zombie reprezintă o stare finală a procesului.

Diagrama completa a starilor unui process

Page 31: Proiectarea Sistemelor de Operare

31

SUB 20STRUCTURI DE DATE ALE PROCESELOR

Două structuri de date ale nucleului descriu starea unui proces: process table entryşi u area.

Tabela de procese conţine câmpuri care trebuie să fie întotdeauna accesibile nucleului, dar u area

conţine câmpuri care trebuie să fie accesibile numai la execuţia procesului.

Câmpurile din tabela de procese(PT)sunt următoarele:

Câmpul de stare care identifică starea procesului.

Intrarea în tabela de procese conţine câmpuri care permit nucleului să localizeze procesul

şi zona sa uarea în memoria principală sau pe un dispozitiv extern. Intrarea în tabela de procese

conţine deasemenea un câmp care dă mărimea procesului, astfel încât nucleul ştie cât spaţiu

trebuie să aloce procesului.

Mai mulţi identificatori ai utilizatorului(utilizatorIDsauUID) determină diferite drepturi

pentru proces.

Identificatorii procesului (proces ID sau PID) specifică relaţia dintre

procese. Aceste câmpuri ID sunt setate când procesul intră în starea creare proces

în urma apelului sistem fork.

Intrarea în tabela de procese conţine un descriptor de evenimente când procesul este

înstarea ―aşteptare―.

Parametri de planificare permit nucleului să determine ordinea în care procesele trec în

stările execuţie în modul nucleu şi în starea execuţie în modul utilizator.

Câmpul semnal reţine semnalele trimise procesului dar care nu sunt încă tratate

Diferite contoare de timp dau timpul de execuţie al procesului şi utilizarea resurselor

nucleului, timpi folosiţi pentru contabilizarea procesului şi pentru calcularea priorităţii de

planificare a procesului. Câmpul contor de timp setat de utilizator este folosit pentru a

transmite un semnal de alarmă unui proces.

U area conţine următoarele câmpuri ce caracterizează stările procesului:

Un pointer spre tabela de procese-intrarea ce corespunde zonei uarea

Identificatorii de utilizator real şi efectiv determină diferite privilegii premise procesului

cum ar fi drepturile de acces la fişier

Câmpurile contor de timp înregistrează timpul pe care procesul (şi descendenţii lui) îl

consumă în execuţie în modul utilizator şi în modul nucleu.

O zonă de reacţie la semnale indică cum doreşte procesul să reacţioneze la semnale.

Un camp de eroare înregistrează erorile întâlnite în timpul apelului sistem.

Un camp valoare de revenire conţine rezultatul apelurilor sistem.

Parametrii I/O descriu cantitatea de date transferate, adresa zonei de date sursă

(ţintă) din spaţiul utilizatorului, deplasamentul în fişier şi altele.

Directorul curent şi rădăcina curentă descriu sistemul de fişiere în care se află

procesul.

Tabela descriptorilor de fişiere utilizator (UFDT) înregistrează fişierele pe care procesul

le-a deschis.

Câmpurile de limitare restricţionează mărimea procesuluişi dimensiunea unui fişier pe

are îl poate scrie.

Câmpul permisiunilor de acces-permisiunile de acces stabilite pentru fişierele create de

proces.

Page 32: Proiectarea Sistemelor de Operare

32

SUB 21PLASAREA ÎN MEMORIE A PROCESELOR

Memoria fizică a maşinii este adresabilă începând de la octetul cu deplasamentul 0 şi

mergând până la un deplasament egal cu cantitatea de memorie a maşinii.

Procesele în sistemul UNIX sunt formate din trei secţiuni logice: text, date şi stivă. Secţiunea

de text conţine un set de instrucţiuni executate de maşină; adresele din secţiunea de text includ

adresele codului în cazul instrucţiunilor de ramificare (sau apel de subrutine),

adresele de date (pentru accesul la variabilele de date globale) sau

adresele de stivă (pentru accesul la structurile de date locale ale subrutinelor)

Compilatorul generează adrese pentru un spaţiu virtual de adrese cu un domeniu de adrese,

iar unitatea de gestiune a memoriei maşinii translatează adresele virtuale generate de compilator

în adrese de locaţii în memoria fizică.

Toate procesele se vor executa folosind aceleaşi adrese virtuale, dar vor referi diferite adrese

fizice. Subsistemele nucleului şi hardware-ul ce cooperează la translatarea adresei virtuale în

adresă fizică formează sistemul de gestiune a memoriei.

Nucleul împarte spaţiul virtual de adrese al procesului în regiuni logice.

O regiune este o zonă contiguă a spaţiului virtual de adrese al procesului care poate

fi tratată ca un obiect distinct şi poate fi partajată sau protejată. Astfel textul, datele şi stiva,

de obicei formează regiuni separate ale procesului.

Mai multe procese pot folosi în comun aceeaşi regiune.

Nucleul conţine o tabelă a regiunilor şi alocă câte o intrare din tabelă pentru fiecare

regiune activă în sistem.

In mod analog fiecare proces conţine o tabelă privată de regiuni per process (per process

region table), numită pe scurt pregion.

Intrările acesteia pot exista în tabela de procese, u area sau într-o zonă de memorie

alocată separat depinzând de implementare. Fiecare intrare a tabelei private de regiuni pointează

către o intrare a tabelei globale de regiuni şi conţine adresa virtuală de start a regiunii în proces.

Intrarea tabelei private de regiuni mai conţine câmpul permisiunilor ce indică tipul de

acces permis procesului: numai citire, citire-scriere sau citire-execuţie.

Fiecare proces accesează regiunea printr-o intrare proprie în tabela privată de

regiuni la fel cum accesează inodul printr-o intrare proprie în tabela descriptorilor

de fişiere a utilizatorului şi în tabela de fişiere din nucleu.

Conceptul de regiune este independent de politicile de gestiune a memoriei implementate

de sistemul de operare. Politica de gestiune a memoriei se referă la acţiunile nucleului ce

asigură împărţirea corectă a memoriei principale de către procese. De exemplu, două

politici de gestiune a memoriei sunt: swapping-ul şi paginarea la cerere. Conceptul de

regiune este deasemenea independent de implementarea gestiunii memoriei:dacă

memoria este împărţită în pagini sau segmente.

Page 33: Proiectarea Sistemelor de Operare

33

SUB 22PLASAREA ÎN MEMORIE A NUCLEULUI

Nucleul se execută în contextul unui proces, însa translatarea memoriei virtual asociată

nucleului este independentă de toate procesele. Codul şi datele pentru nucleu rezidă permanent în

sistem, şi toate procesele îl partajează. Când sistemul este pus la lucru (la încărcare), el încarcă

codul nucleului în memorie şi setează tabelele necesare şi regiştrii pentru maparea adreselor lui

virtuale în adrese fizice de memorie.

Tabelele de pagini ale nucleului sunt analoage cu tabelele de pagini asociate fiecărui proces,

iar mecanismele folosite la maparea adreselor virtuale ale nucleului sunt similare cu cele folosite

pentru adresele utilizator.

Când execuţia este în modul nucleu, sistemul permite accesul la adresele nucleului, dar

înterzice un astfel de acces când execuţia este în modul utilizator.

Page 34: Proiectarea Sistemelor de Operare

34

SUB 23CONTEXTUL PROCESELOR Contextul procesului reprezintă conţinutul spaţiului său de adrese (al utilizatorului),

conţinutul regiştrilor hardware şi structurile de date ale nucleului care au legătură cu procesul.

Formal, contextul procesului este format din contextul de nivel utilizator (userlevel context),

contextul registru (register context), şi contextul de nivel sistem (systemlevel context).

Contextul de nivel utilizator cuprinde zonele de text, date, stivă utilizator şi memorie

partajată care ocupă spaţiul virtual de adrese al procesului.

Contextul registru cuprinde următoarele componente.

Numărătorul de program specifică adresa instrucţiunii următoare pe care o va executa

UCP; aceasta este o adresă virtuală în nucleu sau în spaţiul de memorie al utilizatorului.

Registrul de stare al procesorului (PS) specifică starea hardware a maşinii pe care

rulează procesul.

Pointerul stivei conţine adresa curentă a următoarei intrări în stiva nucleu sau în stiva

utilizator, determinată de modul de execuţie.

Regiştrii generali conţin date generate de proces în timpul execuţiei. Pentru a simplifica

discuţia, să diferenţiem doi regiştri generali, registrul 0 şi 1, folosiţi pentru transmiterea

informaţiilor între proces şi nucleu. Contextul de nivel sistem al procesului are o “parte statică” şi o “parte dinamică”.

Procesul are o parte statică a contextului de nivel sistem pe toată durata existenţei sale, dar poate

avea un număr variabil de părţi dinamice. Partea dinamică a contextului de nivel sistem trebuie

să fie văzută ca o stivă de cadre context pe care nucleul le introduce şi le extrage la apariţia

diferitelor evenimente.

Partea statică conţine următoarele componente.

Intrarea procesului în tabela de procese defineşte starea procesului şi conţine informaţii

de control care sunt permanent accesibile nucleului.

Zona u area a procesorului conţine informaţii de control care trebuie să fie accesate

numai în contextul procesului.

Intrările tabelei private de regiuni, tabelele de regiuni şi tabelele de pagini, definesc

maparea adreselor virtuale în adrese fizice şi deci definesc regiunile de text, date şi stivă

precum şi alte regiuni ale procesului. Dacă unele procese partajează regiuni comune,

regiunile sunt considerate părţi ale contextului fiecărui proces, pentru că fiecare proces

manipulează regiunile independent.

Partea dinamică conţine următoarele componente:

Stiva nucleului conţine cadrele de stivă ale procedurilor nucleului când un proces se

execută în modul kernel. Deşi procesele execută un cod nucleu identic, ele au copii

proprii ale stivei nucleului ce specifică apelurile proprii ale funcţiilor nucleului. De

exemplu, un proces poate invocă apelul sistem creat şi apoi trece în aşteptare până când

nucleul îi asignează un nou inod, iar alt proces poate invoca apelul sistem read şi trece în

aşteptare până când se va face transferul de date de pe disc în memorie. Ambele procese

execută funcţii nucleu, dar ele au stive separate ce conţin propriile secvenţe de apeluri de

funcţii.

Un set de cadre, vizualizate ca o stivă LIFO (last-in-first-out). Fiecare cadru al

contextului de nivel sistem conţine informaţiile necesare pentru refacerea cadrului

precedent, încluzând contextul registru al nivelului precedent.

Descrierea contextului unui proces:

Page 35: Proiectarea Sistemelor de Operare

35

În partea stângă a figurii din urmatoare este prezentată partea statică a procesului.

Aceasta conţine contextul de nivel utilizator, care conţine zona de text a procesului

(instrucţiunile), zona de date, zona de stivă şi zona de memorie partajată (dacă există), şi partea

statică a contextului de nivel sistem, care conţine intrarea în tabela proceselor, zona u area, şi

intrările tabelei private de regiuni(informaţii de mapare a adreselor virtuale ale contextului de

nivel utilizator).

Partea dreaptă a figurii prezintă partea dinamică a contextului. Aceasta conţine câteva

cadre de stivă, iar în fiecare cadru este salvat contextul registru al cadrului anterior şi stiva

nucleu a aceluiaşi cadru. Cadrul 0 al contextului de nivel sistem este o copie a contextului de

nivel utilizator; creşterea stivei se face aici în spaţiul de adresă al utilizatorului, şi stiva nucleu

este nulă. Săgeata pointează de la partea statică a contextului de nivel sistem cătr cadrul din

vârful părţii dinamice a contextului reprezentând informaţii logice stocate în intrarea din tabela

de procese pentru a da posibilitatea nucleului să refacă cadrul context curent al procesului.

Observaţii: Un proces rulează în cadrul contextului său curent. Numărul de cadre context este

limitat de numărul de nivele de întrerupere suportat de maşină. De exemplu, dacă o maşină

suportă diferite nivele de întrerupere pentru întreruperile software, terminale, discuri, toate

celelalte periferice, şi ceas, ea suportă 5 nivele de întrerupere, şi deci, procesul poate conţine

maxim 7 cadre context: câte unul pentru fiecare nivel de întrerupere, unul pentru apelurile

sistem, şi unul pentru nivelul utilizator.

Deşi nucleul se execută permanent în contextul unui proces, funcţia logică pe care o

execută nu este în mod necesar legată de proces. De exemplu, dacă un driver de disc întrerupe

maşina pentru că returnează date, el întrerupe rularea procesului iar nucleul execută rutina de

tratare a întreruperii într-un nou cadru context de nivel sistem al procesului aflat în execuţie,

chiar dacă datele aparţin unui alt proces. Rutinele de tratare întreruperilor în general nu

accesează sau modifică părţile statice ale contextului procesului, atât timp cât aceste părţi nu au

legătură cu întreruperea.

Page 36: Proiectarea Sistemelor de Operare

36

SUB 24SALVAREA CONTEXTULUI-SCHIMBARE DE

CONTEXT

Nucleul salvează contextul unui proces ori de câte ori el introduce în stivă un nou cadru

context de nivel sistem. În particular, aceasta se întâmplă când sistemul recepţionează o

intrerupere, când execută un apel sistem, sau când nucleul face o schimbare de context.

Sistemul răspunde de tratarea întreruperilor, indiferent dacă ele sunt întreruperi

hardware (cum ar fi de la ceas sau de la dispozitivele periferice), întreruperi programabile

(execuţia instrucţiunilor proiectate pentru a genera ―întreruperi software‖), sau excepţii (cum ar

fi erori de pagină).

Dacă UCP lucrează la un nivel de execuţie procesor mai scăzut decât nivelul întreruperii,

el acceptă întreruperea înaintea decodificării instrucţiunii următoare şi ridică nivelul de execuţie

al procesorului, astfel încât nici o altă întrerupere a acelui nivel (sau mai scăzut) nu se poate

produce cât timp tratează întreruperea curentă păstrând integritatea structurilor de date ale

nucleului.

Tratarea întreruperilor

Nucleul tratează întreruperea cu următoarea secvenţă de operaţii:

1. Salvează contextul registru curent al procesului în execuţie şi creează (introduce în

stivă) un nou cadru context.

2. Determină ―sursa‖ sau cauza întreruperii, identifică tipul întreruperii (de ceas sau de

disc) şi numărul unităţii care a produs întreruperea, dacă este cazul(cum ar fi driverul de disc).

Când sistemul recepţionează o întrerupere, aceasta primeşte un număr de la maşină pe

care îl foloseşte ca deplasament într-o tabelă, numită de obicei vector de întrerupere. De obicei

conţine adresa rutinei de tratare a întreruperii corespunzătoare sursei de întrerupere şi calea de

găsire a parametrilor pentru rutină.

3. Nucleul invocă rutina de tratare a întreruperii. Stiva nucleu pentru noul cadru context

este din punct de vedere logic distinctă de stiva nucleu pentru cadrul context anterior.

4. După terminarea execuţiei rutinei de tratare a întreruperii se reia execuţia proceslui

curent.

Nucleul execută o secvenţă de instrucţiuni specifice maşinii şi reface context registrul şi

stiva nucleu a cadrului context anterior aşa cum erau în momentul apariţiei întreruperii şi

apoi reia execuţia cadrului restaurat.

Schimbarea contextului

Nucleul permite o schimbare a contextului doar în patru situaţii:

1. când un proces se pune singur în aşteptare,

2. când acesta se termină,

3. când revine dintr-un apel sistem în modul utilizator dar nu este procesul cel mai potrivit

pentru execuţie,

4. când acesta revine în modul utilizator după ce nucleul termină tratarea unei întreruperi

dar nu este cel mai potrivit proces pentru execuţie.

Nucleul asigură integritatea şi consistenţa structurilor de date interne prin interzicerea

schimbărilor de context arbitrare. Acesta se asigură că starea structurilor sale de date este

consistentă înainte de a realiza schimbarea contextului: dacă toate actualizările au fost făcute,

dacă toate listele sunt înlănţuite corect, dacă anumite structuri de date sunt blocate pentru a

împiedica accesarea lor de către alte procese, dacă nu există structuri de date rămase blocate când

nu este necesar, şi altele.

Page 37: Proiectarea Sistemelor de Operare

37

Situaţii de schimbare a contextului

Nucleul trebuie să execute o schimbare a contextului la terminarea apelului sistem exit,

deoarece nu mai are nimic de făcut. În mod similar nucleul permite o schimbare de context când

un proces se pune în aşteptare deoarece poate trece o perioadă considerabilă de timp până când

procesul va fi trezit, şi alte procese pot fi executate între timp. Nucleul permite o schimbare de

context când un proces nu este cel mai potrivit pentru a fi rulat, pentru a permite planificarea

proceselor adecvate: dacă un proces termină un apel sistem sau revine dintr-o întrerupere şi

există un alt proces cu prioritate mai mare care aşteaptă să ruleze, ar fi incorect să menţinem în

aşteptare procesul cu prioritate mai mare.

Pasi in schimabarea contextului

1. Decide dacă se face schimbarea de context şi dacă schimbarea de context este permisă

acum.

2. Salvează contextul ―vechiului‖ proces.

3. Găseşte ―cel mai bun‖ peoces pentru planificarea la execuţie.

4. Reface contextul acestuia.

Pseudocodul schimbarii contextului

if(salveaza_contex()) /*salvarea contextului procesului executie*/

{

/*allege un alt process pentru executie*/

reface_context(noul_proces);

/*nu este gasit nimic aici*/

}/*reia executia procesului de aici* /

Observaţii

Nucleul în multe implementări, salvează contextul într-un punct al proceslui curent, dar

continuă să execute schimbarea de context şi algoritmii de planificare în contextul vechiului

proces. Când el mai târziu reface contextul procesului, reiaexecuţia în conformitate cu contextul

salvat anterior. Pentru a diferenţia cazul în care nucleul reface contextul noului proces de cazul în

care el continuă execuţia în vechiul context după ce l-a salvat, valorile de revenire a funcţiilor

critice variază, sau numărătorul de program poate fi setat artificial.

Salvarea contextului la întoarcerile forţate

Situaţiile apar când nucleul trebuie să iasă forţat din secvenţa curentă de execuţie şi să

părăsească imediat un context salvat anterior. Algoritmul de salvare a contextului se numeşte

setjmp şi algoritmul de refacere a contextului este longjmp. Metoda este identică cu cea descrisă

pentru funcţia salvare-context, cu excepţia faptului că salvare-context adaugă un nou cadru

context, pe când setjmp memorează contextul salvat în u area şi continuă să execute vechiul strat

context. Când nucleul doreşte să reia vechiul context salvat cu setjmp, el apelează longjmp,

restaurând contextul din zona u area şi returnând 1 pentru setjmp.

Page 38: Proiectarea Sistemelor de Operare

38

SUB25CREAREA PROCESELOR –FORK

Singurul mod prin care un utilizator poate crea un nou proces în UNIX estefolosirea

apelului sistem fork. Procesul care apelează fork este numit proces părinte(parent), iar noul

proces creat este numit proces fiu (child). Sintaxa pentru apelulsistem fork este:

pid=fork();

La revenirea din apelul sistem fork, două procese au copii identice ale contextului lanivel

utilizator, excepţie făcând valoarea de retur a pid-ului. În procesul părinte, pid-ulare valoarea

identificatorului procesului fiu; în procesul fiu, pid-ul are valoarea zero.Procesul 0, creat intern

de către kernel când sistemul este iniţializat este singurulproces care nu este creat prin

intermediul apelului sistem fork.

Nucleul execută următoarea secvenţă de operaţii la apelul sistem fork:

1. Alocă o intrare în tabela de procese penrtru noul proces.

2. Atribuie un identificator unic procesului fiu.

3. Face o copie logică a contextului procesului părinte.

4. Incrementeză contorii tabelei de inoduri şi tabelei de fişiereasociate procesului.

5. Întoarce în procesul părinte numărul identificatoruluiatribuit procesului fiu şi valoarea

zero în procesul fiu.

algoritm fork

intrări: niciuna

ieşiri: la procesul părinte, identificatorul procesul fiu (PID)

la procesul fiu, 0

{

verifică resursele disponibile ale nucleului;

obţine o intrare liberă în tabela de procese şi un număr unic pentruPID;

verifică ca utilizatorul să nu ruleze prea multe procese;

marchează starea procesului ca "în curs de creare";

copiază datele din intrarea în tabela de procese corespunzătoareprocesului părinte în

noua intrare a pocesul fiu;

incrementează contorul inodului directorului curent şi al rădăciniischimbate(dacă este

necesar);

incrementează contoarele fişierelor deschise în tabela de fişiere;

face o copie a contextului procesului părinte (u area, text, date,stivă)în memorie;

depune o copie fidelă a contextului de nivel sistem în contextulde nivel sistem al fiului;

contextul conţine date care permit procesului fiu să se recunoascăsingur şi să înceapă să

ruleze de aici atunci când este planificat;

if (procesul în execuţie este procesul părinte)

{ schimbă starea procesului în "gata de execuţie";

/* dinspre sistem către utilizator */

return(idetificatorul procesului fiu);

}

else /* procesul care se execută este procesul fiu */

{

iniţializează câmpurile de timp ale zonei u area;

return (0); /*cåtre utilizator*/ } }

Page 39: Proiectarea Sistemelor de Operare

39

Page 40: Proiectarea Sistemelor de Operare

40

SUB 26COMUNICAREA INTRE PROCESE PRIN PIPE,

DUP,FORK Execuţia fiecărui apel sistem pipealocă în plus 2 descriptori de fişiere în şirurile to_par şi

to_child. Procesul execută forkşi face o copie a contextului său: fiecare proces poate accesa

datele proprii, ca înexemplul anterior. Procesul părinte închide fişierul său standard de ieçire

(descriptorulde fişier 1) şi duplică (dup) descriptorul de scriere întors de pipe pentru to_child.

Deoarece primul slot liber din UFDT-ul părintelui este chiar acela eliberat prin apelulsistem

close, nucleul copiază descriptorul de scriere rezultat în urma executăriiapelului sistem pipe în

slotul 1 al UFDT-lui şi astfel descriptorul fişierului standard deieşire devine descriptorul de

scriere al pipe-lui pentru to_child. Procesul părinte faceoperaţii similare astfel încât descriptorul

intrării standard să devină descriptorul decitire al pipe-lui pentru to_par. Analog, procesul fiu îşi

închide fişierul standard deieşire (descriptor 0) şi duplică descriptorul de citire al pipe-lui pentru

to_child. Întrucâtprimul slot liber în UFDT este slotul fostuului fişier standard de intare, intrarea

standard a fiului devine descriptorul de citire al pipe-lui pentru to_child. Fiul faceoperaţii

similare astfel încât descriptorul ieşirii standard să devină descriptorul de Scriere al pipe-lui

pentru to_par. Ambele procese închid descriptorii de fişiere întorşi deapelarea lui pipe ( o bună

metodă de programare ). Ca rezultat, când părintele scriela ieşirea standard, acesta scrie în pipe-

ul to_child şi trimite date procesului fiu, careciteşte pipe-ul ca pe propria intrare standard. Când

procesul fiu scrie la ieşireastandard, acesta scrie în pipe-ul to_par şi trimite datele procesului

părinte care citeştepipe-ul ca pe propria intrare standard. Procesele astfel schimbă mesaje prin

intermediul pipe-urilor.

Similar, nu este nici o diferenţă faţă deordinea relativă în care procesele îşi esxecută

apelurile sistem până când acestea intrăîn ciclu: structurile nucleului sunt identice. Dacă procesul

fiu execută apelul sistemread înainte ca procesul părinte să facă write, procesul fiu va intra în

aşteptare pânăcând procesul părinte scrie pipe-ul şi este trezit. Dacă procesul părinte scrie pipe-

ulînainte ca procesul fiu să citească pipe-ul, părintele nu va citi de la intrarea sa

standard până când fiul nu de la citeşte intrarea sa standard şi nu scrie la ieşirea sastandard. Din

acest motiv, ordinea de execuţie este fixată: fiecare proces termină unapel sistem read şi write şi

nu poate termina următorul apel sistem read până cândcelălalt proces nu termină un apel sistem

read şi write.

Page 41: Proiectarea Sistemelor de Operare

41

SUB 27GESTIUNEA SEMNALELOR Semnalele informează procesele despre apariţia evenimentelor asincrone. Procesele îşi

pot trimite semnale prin intermediul apelului sistem kill, sau nucleul poate trimiteintern semnale.

Există 19 semnale în versiunea de UNIX System V (Release 2) carepot fi clasificate după cum

urmează :

1. Semnale pentru terminarea proceselor, transmise atunci cînd un proces execută apelul

sistem exit sau când un proces execută apelul sistem signal cu parametrul "terminare fiu";

2. Semnale de atenţionare în cazul excepţiilor produse de procese, de exemplu când un

proces accesează o adresă în afara spaţiului lor virtual de adrese, când un proces încearcă

să scrie în zonele de memorie protejate la scriere (cum ar fi codul programului), când

execută o instrucţiune

privilegiată, sau pentru diferite erori hardware;

3. Semnale pentru situaţii fără ieşire apărute în timpul apelurilor sistem, cum ar fi lipsa

resurselor în timpul execuţiei apelului sistem exec după ce spaţiul iniţial de adrese fusese

eliberat

4. Semnale determinate de condiţii de eroare neaşteptate apărute în timpul unui apel sistem;

5. Semnale provenite de la procesele în modul utilizator, de exemplu când un proces doreşte

să recepţioneze un semnal alarm după un anumit timp, sau când procesele trimit unul

altuia semnale în mod arbitrar, prin intermediul apelului sistem kill;

6. Semnale provenite de la interacţiunea cu un terminal, atunci când un utilizator întrerupe

un terminal, sau când un utilizator apasă tastele "break" sau "delete";

7. Semanale de urmărire a execuţiei unui proces.

Page 42: Proiectarea Sistemelor de Operare

42

Tratarea semnalelor este diferită după cum nucleul trimite un semnal unui proces, cum

tratează procesul un semnal şi cum un proces îşi controlează reacţia la apariţia unuisemnal.

Pentru a trimte un semnal unui proces, nucleul setează un bit în câmpul signaldin intrarea tabelei

proceselor, corespunzător tipului semnalului recepţionat.

Tratarea semnalelor. Nucleul tratează semnalele în contextul procesului care le recepţionează, deci un

proces trebuie să ruleze pentru a putea trata semnalele. Există trei cazuri în tratarea

semnalelor: procesul apelează exit la recepţionarea semnalului, acesta ignoră

semnalul, sau execută o funcţie particulară (definită de utilizator). Acţiunea implicită

este de a apela exit în modul nucleu, dar un proces poate specifica o acţiune specială,

pe care s-o execute la recepţionarea unui anumit semnal cu ajutorul apelul sistemsignal.

Sintaxa pentru apelul sistem signal este:

oldfunction=signal (signum, function);

• signum - numărul semnalului pentru care procesul specificăacţiunea;

• function - adresa funcţiei (utilizator) pe care procesul doreşte să oapeleze la recepţia

semnalului;

•oldfunction - valoarea parametrului function la ultimul apel al lui

signal cu parametrul signum.

Page 43: Proiectarea Sistemelor de Operare

43

SUB 28TRIMITEREA DE SEMNALE LA PROCESE

Procesele trimit semnale folosind apelului sistem kill. Sintaxa pentru acest apel este:

kill (pid, signum)

• pid identifică setul de procese care primesc semnalul;

• signum este numărul semnalului trimis.

În lista care urmează se arată corespondenţa dintre valorile parametrului pid şi seturile de

procese.

• Dacă pid este un întreg pozitiv, nucleul trimite un semnal procesului care are

identificatorul de proces pid.

• Dacă pid este 0, nucleul trimite semnal tuturor proceselor din grupul procesului care a

trimis semnalul.

• Dacă pid este -1, nucleul trimite semnalul tuturor proceselor al căror identificator al

utilizatorului real este egal cu identificatorul utilizatorului efectiv al procesului care a

trimis semnalul;

• Dacă pid este un întreg negativ diferit de -1, nucleul trimite semnalul tuturor proceselor

din grupul de procese care au valoarea absolută egală cu valoarea parametrului pid.

În toate cazurile, dacă procesul care trimite semnalul nu are UID efectiv al

superutilizatorului, sau UID-ul său efeciv sau real este diferit de UID-ul procesului destinatar,

kill eşuează.

Page 44: Proiectarea Sistemelor de Operare

44

SUB 29SHELLUL

Shell-ul citeşte o linie de la intrarea sa standard şi o interpretează după un set fixat de

reguli. Descriptorii fişierelor standard de intrare şi de ieşire pentru shell-ul de logare în sistem

sunt de obicei ai terminalului pe care utilizatorul îi foloseşte.

Dacă shell-ul recunoaşte şirul de intrare ca fiind o comandă internă (de exemplu,

comenzile cd, for, while şi altele), el execută comanda intern fără a mai crea procese; altfel,

presupune că aceasta este numele unui fişier executabil.

COMENZI SHELL

Cea mai simplă linie de comandă conţine un nume de program şi câţiva parametri cum

ar fi:

who

grep -n include *.c

ls -1

Shell-ul execută un apel fork şi crează un proces fiu care execută programul pe

care utilizatorul l-a specificat în linia de comandă. Procesul părinte, shell-ul care

este folosit de utilizator, aşteaptă până când procesul fiu termină comanda şi apoi revine în ciclu

pentru a citi comanda următoare.

Pentru a rula un proces asincron (în fundal), ca de exemplu:

nroff -mm big document &

shell-ul setează o variabilă internă amper când analizează caracterul &. Dacă găseşte variabila

setată la sfârşitul buclei, nu se execută wait dar imediat reîncepe ciclul şi citeşte următoarea linie

de comandă.

Exemplul de mai jos arată cum tratează shell-ul o linie de comandă ls-l|wc cu un singur

pipe. După ce procesul părinte

apelează fork şi crează un proces

fiu, fiul crează un pipe. Procesul fiu

execută la rândul său un apel fork;

el şi fiul său tratează fiecare câte o

componentă a liniei de comandă.

Procesul fiu ( ‖ nepotul ‖ ) creat

prin al doilea apel fork execută

prima componentă a comenzii (ls):

el scrie în pipe, aşa că închide

descriptorul fişierului său standard

de ieşire, duplică descriptorul de

scriere în pipe şi închide

descriptorul iniţial de scriere în pipe pentru că acesta nu mai este necesar.

Ralucs
Highlight
Ralucs
Typewritten Text
Ralucs
Typewritten Text
Ralucs
Typewritten Text
subiect scos
Page 45: Proiectarea Sistemelor de Operare

45

SUB 30 Subiect scos

SUB 31 POLITICILE DE PLANIFICARE

Planificarea proceselor

nucleul aloca CPU unui proces pentru o cuanta de timp( perioada numita time-slice sau

time-quantum)

Fiecare proces activ are o scheduling priority

K comuta contextul de la un proces la altul cu prioritate superioara

K

o re-calculeaza prioritatea procesului in curs de executie atunci cand el revine din

K mode in U mode

o periodic reajusteaza prioritatea fiecarui process ―ready to run‖ in U mode

clock-tick-intreruperede ceas(de 50-100 de oriper secunda)

Algoritmul: Round-Robin with Multilevel Feedback

algoritm planificare_proces

intrare: niciuna

ieşire: niciuna

{

while (nu este ales proces la execuţie)

{ for (fiecare proces din coada de rulare)

alege procesul cu prioritatea cea mai mare care este încărcat în memorie;

if (nici un proces eligibil de executat)

pune maşina în starea idle (no operating);

/* întreruperile o pot scoate din starea idle ‖ */ }

scoate procesul ales din coada de rulare;

schimbă contextul în cel al procesului care a fost ales, preia execuţia acestuia;

}

La încheierea comutării contextului, nucleul execută algoritmul de planificare a unui

proces selectând procesul cu cea mai mare prioritate din cele care se află în stările ―gata de

execuţie şi încărcat în memorie‖ şi ―întrerupt‖. Nu are nici un sens selectarea unui proces dacă

nu este încărcat în memorie, deoarece nu poate fi executat până când nu este încărcat în memoria

de lucru. Dacă mai multe procese au fixată cea mai mare prioritate, nucleul alege acel proces

care a fost pentru cea mai lungă perioadă de timp în starea ―gata de execuţie‖, conform politicii

de planificare a listei circulare. Dacă nu există nici un proces gata de execuţie, procesorul trece în

starea idle (inactivă) până la următoarea întrerupere de ceas; după tratarea întreruperii, nucleul

încearcă din nou să planifice un proces.

Priorităţile proceselor

Fiecare intrare în tabela(Process table entry) proceselor (PT) conţine un câmp de

prioritate(Priority fileld) pentru planificare.

Domeniul priorităţilor procesului poate fi partiţionat în două clase :

user priorities (calculate)-procese care au fost intrerupte la trecerea din K mode in Umode

kernel priorities (fixe)-procese aduse in aceasta stare prin alg. Sleep cauza lui sleep

creaza nivelul de prioritate.

o interuptibile

o ne-interuptibile

Page 46: Proiectarea Sistemelor de Operare

46

Observatie: Procesele cu prioritate nucleu scăzută se pot trezi la recepţionarea unui semnal, dar

procesele cu prioritate nucleu ridicată continuă să rămână în starea de aşteptare (sleep).

Prioritatile proceselor

Mutarea procesului dintr-o coadă în alta de priorităţi

Efectul recalculării priorităţilor o dată pe secundă este acela că procesele cu priorităţi

de nivel utilizator sunt mutate între listele de priorităţi, aşa cum se arată în figura

Page 47: Proiectarea Sistemelor de Operare

47

Calculul prioritatilor –in User mode (ready-to-run)

Clock-Handler-ajusteaza toate prioritatile proceselor in User mode (ready-to-run) la

interval de 1 secunda(60 IT de ceas)

o la fiecare clock-interrupt se incrementeaza un camp in PT entry astfel ca in PT se

retine pentru proces:recent CPU usage

o la fiecare1 secunda Clock-Handler ajusteaza recent CPU usage folosind functia

decay:

Decay(recent CPU usage)=recent CPU usage/2

cand se recalculeaza recent CPU usage,Clock-Handler calculeaza prioritatea fiecarui

proces ready-to-run cu formula:

Priority = (―recent CPU usage‖/2)+(base level user priority)

Valoare mica=prioritate mare !!!

Base level user priority = threshold value (ex.60)

Exemplu de planificare a proceselor

Liste circulare de planifiacare si prioritatile proceselor

Exemplul de planificator cu partajare corecta

Principiul planificatorului cu partajare corectă este să se împartă comunitatea

utilizatorilor într-un set de grupuri partajate corect, astfel încât membri fiecărui grup sunt

subiectul constrângerilor unui planificator de procese obişnuit relativ la alte procese din grup.

Totuşi, sistemul alocă timpul UCP proporţional fiecărui grup, fără a ţine seama cât de multe

procese sunt în fiecare grup.

Page 48: Proiectarea Sistemelor de Operare

48

SUB 32 APELURI SISTEM PENTRU CLOCK

Apelurile sistem legate de clock sunt: stime, time, times şi alarm.

Primele două se ocupă cu timpul global al sistemului, iar ultimele două cu timpul

proceselor individuale.

• STIME-permite superuser-ului să seteze o variabilă nucleu globală la o valoare ce dă timpul

curent:

stime(pvalue);

unde pvalue pointează la un long integer ce dă timpul măsurat în secunde.

• TIME-furnizează timpul setat de către apelul sistem stime:

time(tloc);

unde tloc indică o locaţie în procesul utilizator pentru valoarea returnată.

•TIMES-furnizează timpii cumulaţi pe care procesul apelant i-a consumat în modurile utilizator

şi nucleu şi timpii cumulaţi consumaţi de toate procesele fiu în starea zombie în modurile

utilizator şi nucleu. Sintaxa apelului este

times(tbuffer)

struct tms*tbuffer;

unde structura tms conţine timpii obţinuţi şi este definită prin

struct tms {

/* time_t este structura pentru timp */

time_ttms_utime;/*timpul cumulat în modul utilizator de către proces*/

time_ttms_stime;/*timpul cumulat în modul nucleu de către proces*/

time_ttms_ctime;/*timpul cumulat în modul utilizator de către fii*/

time_ttms_cstime;/*timpul cumulat în modul nucleu de către fii*/

};

Factorul comun în toate apelurile sistem de timp prezentate este ceasul sistemului:

nucleul manipulează variate numărătoare de timp când tratează întreruperile de ceas

şi iniţiază acţiuni corespunzătoare.

Exemple de programe: pentru apelurile sistem times si alarm

Ralucs
Highlight
Page 49: Proiectarea Sistemelor de Operare

49

SUB 33GESTIUNE CLOCK

Ceasul

Funcţiile rutinei de tratare a întreruperilor de ceas Clock-Handler-sunt:

reporneşte ceasul;

planifică apelurile funcţiilor interne ale nucleului pe baza timerelor interne;

furnizează posibilitatea schiţării execuţiei proceselor în modul nucleu şi utilizator;

calculează statistici pentru procese şi sistem;

urmăreşte timpul;

trimite semnale de alarmă proceselor care solicită acest lucru;

trezeşte periodic procesul încărcător;

controlează planificarea proceselor.

Algoritmul pentru tratarea intreruperilor de ceas

Nucleul înmagazinează informaţia necesară într-o tabelă callout (tabelă de timeout) ce

conţine funcţia care trebuie apelată atunci când timpul expiră, un parametru pentru funcţie şi

timpul în impulsuri de ceas până când funcţia ar trebui să fie apelată.

Algoritmul clock

intrări: niciuna

ieşiri: niciuna

{

reporneşte ceasul (astfel încât întreruperea de ceas să apară în continuare)

if (tabela de timeout nu este goală)

{

ajustează timpii de timeout;

planifică funcţia de timeout dacă timpul a expirat;

}

if (nucleul prezintă facilităţi de profiling)

reţine numărătorul de program la momentul întreruperii;

if (utilizatorul prezintă facilităţi de profiling)

reţine numărătorul de program la momentul întreruperii;

calculează statisticile per sistem;

calculează statisticile per proces;

ajustează mărimea valorii de utilizare a UCP

if ( a trecut o secundă sau mai mult de când s-a aflat aici iar întreruperea nu se află

într-o regiune critică)

{

for (toate procesele din sistem)

{

ajustează timpul în cazul alarmei active;

ajustează mărimea valorii de utilizare a UCP;

if (procesul se execută în modul utilizator)

ajustează prioritatea procesului;

}

trezeşte procsul swapper dacă e necesar;

}}

Page 50: Proiectarea Sistemelor de Operare

50

SUB 34ALOCAREA SPATIULUI DE SWAP

Dispozitivul de swap este un dispozitiv de tip bloc într-o secţiune configurabilă a discului.

Pe câtă vreme nucleul alocă spaţiu pentru fişiere bloc cu bloc, în zona de swap spaţiul este

alocat în grupuri de blocuri contigue.

Alocarea spaţiului pe dispozitivul de swap este tranzitorie, depinzând de modul de planificare

a proceselor.

Un proces care rezidă pe dispozitivul de swap va migra, în cele din urmă, înapoi în memoria

principală, eliberând spaţiul pe care l-a ocupat în zona de swap.

Nucleul păstrează evidenţa spaţiului liber pentru dispozitivul de swap într-o tabelă în

memoria internă denumită map.

Map-urile permit o alocare tip first-fit (prima potrivire) a blocurilor contigue de resursă.

Map este o tabelă în care fiecare intrare constă într-o adresă a unei resurse alocabile şi numărul

corespunzător de unităţi de resursă disponibile; nucleul interpretează adresa şi unităţile în

concordanţă cu tipul tabelei map. Iniţial, map conţine o intrare care indică adresa şi numărul

total de resurse. De exemplu, nucleul tratează fiecare unitate a map ca un grup de blocuri disc,

iar adresa este tratată ca un offset (deplasament) faţă de începutul zonei de swap.

Algoritm pentru alocarea spaţiului din Map

Algorithm malloc /* algoritm pentru alocarea spaţiului din map */

input: (1) map address/* indicăcare map trebuiefolosit*/

(2) requested number of units

output: address, if successful 0, otherwise

{

for(every map entry)

{

if(current map entry can fit requested units)

{

if(requested units == number of units in entry)

delete entry from map;

else

adjust start address of entry;

return(original address of entry);

}

}

return(0);

}

Nucleul caută în tabela map prima intrare care conţine spaţiu suficient pentru cererea

făcută. Dacă cererea consumă toate resursele intrării din map, nucleul şterge intrarea

din tabelă şi comprimă tabela în mod corespunzător. Dacă cererea este mai mică decât

numărul de unităţi al intrării din tabelă, nucleul ajustează câmpurile de adresă şi

număr de unităţi ale intrării în concordanţă cu cantitatea de resurse alocate.

Page 51: Proiectarea Sistemelor de Operare

51

Alocarea spatiului de Swap

Când eliberează resurse, kernel-ul găseşte poziţia lor corespunzătoare din mapdupă

adresă.

Trei cazurisunt posibile:

1.Resurseleeliberateacoperăcompletunspaţiudinmap:elesuntcontiguecuintrărilealecăroradreselepr

ecedimediatşileurmeazăînmap.Înacestcaz,kernel-ul combină intrările nou eliberate lor resurse cu

cele(două) deja existente într-o singură intrare în map.

2.Resursele eliberate umplu parţial un gol din map. Dacă adresele resurselor eliberate sunt

contigue cu intrarea din map cele-ar precede imediat sau le-ar urma imediat (dar nu amândouă )

kernel-ul ajustează câmpurile ‖adresss‖şi―units‖ ale intrării respective pentru a include şi

resursele tocmai eliberate.

3.Resursele eliberate acoperă parţial un gol dar nu sunt contigue cu nici o resursădin map.

Kernel-ul creazăo nouă intrare pentru map şi o inserează în poziţia corespunzătoare.

Eliberarea spatiului de swap

Alocarea Spatiului de Swap din a Doua Intrare din Map

Page 52: Proiectarea Sistemelor de Operare

52

SUB 35EVACUAREA PROCESELOR

Scoaterea unui proces din memorie

Kernel-ul duce un proces în spaţiul de swap când are nevoie de spaţiu în memorie, în

următoarele cazuri:

1. Apelul sistem fork trebuie să aloce spaţiu pentru un proces fiu,

2. Apelul sistem brk măreşte dimesiunea unui fişier,

3. Un proces se măreşte prin creşterea naturală a stivei sale,

4. Kernel-ul doreşte să elibereze spaţiu în memorie pentru procese pe care le-a scos anterior din

memorie în spaţiul de swap şi pe care acum trebuie să le readucă în memorie.

Daca K decide ca un proces poate fi evacuat, mai intai se decrementeaza ref.count la fiecare

regiune a procesului; numai daca apoi valoarea este 0 se aloca spatiu pe swap-device si se

scoate pe disc; apoi se pune adresa din swap-device in RT (Region Table)entry.

Nu este necesar ca nucleul să scrie întreg spaţiul virtual de adrese al unui proces în zona de

evacuare. În schimb, el copiază memoria fizică asigurată unui proces în spaţiul alocat pe

dispozitivul de swap, ignorând adresele virtuale neasigurate. Când nucleul încarcă înapoi în

memorie procesul, el cunoaşte tabela adreselor virtuale a procesului, astfel încât reasigură

procesul la adresele virtuale corespunzătoare.

Maparea spatiului unui proces in Swap Device (Swap out)

Page 53: Proiectarea Sistemelor de Operare

53

Aducerea unui proces in memorie (Swap in)

Ajustarea Map-ului Memoriei pentru Extinderea Swap-ului in urma unui brk sau

cresterea stack

Page 54: Proiectarea Sistemelor de Operare

54

SUB 36REINCARCAREA PROCESELOR

Swaper

Process0-swapper-ul este singurul proces care aduce procese in MI de pe swap-device-

SINGURUL PROCES KERNEL!!

Swapper sleeps-este wake-up de catre K si se executa cu o prioritate ridicata, dar in mod

kernel

Swapper nu face apeluri sistem ci foloseste functii K interne

Este tipic pentru un proces kernel

Cand Swapper este wake-up analizeaza procesele din coada ―ready-to-run-swapped‖; il

selecteaza pe cel care sta de cel mai mult timp in aceasta stare

Dacă este destulă memorie liberă disponibilă, swapper-ul încarcă procesul în memorie, executând operaţiile inverse evacuării: alocă memorie fizică, citeşte procesul din zona de swap şi

eliberează spaţiul de swap.

Algoritmul pentru Swapper

algoritm swapper /*încarcă procesele executate, evacuează alte procese pentru a face loc*/

intrare: nici una; ieşire: nici una;

{

buclă:

for (toate procesele evacuate care sunt "ready to run")

alege procesul care a stat cel mai mult evacuat;

if (nu există asemenea proces)

{ sleep(eveniment: trebuie să încarce);

salt la buclă;

}

if (este loc suficient pentru proces în memoria principală)

{ încarcă procesul;

salt la buclă;

}

/*bucla2:se află aici în algoritmul revizuit*/

for (toate procesele încărcate în memoria principală, care nu sunt zombie şi nu sunt

blocate în memorie)

{ if (există un proces în aşteptare )

alege procesul pentru care valoarea prioritate+timp de rezidenţă este cea

mai mare;

else (nu sunt procese care aşteaptă )

alege procesul pentru care valoarea timp de rezidenţă+nice este cea mai

mare:}

if (procesul ales nu este în aşteptare sau cerinţele de rezidenţă nu sunt satisfăcute )

sleep(eveniment : trebuie să incarce un proces);

else

evacuează procesul;

salt la buclă; /*goto buclă 2 în algpritmul revizuit */}

Secventa Operatiilor de Swapping ;

Page 55: Proiectarea Sistemelor de Operare

55

Thrashing cauzat de Swapping

Un asemenea caz este acela în care nucleul încarcă procesul D la secunda 2, planifică

procesul C şi apoi, la secunda 3, evacuează procesul D în favoarea procesului E (ca urmare a

acţiunii valorii nice ) dacă procesul D nu s-a executat.

SUB 37STRUCTURI DE DATE PENTRU DEMAND PAGING

Intrările în Tabela de Pagini şi Descriptori de Blocuri pe Disc

Legătura dintre Structurile de Date pentru Demand Paging

Page 56: Proiectarea Sistemelor de Operare

56

SUB 38,39 s-au scos

SUB 40PAGE STEALER

Diagrama de Stare pentru Îmbătrânirea Paginii

Ralucs
Highlight
Page 57: Proiectarea Sistemelor de Operare

57

SUB 41IPC-URI : MESAJE, ZONE COMUNE DE MEMORIE

Pachetul System V IPC din UNIX se compune din trei mecanisme:

1. Mesajele - permit proceselor să trimită fluxuri de date formatate către alte procese;

2. Memoria partajată - permite proceselor să folosească în comun părţi din spaţiul lor

virtual de adrese;

3. Semafoarele - permit proceselor să-şi sincronizeze execuţia.

MESAJELE

Există patru apeluri sistem pentru comunicarea prin mesaje:

•msgget - întoarce (sau creează) un descriptor de mesaje, care desemnează o coadă de mesaje,

utilizat ca parametru în celelalte apeluri sistem

•msgctl - dispune de opţiuni de setare sau examinare a valorilor parametrilor asociaţi unui

descriptor de mesaje, precum şi de o opţiune de eliberare a descriptorilor

•msgsnd - trimite un mesaj;

•msgrcv - recepţionează un mesaj.

Apelul sistem msgget

Sintaxa apelului sistem msgget este următoarea :

msgqid=msgget(key,flag)

•msgqid = descriptorul returnat de apelul sistem;

•key = cheie numerică, care reprezintă numele său desemnat de utilizator;

•flag = set de permisiuni de citire-scriere-execuţie separat pentru utilizator, grup şi ceilalţi,

similare permisiunilor de acces la fişiere.

Apelul sistem msgsnd

Procesele folosesc apelul sistem msgsnd pentru a trimite un mesaj, apelul având

următoarea sintaxă :

msgsnd(msgqid,msg,count,flag)

•msgqid = descriptorul cozii de mesaje, returnat în mod obişnuit de apelul sistem msgget;

•msg = un pointer către o structură de date – controlată de către utilizator – compusă din tipul

mesajului (care poate lua valori întregi) şi un şir de caractere;

•count - specifică dimensiunea în octeţi a şirului de caractere din structura msg;

•flag - precizează acţiunea pe care urmează să o întreprindă nucleul, însituaţia în care numai are

la dispoziţie suficient spaţiu în buffer – ele interne de memorie.

Algoritmul msgsnd/*trimitere mesaj*/

Intrări: (1)descriptorul cozii de mesaje

(2)adresa structurii de date pentru mesaje

(3)lungimea mesajului

(4)indicatori

Ieşiri: numărul de octeţi efectiv trimişi

Page 58: Proiectarea Sistemelor de Operare

58

{

verifică valabilitatea descriptorului şi a drepturilor de acces;

while (nu există spaţiu de memorie suficient pentru stocare a mesajului)

{

if (indicatorii specific faptul că procesul nu aşteaptă)

return;

sleep (eveniment: există spaţiu sufficient pentru stocarea mesajului)

}

obţine un antet de mesaj;

copiază mesajul propriu-zis din spaţiul utilizator în spaţiul nucleu;

actualizează structura de date:

-inserează în listă noul antet de mesaj;

-iniţializează pointerul din antetul de mesaj să pointeze către zona de date;

-înscrie valoarea:-contorului de octeţi;

-momentelor de timp;

-identificatorului procesului transmiţător;

trezeşte toate procesele care aşteaptă să citească mesaje din coadă;

}

Structurile de date pentru comunicarea prin mesaje

Apelul sistem msgrcv

Procesele recepţionează mesaje cu ajutorul apelului sistem msgrcv, care are următoarea

sintaxă : count=msgrcv(id, msg, maxcount, type, flag) .

•id = descriptorul de mesaj;

•msg = adresa unei structuri de date a utilizatorului în care se va scrie mesajul primit;

•maxcount = dimensiunea şirului de caractere din structura de date msg;

•type - specifică tipul de mesaj pe care utilizatorul doreşte să-l citească;

•flag – precizează ce trebuie să facă nucleul dacă nu există mesaje în coada de mesaje;

•count – reprezintă numărul de octeţi de date recepţionaţi efectiv de către utilizator.

Page 59: Proiectarea Sistemelor de Operare

59

Algoritmul msgrcv /*recepţionare mesaj*/

Intrări :(1) descriptorul de mesaj

(2) adresa vectorului de date pentru mesajele care sosesc

(3) dimensiunea vectorului de date

(4) tipul de mesaj cerut

(5) indicatori

Ieşiri: numărul de octeţi din mesajul returnat

{

verifică permisiunile;

ciclu:

verifică validitatea descriptorului de mesaj;

/*găseşte mesajul care va fi returnat către utilizator*/

if (tipul de mesaj cerut==0)

se consideră primul mesaj din coada de mesaje;

else

if (tipul de mesaj cerut > 0)

se consideră primul mesaj care are tipul cerut, din coada de mesaje;

else /* valoarea tipului mesajului este negativă */

se consideră primul mesaj dintre cele care au valoarea tipului cea mai

mică din coada de mesaje, astfel încâtaceastă valoare să fie mai mică sau

egală, în modul, cu valoarea tipului cerut;

if (există un mesaj)

{

corectează dimensiunea mesajului sau returnează eroare dacă dimensiunea dată

de utilizator este prea mică;

copiază tipul şi textul mesajului din spaţiul nucleu în spaţiul user;

sterge mesajul din coada de mesaje;

return;

}

/* nu există nici un mesaj */

if (indicatorul precizează ca procesul să nu treacă în aşteptare)

return (eroare);

sleep(eveniment:sosirea unui mesaj în coada de mesaje);

goto ciclu;

}

Apelul sistem msgctl.

Un proces poate inspecta starea unui descriptor de mesaj, îi poate seta valoarea şi poate

şterge un descriptor de mesaj cu ajutorul apelului sistem msgctl.

Sintaxa apelului este: msgctl (id, cmd, mstatbuf)

•id – identifică descriptorul de mesaj;

•cmd – precizează tipul comenzii;

•mstatbuf – reprezintă adresa structurii de date utilizator care va conţine parametrii de control sau

rezultatele unei interogări

Page 60: Proiectarea Sistemelor de Operare

60

MEMORIE PARTAJATA

Apelurile sistem pentru manipularea zonelor de memorie partajată sunt similare

apelurilor sistem dedicate comunicaţiei prin mesaje:

•shmget - crează o nouă zonă regiune de memorie partajată sau întoarce una existentă;

•shmat - ataşează logic o regiune de memorie la spaţiul virtual de adrese al unui proces;

•shmdt - detaşează o regiune de spaţiul virtual de adrese al unui proces;

•shmctl - manipulează diverşi parametri asociaţi zonelor de memorie partajată.

Apelul sistem shmget.

Sintaxa apelului sistem shmget: shmid=shmget(key,size,flag)

•size = numărul de octeţi din regiunea de memorie;

•key si flag la fel ca la celelalte.

Structurile de date implicate în gestiunea zonelor de memorie partajată

Apelul sistem shmat

Un proces ataşează o regiune de memorie comună spaţiului său virtua de adrese cu

ajutorul apelului sistem shmat, care areu rmătoarea sintaxă: virtaddr=shmat(id,addr,flags)

•id - returnat de apelul sistem shmget anterior, identifică regiunea de memorie partajată;

•addr = adresa virtuală unde utilizatorul doreşte să ataşeze regiunea de memorie partajată

•flags – specifică dacă regiunea este accesibilă numai pentru citire (read-only) şi dacă nucleu

ltrebuie să rotunjească adresa specificată de utilizator.

•virtaddr = adresa virtuală la care nucleul a ataşat regiunea, care nu trebuie să fie neapărat egală

cu valoarea cerută de către proces.

Algoritmul shmat/*ataşează o zonă de memorie*/

Intrări: (1)descriptorul zonei de memorie partajată

(2)adresa virtuală la care să se facă ataşarea

(3)indicatori

Ieşiri: adresa virtuală la care s-a ataşat zona de memorie partajată

{

verifică validitatea descriptorului şi a drepturilor de acces;

if (adresa virtuală specificată de utilizator!=0)

Page 61: Proiectarea Sistemelor de Operare

61

{

rotunjeşt eadresa virtuală conform specificaţiilor indicatorilor;

verifică validitatea adresei virtuale şi a dimensiunii regiunii;

}

else/*utilizatorul doreşte ca nucleul să găsească o adresă corespunzătoare*/

nucleul alege o adresa virtuală (daca nu este nici una disponibilă întoarce eroare);

ataşează regiunea la spaţiul de adrese al procesului (alg.attachreg)

if (regiunea este ataşată pentru prima dată)

alocă tabele de pagini, memorie pentru regiune (alg.growreg);

return (adresa virtuală la care s-a făcut ataşarea);

}

Apelul sistem shmdt

Un proces detaşează o regiune de memorie comună din spaţiul său virtual de adrese cu

ajutorul apelului sistem: shmdt(addr)

•addr = adresa virtuală întoarsă de un apel shmat anterior

Apelul sistem shmctl

Pentru examinarea stării şi stabilirea valorilor parametrilor unei regiuni de memorie

partajată, un proces utilizează apelul sistem shmctl,care are următoarea sintaxă:

shmctl(id, cmd, shmstatbuf)

•id – identifică intrarea corespunzătoare din tabela regiunilor de memorie partajată;

•cmd – precizează tipul operaţiunii;

•shmstatbuf = adresa unei structuri de date utilizator care conţine informaţiile de stare din

intrărea în tabel a regiunilor de memorie partajată, atunci când se face interogarea sau setarea

parametrilor de stare

Page 62: Proiectarea Sistemelor de Operare

62

SUB 42 s-a scos

SUB 43 SOCKET-URI Modelul comunicării prin socket-uri

Apeluri sistem pentru mecanismul de comunicare prin socket-uri:

• socket;

• close;

• bind;

• connect;

• listen;

• accept;

• send;

• recv;

• shutdown;

• getsockname;

• getsockopt;

• setsockopt

Apelul sistem socket

Apelul sistem socket stabileşte punctual final al unei legături de comunicaţie.

sd=socket(format, type, protocol);

•format - precizează domeniul de comunicaţie (domeniul UNIX, sau domeniul Internet);

•type - indică tipul de comunicaţie prin socket (circuit virtual, sau datagramă);

•protocol - precizează un anumit protocol pentru controlul comunicaţiei

•sd - descriptorul de socket.

Apelul sistem close - închide socket-urile.

- eliberează şi descriptorul de socket

Apelul sistem bind

Apelul sistem bind asociază un nume descriptorului de socket.

Page 63: Proiectarea Sistemelor de Operare

63

bind (sd, address, length)

•sd-descriptorul de socket;

•address-adresa unei structuri care precizează un indicator al domeniului şi protocolului de

comunicaţie, precizate în cadrul apelului sistem socket;

•length = lungimea structurii de date address -> fără acest parametru nucleul nu ar şti cât de

lungă este adresa, deoarece lungimea acesteia poate diferi de la un domeniu (sau protocol) la

altul.

Apelul sistem connect

Apelul sistem connect cere nucleului să facă o conexiune cu un socket existent.

connect(sd, address, length)

•sd - descriptorul de socket;

•address – adresa socket-ului destinaţie care va constitui celălalt capăt al liniei de comunicaţie.

•length = lungimea structurii de date address -> fără acest parametru nucleul nu ar şti cât de

lungă este adresa, deoarece lungimea acesteia poate diferi de la un domeniu (sau protocol) la

altul.

Apelul sistem listen

Apelul sistem listen precizează lungimea maximă a cozii de aşteptare.

listen (sd, qlength)

•sd = descriptorul de socket;

•qlength = numărul maxim de cereri care vor fi luate în consideraţie

Apelul sistem accept

Apelul sistem accept primeşte cererile de conectare la un process erver

nsd=accept(sd, address, addrlen)

•sd = descriptorul de socket;

•address - indică o zonă de date utilizator pe care nucleul o completează cu adresa de retur a

procesului client care se conectează;

•addrlen - precizează dimensiunea acestei zone.

Apelul sistem send

Apelul sistem send permite trimiterea datelor printr-un socket. Sintaxa apelului sistem send este:

count=send(sd, msg, length, flags)

•sd - descriptorul de socket;

•msg - un pointer către datele care urmează să fie transmise;

•length - lungimea datelor de transmis;

•count - numărul de octeţi efectiv transmişi;

•parametrului flags i se poate atribui valoarea SOF_OOB pentru a realiza o transmitere „out-of-

band‖ a unor date, înţelegând prin aceasta că datele trimise nu fac parte din schimbul obişnuit de

date între procesele care comunică.

Page 64: Proiectarea Sistemelor de Operare

64

Apelul sistem recv

Apelul sistem recv permite recepţionarea datelor printr-un socket. Sintaxa apelului

sistem recv este count=recv(sd, buf, length, flags)

•buf-locul unde se memorează datele care sosesc;

•length-lungimea aşteptată a datelor;

•count-numărul de octeţi efectiv copiaţi în programul utilizatorului;

•Parametrul flags poate primi valoarea „peek‖, pentru un mesaj care soseşte , în scopul

examinării conţinutului său fără a-l scoate din coada de aşteptare, sau valoarea „out-of-band‖

pentru cazul explicat mai sus;

•Versiunile pentru datagrame ale acestor apeluri sistem, sendto şi recvfrom, au în plus parametric

pentru adrese.

Apelul sistem shutdown

Apelul sistem shutdown închide o conexiune cu un socket

shutdown(sd, mode)

•sd – descriptorul de socket;

•mode-indică dacă partea care trimite datele, partea care le recepţionează, sau ambele părţi

încheie transmisia datelor.