Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml


Apelul sistem read - UNIX

linux



+ Font mai mare | - Font mai mic



Apelul sistem read - UNIX

Sintaxa apelului sistem read este:

numar = read(fd, buffer, contor);



unde fd este descriptorul de fisier returnat de catre open, buffer este adresa de memorie din spatiul procesului utilizator care va contine datele in caz de reusita a apelului, contor este numarul de octeti pe care utilizatorul doreste sa-i citeasca, iar numar este numarul de octeti cititi in urma apelului.

mode  indica tipul operatiei (citire sau scriere)

count  numarul de octeti ce urmeaza a fi cititi sau scrisi

offset  deplasamentul din fisier

address   adresa din spatiul nucleu sau utilizator in care se vor

copia datele

flag  indica tipul adresei (utilizator sau nucleu)

Figura 5.5. Parametrii de I/O salvati in u area

In figura 5.6 este prezentat algoritmul read pentru citirea unui fisier obisnuit. Nucleul determina intrarea in tabela de fisiere corespunzatoare descriptorului de fisier prin intermediul pointerului pastrat in intrarea din tabela descriptorilor de fisiere utilizator (vezi figura 5.3). O parte din parametrii de I/O sunt scrisi in u area pentru a se elimina necesitatea transmiterii lor ca parametrii ai functiei (fig.5.5.).

Algoritm read

intrari: descriptorul de fisier

adresa buffer-ului din spatiul de memorie al procesului utilizator

numarul de octeti ce se doreste a fi citit

iesire: numarul de octeti copiati in spatiul utilizator

deblocheaza inodul;

actualizeaza deplasamentul din tabela de fisiere pentru urmatoarea

operatie de citire;

return (numarul total de octeti cititi);

}

Figura 5.6. Algoritmul pentru citirea unui fisier

Astfel, este setat modul de I/O pentru a indica ca se executa o citire, un bit de semnalizare care indica faptul ca datele vor fi transferate in spatiul de adrese utilizator, un contor care indica numarul de octeti ce vor fi cititi, adresa buffer-ului din spatiul utilizator, si un camp de deplasament (copiat din tabela de fisiere) care precizeaza de unde va incepe citirea datelor.

Dupa stabilirea parametrilor de I/O in u area, folosind pointerul din tabela de fisiere catre intrarea din tabela de inoduri, nucleul blocheaza inodul inainte de a incepe citirea fisierului. Algoritmul intra apoi intr-un ciclu pana la citirea numarului dorit de octeti. Nucleul determina pe baza deplasamentului numarul blocului care va fi citit si il memoreaza. Dupa citirea unui bloc in memorie, folosind algoritmul bread sau breada, nucleul copiaza datele din bloc in spatiul de adrese utilizator al procesului .

Sunt modificati parametrii din u area corespunzator numarului de octeti cititi incrementand deplasamentul si adresa din spatiul utilizator la care va avea loc urmatorul transfer, si decrementand contorul cu numarul de octeti care mai trebuie cititi. Daca cererea utilizatorului nu a fost satisfacuta, nucleul reia executia operatiilor din ciclu. Acesta se va incheia cand nucleul satisface integral cererea utilizatorului, cand se ajunge la sfarsitul fisierului, sau cand se semnaleaza o eroare in desfasurarea unei operatii de citire de pe disc sau de scriere in spatiul utilizator.

#include <fcntl.h>

main()

Figura 5.7. Un exemplu de program de citire dintr-un fisier

In exemplul din figura 5.7, apelul open returneaza un descriptor de fisier care este atribuit variabilei fd si care va fi utilizata in secventa de apeluri de citire. La excutia apelului sistem read nucleul verifica daca descriptorul de fisier este legal si daca procesul a deschis anterior fisierul pentru citire. In u area sunt memorate valorile lilbuf, 20 si 0 in campurile adress, count, respectiv offset. Nucleul determina ca octetul cu deplasamentul 0 se afla in blocul cu numarul 0 din fisier si gaseste intrarea din inod corespunzatoare blocului. Presupunand ca un astfel de bloc exista, nucleul citeste intregul bloc (1ko) intr-un buffer, dar copiaza doar 20 de octeti la adresa lilbuf din spatiu utilizator. Apoi, incrementeaza deplasamentul cu 20 si decrementeaza contorul cu numarul de octeti ramasi de citit la 0. Deoarece operatia de citire s-a incheiat cu succes, nucleul reseteaza valoarea deplasamentulului din tabela de fisiere la 20, urmatoarea operatie de citire incepand de la octetul 20 al fisierului, iar apelul sistem returneaza numarul de octeti cititi, 20.



