This shows you the differences between two versions of the page.
so:cursuri:curs-02 [2014/02/21 13:04] razvan.deaconescu [Buffered I/O vs. System-Level I/O] |
so:cursuri:curs-02 [2019/04/14 09:08] (current) dragos_florin.costea [Curs 02 - Interfața sistemului de fișiere] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Curs 02 - Sistemul de fișiere ====== | + | ====== Curs 02 - Interfața sistemului de fișiere ====== |
- | <html> | + | * [[http://prezi.com/5-5ua6acyxv9/so-curs-2/?kw=view-5-5ua6acyxv9&rc=ref-31844697 | Curs 02 - Interfața sistemului de fișiere (vizualizare Prezi)]] |
- | <iframe src="http://prezi.com/embed/5-5ua6acyxv9/?bgcolor=ffffff&lock_to_path=0&autoplay=no&autohide_ctrls=0&features=undefined&disabled_features=undefined" width="550" height="400" frameBorder="0"></iframe> | + | * [[http://elf.cs.pub.ro/so/res/cursuri/SO_Curs-02.pdf | Curs 02 - Interfața sistemului de fișiere (PDF)]] |
- | </html> | + | |
- | * [[http://prezi.com/5-5ua6acyxv9/so-curs-2/?kw=view-5-5ua6acyxv9&rc=ref-31844697 | Curs 02 - Sistemul de fișiere (vizualizare Prezi)]] | + | * [[https://docs.google.com/document/d/1kH3Sg8OcW8oMUqsuG1jaicUxUze05vN_2wHaJix3W28/edit?usp=sharing|Notițe de curs]] |
- | * [[http://elf.cs.pub.ro/so/res/cursuri/SO_Curs-02.pdf | Curs 02 - Sistemul de fișiere (PDF)]] | + | |
* Suport curs | * Suport curs | ||
Line 12: | Line 10: | ||
* Capitolul 9 - File-System Interface | * Capitolul 9 - File-System Interface | ||
* Capitolul 10, Secțiunea 10.1 - File-System Structure | * Capitolul 10, Secțiunea 10.1 - File-System Structure | ||
- | * Modern Operating Systems | ||
- | * Capitolul 6 - File System Implementation (secțiunile 1 și 2) | ||
* Linux System Programming | * Linux System Programming | ||
* Capitolul 2 (programatic) | * Capitolul 2 (programatic) | ||
Line 19: | Line 15: | ||
* Capitolul 2 (programatic) | * Capitolul 2 (programatic) | ||
+ | <html> | ||
+ | <center> | ||
+ | <iframe src="https://prezi.com/embed/5-5ua6acyxv9/?bgcolor=ffffff&lock_to_path=0&autoplay=no&autohide_ctrls=0&features=undefined&disabled_features=undefined" width="550" height="400" frameBorder="0"></iframe> | ||
+ | </center> | ||
+ | </html> | ||
===== Demo-uri ===== | ===== Demo-uri ===== | ||
Pentru parcurgerea demo-urilor, folosim [[http://elf.cs.pub.ro/so/res/cursuri/curs-02-demo.zip|arhiva aferentă]]. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda<code bash> | Pentru parcurgerea demo-urilor, folosim [[http://elf.cs.pub.ro/so/res/cursuri/curs-02-demo.zip|arhiva aferentă]]. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda<code bash> | ||
- | user@host:~$ wget http://elf.cs.pub.ro/so/res/cursuri/curs-02-demo.zip | + | wget http://elf.cs.pub.ro/so/res/cursuri/curs-02-demo.zip |
</code> și apoi decomprimăm arhiva<code bash> | </code> și apoi decomprimăm arhiva<code bash> | ||
- | user@host:~$ unzip curs-02-demo.zip | + | unzip curs-02-demo.zip |
</code> și accesăm directorul rezultat în urma decomprimării<code bash> | </code> și accesăm directorul rezultat în urma decomprimării<code bash> | ||
- | user@host:~$ cd curs-02-demo/ | + | cd curs-02-demo/ |
</code> | </code> | ||
Line 35: | Line 36: | ||
Pentru a afișa tabela de descriptor de fișier a procesului shell current (PID-ul său este reținut în construcția ''$$''), folosim comanda<code bash> | Pentru a afișa tabela de descriptor de fișier a procesului shell current (PID-ul său este reținut în construcția ''$$''), folosim comanda<code bash> | ||
- | user@host:~$ lsof -a -d 0-1023 -p $$ | + | lsof -a -d 0-1023 -p $$ |
</code> | </code> | ||
Line 50: | Line 51: | ||
</spoiler> | </spoiler> | ||
+ | <note> | ||
+ | Pe anumite sisteme descriptorul este marcat cu ''0u'' adică este read-write; dar, în mod practic, este folosit doar pentru citire. | ||
+ | </note> | ||
==== Descriptori de fișier pentru procesele daemon ==== | ==== Descriptori de fișier pentru procesele daemon ==== | ||
Vrem să investigăm descriptorii de fișiere pentru procesele daemon din sistem. Pentru început vrem să aflăm procesele daemon din sistem; procesele daemon au ca proces părinte procesul ''init'' (procesul cu PID-ul ''1'') și vom folosi comanda de mai jos pentru a le afla:<code bash> | Vrem să investigăm descriptorii de fișiere pentru procesele daemon din sistem. Pentru început vrem să aflăm procesele daemon din sistem; procesele daemon au ca proces părinte procesul ''init'' (procesul cu PID-ul ''1'') și vom folosi comanda de mai jos pentru a le afla:<code bash> | ||
- | user@host:~$ ps --ppid 1 | + | ps --ppid 1 |
</code> | </code> | ||
- | Pentru unul dintre procesele daemon descoperite prin rularea comenzii anterioare , afișam tabela de descriptori (e nevoie de drept de ''root'') folosind comanda ''lsof'':<code bash> | + | Pentru unul dintre procesele daemon descoperite prin rularea comenzii anterioare, afișăm tabela de descriptori (e nevoie de drept de ''root'') folosind comanda ''lsof'':<code bash> |
- | root@host:~# sudo lsof -a -d 0-1023 -p $PID | + | sudo lsof -a -d 0-1023 -p $PID |
</code> | </code> | ||
Line 78: | Line 82: | ||
==== Descriptorii de fișier după redirectare ==== | ==== Descriptorii de fișier după redirectare ==== | ||
- | Vrem să vedem cum se modifică descriptorii de fișier în cazul redicterării. Pentru a putea vedea acest lucru vom rula o comandă de durată (''sleep'') și vom redirecta intrarea și ieșirea standard:<code bash> | + | Vrem să vedem cum se modifică descriptorii de fișier în cazul redirectării. Pentru a putea vedea acest lucru vom rula o comandă de durată (''sleep'') și vom redirecta intrarea și ieșirea standard:<code bash> |
- | user@host:~$ sleep 100 < /etc/passwd > f.txt | + | sleep 100 < /etc/passwd > f.txt |
</code> | </code> | ||
- | Pentru a investiga procesul ''sleep'' proaspăt porni, trebuie să știm PID-ul său. Deschidem o altă consolă și aflăm PID-ul procesului ''sleep'' creat folosind comanda:<code bash> | + | Pentru a investiga procesul ''sleep'' proaspăt pornit, trebuie să știm PID-ul său. Deschidem o altă consolă și aflăm PID-ul procesului ''sleep'' creat folosind comanda:<code bash> |
- | user@host:~$ pidof sleep | + | pidof sleep |
</code> | </code> | ||
- | Vom folosi onstrucția ''$PID'' referă PID-ul procesului ''sleep'' pe care-l investigăm. Ca și până acum, afișam tabela de descriptori de fișier a procesului folosind comanda:<code bash> | + | Vom folosi construcția ''$PID'' referă PID-ul procesului ''sleep'' pe care-l investigăm. Ca și până acum, afișam tabela de descriptori de fișier a procesului folosind comanda:<code bash> |
- | user@host:~$ lsof -a -o -d 0-1023 -p $PID | + | lsof -a -o -d 0-1023 -p $PID |
</code> | </code> | ||
Line 103: | Line 107: | ||
user@host:~$ make | user@host:~$ make | ||
</code> și obținem executabilul ''c-file-ops''. Rulăm executabilul ''c-file-ops'':<code bash> | </code> și obținem executabilul ''c-file-ops''. Rulăm executabilul ''c-file-ops'':<code bash> | ||
- | user@host:~$ ./c-file-ops | + | ./c-file-ops |
</code> | </code> | ||
Pentru a urmări evoluția tabelei de descriptori și a cursorului de fișier, vom folosi comanda ''lsof''. Într-o altă consolă rulăm comanda<code bash> | Pentru a urmări evoluția tabelei de descriptori și a cursorului de fișier, vom folosi comanda ''lsof''. Într-o altă consolă rulăm comanda<code bash> | ||
- | user@host:~$ lsof -a -o -d 0-1023 -p $(pidof c-file-ops) | + | lsof -a -o -d 0-1023 -p $(pidof c-file-ops) |
</code> Pentru început sunt afișați doar descriptorii standard. | </code> Pentru început sunt afișați doar descriptorii standard. | ||
Line 121: | Line 125: | ||
La finalul rulării programului urmărim dimensiunea fișierului ''f.txt'':<code bash> | La finalul rulării programului urmărim dimensiunea fișierului ''f.txt'':<code bash> | ||
- | user@host:~$ stat -c "%s" f.txt | + | stat -c "%s" f.txt |
256 | 256 | ||
</code> Observăm că fișierul are dimensiunea de 256 octeți, atât cât a primit ca argument apelul ''ftruncate''. | </code> Observăm că fișierul are dimensiunea de 256 octeți, atât cât a primit ca argument apelul ''ftruncate''. | ||
Line 128: | Line 132: | ||
<spoiler Răspuns> | <spoiler Răspuns> | ||
- | Apelul ''ftruncate'' modifică modifică dimensiunea fișierului. Un fișier are un câmp de dimensiune alterat de comanda ''ftruncate''. Acest câmp este diferit de cursorul de fișier. Teoretic cursorul de fișier poate fi plasat dincolo de sfârșitul fișierului. Din acest motiv, apelul ''ftruncate'' nu are nici un efect asupra cursorului de fișier. | + | Apelul ''ftruncate'' modifică dimensiunea fișierului. Un fișier are un câmp de dimensiune alterat de comanda ''ftruncate''. Acest câmp este diferit de cursorul de fișier. Teoretic cursorul de fișier poate fi plasat dincolo de sfârșitul fișierului. Din acest motiv, apelul ''ftruncate'' nu are nici un efect asupra cursorului de fișier. |
Acest lucru este precizat și în [[http://man7.org/linux/man-pages/man2/ftruncate.2.html#DESCRIPTION|secțiunea DESCRIPTION a paginii de manual a apelului ftrunctate]]. | Acest lucru este precizat și în [[http://man7.org/linux/man-pages/man2/ftruncate.2.html#DESCRIPTION|secțiunea DESCRIPTION a paginii de manual a apelului ftrunctate]]. | ||
Line 180: | Line 184: | ||
</code> | </code> | ||
- Rapid, într-o altă consolă, urmărim **apelurile de bibliotecă** realizate de programul ''buffered'' folosind comanda:<code bash> | - Rapid, într-o altă consolă, urmărim **apelurile de bibliotecă** realizate de programul ''buffered'' folosind comanda:<code bash> | ||
- | ltrace -e putchar+fputc -p $(pidof buffered) | + | ltrace -e putchar,fputc -p $(pidof buffered) |
</code> | </code> | ||
Line 187: | Line 191: | ||
./buffered | ./buffered | ||
</code> | </code> | ||
- | - Rapid, într-o altă consolă, urmărim **apelurile de bibliotecă** realizate de programul ''buffered'' folosind comanda:<code bash> | + | - Rapid, într-o altă consolă, urmărim **apelurile de sistem** realizate de programul ''buffered'' folosind comanda:<code bash> |
strace -e write -p $(pidof buffered) | strace -e write -p $(pidof buffered) | ||
</code> | </code> | ||
- | Care este numărul de apeluri de bibliotecă și numărul de apeluri de sistem realizate de programul ''buffered''? | + | Care este numărul de apeluri de bibliotecă și numărul de apeluri de sistem realizate de programul ''buffered'' în cadrul buclelor ''for''? |
<spoiler Răspuns> | <spoiler Răspuns> | ||
Line 201: | Line 205: | ||
</code> | </code> | ||
- | Care este numărul de apeluri de bibliotecă și numărul de apeluri de sistem realizate de programul ''buffered''? | + | Care este numărul de apeluri de bibliotecă și numărul de apeluri de sistem realizate de programul ''system''? |
<spoiler Răspuns> | <spoiler Răspuns> | ||
Line 210: | Line 214: | ||
==== Apelul dup și cursorul de fișier ==== | ==== Apelul dup și cursorul de fișier ==== | ||
- | - Intrați în directorul ''open-dup/'' din arhiva cu demo-uri a cursului. | + | Ne propunem să urmărim efectul apelului ''dup()'' asupra cursorului de fișier. Pentru aceasta accesăm subdirectorul ''open-dup/'' din directorul cu demo-uri a cursului și parcurgem fișierele ''open.c'' și ''dup.c''. În ambele fișiere se deschid doi descriptori de fișier (''fd1'' și ''fd2''): în cazul fișierului ''open.c'' descriptorul ''fd2'' este creat folosind apelul ''open()'', iar în cazul fișierului ''dup.c'' descriptorul ''fd2'' este creat folosind apelul ''dup()''. |
- | * Parcurgeți fișierele ''open.c'' și ''dup.c''. | + | |
- | * Compilați programele folosind comanda<code bash> | + | Compilăm programele folosind comanda<code bash> |
make | make | ||
- | </code> | + | </code> și obținem executabilele ''open'' și ''dup''. |
- | * Veți obține executabilele ''open'' și ''dup''. | + | |
- | * Rulați executabilul ''open'':<code bash> | + | Rulăm executabilul ''open'':<code bash> |
./open | ./open | ||
</code> | </code> | ||
- | * Într-o altă consolă, pentru a urmări evoluția tabelei de descriptori și a cursorului de fișier, rulați comanda:<code bash> | + | |
+ | Pentru a urmări tabela de descriptori de fișier și cursorul de fișier pentru procesul creat, deschidem o altă consolă și rulăm comanda:<code bash> | ||
watch -d lsof -a -o -d 0-1023 -p $(pidof open) | watch -d lsof -a -o -d 0-1023 -p $(pidof open) | ||
</code> | </code> | ||
- | * Folosiți ENTER în consola în care ați rulat executabilul ''open'' și urmăriți evoluția programului în consola în care ați rulat ''lsof''. | + | |
- | * Coloana ''OFFSET'' indică //file pointer//-ul (cursorul de fișier, //file offset//). | + | În consola în care am rulat executabilul ''open'' folosim comanda ''ENTER'' pentru a parcurge pașii din program. Urmărim în a doua consolă evoluția tabelei de descriptori și a cursorului de fișier. |
- | * **Urmați aceeași pași pentru executabilul ''dup''**. | + | |
- | * Ce diferențe apar? | + | <note tip> |
+ | Coloana ''OFFSET'' indică poziția cursorului de fișier. | ||
+ | </note> | ||
+ | |||
+ | Realizați aceeași pași pentru executabilul ''dup''. | ||
+ | |||
+ | Ce diferențe apar la nivelul tabelei de descriptori de fișier și cursor de fișier între programul ''open'' și programul ''dup''? | ||
+ | |||
+ | <spoiler Răspuns> | ||
+ | Ambele apeluri creează o intrare nouă în tabela de descriptori de fișier. În cazul apelului ''dup'' intrarea nou creată este o clonă a celei vechi. Alterarea cursorului de fișier pentru descriptorul ''fd1'' este vizibilă pentru descriptorul ''fd2''. Cei doi descriptori referă aceeași structură, care conține același cursor de fișier. În cazul apelului ''open'' intrările sunt distincte, chiar dacă în final referă același fișier. Modificarea cursorului de fișier pentru descriptorul ''fd1'' nu afectează cursorul de fișier pentru descriptorul ''fd2''. | ||
+ | </spoiler> | ||
===== Link-uri recomandate ===== | ===== Link-uri recomandate ===== | ||
[[http://www.ibm.com/developerworks/aix/library/au-lsof.html|Finding open files with lsof]] | [[http://www.ibm.com/developerworks/aix/library/au-lsof.html|Finding open files with lsof]] | ||
- |