Dupa executarea tuturor verificarilor si initializarilor (efectuate si in cazul primei citiri), al doilea apel read va incepe citirea de la octetul 20. Pe durata executiei algoritmului de citire a blocului disc, exista posibilitatea ca acesta sa fie regasit in buffer-ul cache fara a mai fi nevoie de o operatie cu discul. Se copiaza cei 1004 ultimi octeti la adresa bigbuf. Apoi printr-o noua operatie cu discul, se citeste urmatorul bloc din care se copiaza incepand cu pozitia 1004 din bigbuf inca 20 de octeti din noul bloc. In mod asemanator se procedeaza si la cel de-al treilea apel read.

Exemplul arata ca cererile pentru operatii de I/O sunt avantajoase atunci cand deplasamentul de start corespunde unui inceput de bloc disc, iar lungimea transferului este multiplu de dimensiunea unui bloc. In acest fel se utilizeaza integral datele din blocurile disc citite, eliminandu-se o iteratie suplimentara a buclei din algoritmul read, si deci implicatiile ce decurg din acest lucru: accesul la inod pentru mai mult timp si concurenta alaturi de alte procese la buffer-ul cache.

Daca un proces citeste doua blocuri secvential, nucleul presupune ca toate citirile ulterioare vor fi secventiale pana cand acest lucru va fi infirmat. Pe durata fiecarei parcurgeri a buclei din apelul read, nucleul salveaza in inodul din memoria interna numarul urmatorului bloc logic, iar in cadrul urmatoarei parcurgeri compara numarul blocului logic curent cu valoarea anterior salvata. Daca sunt egale, nucleul calculeaza numarul blocului fizic pentru citirea in avans si salveaza valoarea sa in u area pentru a fi utilizata de algoritmul breada. Daca procesul nu va citi sfarsitul unui bloc, nucleul nu va apela citirea in avans pentru urmatorul bloc.

Daca se incearca citirea unor blocuri pentru care numerele de bloc din inod sau din blocurile de indirectare au valoarea 0, nucleul satisface cererea alocand un buffer arbitrar cu continut 0, pe care il copiaza in spatiul utilizator.

Cand un proces invoca apelul sistem read, nucleul blocheaza inodul corespunzator pe durata apelului, evitand astfel posibilitatea returnarii unor date inconsistente. Spre exemplu, daca procesul A trebuie sa citeasca mai multe blocuri, iar dupa citirea unui parti se pune in asteptare, iar in timp ce asteapta, un alt proces B acceseaza inodul si modifica portiunea din fisier pe care urmeaza sa o citeasca procesul A, atunci ceea ce va citi A va fi o mixtura de date vechi si noi. Blocarea inodului la intrarea in apelul sistem si deblocarea sa la sfarsitul acestuia rezolva problemele de acest fel.

Consideram in continuare cazul unui proces care citeste un anumit fisier, iar citirea se face prin doua apeluri distincte. Daca in intervalul dintre cele doua citiri un alt proces va executa o scriere in fisierul considerat, atunci datele intoarse la cea de-a doua citire a primului proces vor fi o combinatie intre prima si cea de-a doua versiune a fisierului. Pentru a ilustra aceasta situatie se da exemplul din figura 5.8. Ordinea executiei apelurilor poate fi: read1, read2, write1, write2 sau read1, write1, read2, write2, etc. Pentru a evita aceasta situatie se foloseste facilitatea de blocare pe fisier si inregistrare (vezi paragraful 5.4) ceea ce permite unui proces sa garanteze consistenta fisierului cat timp acesta este deschis.

#include <fcntl.h>

/* process A */

main()

/* process B */

main();

;

fd = open('/etc/passwd', O_WRONLY);

write (fd, buf, sizeof(buf)); /* write 1 */

write (fd, buf, sizeof(buf)); /* write 2 */

}

Figura 5.8. Un proces care citeste si unul care scrie din/intr-un fisier

Exista posibilitatea ca un proces sa poata deschide un fisier de mai multe ori si sa-l citeasca folosind descriptori de fisier diferiti.

In figura 5.9. este prezentat cazul unui proces care deschide un fisier de doua ori. Citirea se face prin manipularea in mod independent a deplasamentului din tabela de fisiere asociata fiecarui descriptor, astfel ca la incheierea procesului, sirurile buf1 si buf2 ar trebui sa fie identice, presupunand ca nici un alt proces nu scrie in acest timp in fisierul "/etc/passwd".

#include <fcntl.h>

main()

Figura 5.9. Citirea dintr-un fisier folosind doi descriptori




Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 1112
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved