Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:cursuri:curs-10 [2014/04/14 18:11]
razvan.deaconescu removed
so:cursuri:curs-10 [2019/04/20 20:24] (current)
razvan.deaconescu
Line 1: Line 1:
-====== Curs 10 - Implementarea sistemelor ​de fișiere ======+====== Curs 10 - Dispozitive ​de intrare/ieșire ======
  
-<​html>​ +  * [[http://​prezi.com/​z_hkmewcaqm_/?utm_campaign=share&utm_medium=copy&rc=ex0share|Curs 10 -  Dispozitive de Intrare/Iesire (Prezi)]] 
-<iframe src="http://​prezi.com/​embed/​i7gfiypqqpje/?bgcolor=ffffff&amp;​lock_to_path=0&amp;​autoplay=0&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"><​/iframe> +  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-10.pdf|Curs 10 - Dispozitive de Intrare/Iesire (PDF)]]
-</html>+
  
-  * [[http://prezi.com/i7gfiypqqpje/curs-10-so/?kw=view-i7gfiypqqpje&​rc=ref-31844697 ​Curs 10 - Implementarea sistemelor ​de fișiere (Vizualizare Prezi)]] +  * [[https://docs.google.com/document/d/1dc5Kaamjo6WPy7LABkBGTcxjVwgl3JbnlHnE0iREmwM/​edit?usp=sharing|Notițe ​de curs]]
-  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-10.pdf | Curs 10 - Implementarea sistemelor de fișiere (PDF)]]+
  
   * Suport curs   * Suport curs
-    * Operating ​System ​Concepts +    * Operating ​Systems ​Concepts ​Essentials 
-      * Capitolul 11 – File-System Implementation +      * Capitolul 11 -- Mass Storage Structure 
-        * Secțiunile 11.1 – 11.8+        * Secțiunile 11.2, 11.4, 11.7 
 +      * Capitolul 12 -- I/O Systems
     * Modern Operating Systems     * Modern Operating Systems
-      * Capitolul ​6 – File Systems +      * Capitolul ​5 -- Input/​Output 
-        * Secțiunile ​6.3, 6.4+        * Secțiunile ​5.1, 5.2, 5.3 
 +        * Subsecțiunile 5.4.15.4.3 
 + 
 +<​html>​ 
 +  <​center>​ 
 +    <iframe src="​https://​prezi.com/​embed/​z_hkmewcaqm_/?​bgcolor=ffffff&​amp;​lock_to_path=0&​amp;​autoplay=0&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"></​iframe>​ 
 +  </​center>​ 
 +</​html>​ 
 ===== Demo-uri ===== ===== Demo-uri =====
  
-Pentru parcurgerea demo-urilor, ​folosiți ​[[http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-10.zip|arhiva aferentă]].+Pentru parcurgerea demo-urilor, ​folosim ​[[http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-10-demo.zip|arhiva aferentă]]. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda<​code bash> 
 +wget http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-10-demo.zip 
 +</​code>​ și apoi decomprimăm arhiva<​code bash> 
 +unzip curs-10-demo.zip 
 +</​code>​ și accesăm directorul rezultat în urma decomprimării<​code bash> 
 +cd curs-10-demo/​ 
 +</​code>​ 
 + 
 +Acum putem parcurge secțiunile cu demo-uri de mai jos. 
 + 
 +==== Investigare întreruperi ==== 
 + 
 +Dorim să investigăm livrarea întreruperilor hardware către sistemul local. Vom urmări întreruperea de ceas (timer) și întreruperea de tastatură.
  
-  - Folosiți comanda ​''​stat'' ​pentru a afișinformații despre ​inode-ul corespunzător unui fișier, director, link simbolic, char device, block device:<​code ​bash+În Linux fișierul care afișează informații despre tastatură este ''​/​proc/​interrupts''​. În acest fișier sunt afișate informații ​statistice ​despre ​întreruperilor livrate, câte o coloană pentru fiecare procesor. În cadrul ​fișierului găsim informații și despre întreruperea de ceas și cea de tastatură:<​code>​ 
-stat /etc/passwd +$ cat /proc/interrupts ​ 
-stat /usr/lib/ +           CPU0       ​CPU1 ​      ​CPU2 ​      ​CPU3 ​       
-stat /usr/bin/cc +  ​0: ​        ​14 ​         0          0          0  IR-IO-APIC-edge ​     timer 
-stat /dev/null +  ​1: ​   1358967 ​         0          0          0  IR-IO-APIC-edge ​     i8042 
-stat /dev/loop0+[...] 
 +LOC:   ​96023026 ​  ​47877718 ​  ​90900926 ​  ​54219891 ​  Local timer interrupts 
 +[...]
 </​code>​ </​code>​
-    * Afișați informații despre un socket Unix, după ce îl utați în ierarhia ​''/​var/run/''​:<​code ​bash+ 
-sudo find /var/run -type s +Prima coloană este linia de întrerupere (''​IRQ line''​) pe care se livrează semnalul de întrerupere ​tre procesor. Este 0 în cazul [[http://​en.wikipedia.org/​wiki/​Intel_8253|timer-ului programabil (8253)]] șîn cazul [[http://​en.wikipedia.org/​wiki/​Keyboard_controller_(computing)|controller-ului de tastatură (8042)]]. 
-sudo stat /​var/​run/​udev/control+ 
 +Din output-ul comenzii de mai sus am selectat doar intrările referitoare la întreruperea de ceas (''​timer''​ și //Local timer interrupts//) și cea de tastatură (''​i8042''​). La noi rulări ale comenzii<​code>​ 
 +cat /proc interrupts
 </​code>​ </​code>​
-    * Aflați dimensiunea fișierului ​''/​sbin/init'' ​folosind ​''​stat'':<​code ​bash+vom observa actualizări ale valorilor întreruperilor. În figura de mai sus întreruperea de tastatură (''​i8042''​) este tratată doar pe primul procesor (''​CPU0''​) în vreme ce există întreruperi de ceas locale pentru fiecare procesor (de unde și denumirea de //local//). 
-stat -c %s /sbin/init+ 
 +Pe sistemele multi-core/​multiprocesor se folosesc întreruperile de ceas locale (cele indicate de //Local timer interrupts//​). Acestea sunt livrate de controller-ul de întreruperi (APIC) către fiecare procesor în parte. Din acest motiv există actualizări pentru linia identificată de ''​LOC:'' ​dar nu și pentru timer-ul programabil de pe linia identificată cu ''​timer''​. Pe sisteme uniprocesor,​ pentru livrarea întreruperii de ceas se folosește timer-ul programabil.((What are Linux local timer interrupts? http://​stackoverflow.com/​questions/​10567214/​what-are-linux-local-timer-interrupts)) 
 + 
 +Informațiile despre întreruperea de ceas sunt actualizate periodic în fișierul ''/​proc/​interrupts''​ pentru că la un interval dat se livrează o nouă întrerupere. 
 + 
 +Întreruperile de tastatură sunt livrate la fiecare apăsare de tastă. Pentru a investiga evoluția numărului de întreruperi de tastatură livrate, tastăm șirul de comenzi de mai jos:<​code>​ 
 +$ cat /​proc/​interrupts | grep ' 1:' 
 +  1:    1366012 ​         0          0          0  IR-IO-APIC-edge ​     i8042 
 +$ echo '​aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'​ 
 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
 +$ cat /proc/interrupts | grep ' 1:' 
 +  1:    1366184 ​         0          0          0  IR-IO-APIC-edge ​     i8042
 </​code>​ </​code>​
-    ​Urmăriți modificările timpilor de acces pe fișier (//access time////modify time//,  ​//change time//) folosind comenzile ​de mai jos:<code bash> + 
-cd /tmp +<note important>​ 
-touch a.txt +Șirul de comenzi de mai sus trebuie tastat pentru a genera întreruperi. ​**Nu** dăm copy-paste la șir. 
-stat a.txt +</​note>​ 
-cat a.txt + 
-stat a.txt +Între prima afișare și a doua afișare a conținutului fișierul ''/​proc/​interrupts''​ am tastat circa 70-80 de taste pentru comanda ''​echo ...''​ șa doua comandă ''​cat''​ (am mai apăsat și pe tasta Backspace când am greșit). Observăm că diferența între cele două rezultate (întreruperi livrate) este ''​1336184 - 1336012 = 172''​. Au fost livrate circa dublu de întreruperi față de tastele apăsate. Acest lucru se întâmplă pentru că se livrează o întrerupere pentru fiecare apăsare de tastă ​(//key press//) și una pentru fiecare eliberare de tastă (//key release//); de unde și numărul dublu de întreruperi livrate față de taste apăsate. 
-chmod a+rw a.txt +==== Utilitate disk cache ==== 
-stat a.txt + 
-echo "​abc"​ > stat.txt +Dorim să urmărim efectul cache-ul de disk (numit și //page cache//). Acesta stochează datele frecvent accesate în memorie astfel că viitoare folosiri ale acestora să fie mai rapide. Vom copia de două ori un fișier și vom observa că a doua oară copierea este mai rapidă datorită cache-ului. 
-stat a.txt+ 
 +Creăm un fișier ''​in.dat''​ de 100MB de date aleatoare folosind comanda ''​dd''​:<code bash> 
 +$ dd if=/dev/urandom bs=1M count=100 of=in.dat 
 +100+0 records in 
 +100+0 records out 
 +104857600 bytes (105 MB) copied, 7.14143 s, 14.7 MB/s
 </​code>​ </​code>​
-      * //access time// este timpul de acces al fișierului,​ deschis pentru citire. + 
-      * //modify time// este timpul de modificare a datelor ​fișierului. +Apoi copiem ​fișierul ''​in.dat''​ în fișierul ''​out.dat''​ folosind comanda ''​cp'' ​și măsurând durata ​de execuție cu ajutorul comenzii ''​time''​:<code bash> 
-      * //change time// este timpul de modificare a metadatelor ​fișierului (informații din inode). +razvan@einherjar:​~$ ​/usr/​bin/​time -v cp in.dat out.dat 
-  - Creați un fișier simplu ​și urmăriți numărul ​de link-uri ale acestuia:<code bash> + Command being timed: "cp in.dat out.dat"​ 
-cd /tmp + User time (seconds): 0.00 
-touch first.txt + System time (seconds): 0.09 
-ls -i first.txt + Percent of CPU this job got: 100% 
-ls -l first.txt+ Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.09 
 +        [...] 
 +        Voluntary context switches: 1 
 + Involuntary context switches: 2 
 + Swaps: 0 
 + File system inputs: 0 
 + File system outputs: 204800 
 +        [...]
 </​code>​ </​code>​
-    * A doua coloana ​de la rularea ''​ls -l'' ​este numărul de link-uriinițial 1+Observăm ca a durat foarte puțin copierea, sub ''​10''​ milisecunde în rularea de mai sus. Aceasta s-a întâmplat pentru că fișierul ''​in.dat''​ a fost cache-uit în page cache de la rularea ​comenzii ​''​dd'', ​când a fost generat
-    * Creați un fișier ca hard link la primul:<code bash> + 
-ln first.txt second.txt+Ca să urmărim ce se întâmplă când fișierul nu se găsește în page cache, facem flush la page cache și apoi invalidăm intrările folosind comenzile de mai jos:<code bash> 
 +$ free -m 
 +             ​total ​      ​used ​      ​free ​    ​shared ​   buffers ​    ​cached 
 +Mem:          7893       ​4715 ​      ​3178 ​       251        728       ​1687 
 +-/+ buffers/​cache: ​      ​2299 ​      ​5593 
 +Swap:         ​3813 ​       427       ​3386 
 +$ sudo sync 
 +$ echo 1 | sudo tee /​proc/​sys/​vm/​drop_caches  
 +
 +$ free -m 
 +             ​total ​      ​used ​      ​free ​    ​shared ​   buffers ​    ​cached 
 +Mem:          7893       ​2653 ​      ​5240 ​       251          0        397 
 +-/+ buffers/​cache: ​      ​2255 ​      ​5637 
 +Swap:         ​3813 ​       427       3386
 </​code>​ </​code>​
-    * Observațcă inode-ul este același iar numărul de link-uri este egal cu doi:<code bash> + 
-ls -i first.txt second.txt +Am folosit comanda ''​free''​ doar pentru a raporta folosirea bufferelor șa cache-ului. După rularea comenzilor ''​sync'' ​și ''​echo ...''​ observăm eliberarea completă a bufferelor și aproape compleă a cache-ului.((Linux memory: buffer vs cache: http://​stackoverflow.com/​questions/​6345020/​linux-memory-buffer-vs-cache)) 
-ls -l first.txt second.txt+ 
 +Copiem din nou fișierul ''​in.dat''​ într-un nou fișier ''​out2.dat''​ și folosim comanda ''​time''​ pentru a măsura durata:<code bash> 
 +$ /​usr/​bin/​time ​-v cp in.dat out2.dat 
 + Command being timed: "cp in.dat out2.dat"​ 
 + User time (seconds): 0.00 
 + System time (seconds): 0.22 
 + Percent of CPU this job got: 11% 
 + Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.02 
 +        [...] 
 +        Voluntary context switches: 451 
 + Involuntary context switches: 11 
 + Swaps: 0 
 + File system inputs: 205632 
 + File system outputs: 204800 
 + [...]
 </​code>​ </​code>​
-    * Creați un al treilea link și observați numărul de link-uri egal cu 3:<code bash> +Observăm că acum operația durează semnificativ mai mult (2 secunde). De asemenea încărcarea pe procesor este mai mică (''​11%''​ față de ''​100%''​ pentru că acum procesorul așteaptă după disc. Observăm diferența mare de schimbări de context voluntare (procesul se blochează) și numărul ​diferit ​de zero de citiri din sistemul de fișiereacum întreg fișierul de intrare este citit de pe disc, nu mai este cache-uit în memorie
-ln second.txt third.txt + 
-ls -i first.txt second.txt third.txt +Cache-ul de disk este esențial pentru funcționarea eficientă a sistemului. În absența acestuia procesorul ar trebui să solicite informații de pe disc, dispozitiv foarte lent comparativ cu memoria șprocesorTrebuie avut grijă la flush-ul/​sincronizarea periodică a informațiilor din memorie pe disc pentru ca acestea să nu se piardă la o închidere bruscă a sistemului, memoria fiind volatilă. 
-ls -l first.txt second.txt third.txt+==== Copiere conținut CD/DVD în fișier ​.iso ==== 
 + 
 +Dorim să creăm facil un fișier format ​.iso conținând imaginea unui CD/DVDPentru aceasta comanda de creare este una foarte simplă ce folosește ''​dd'':<​code bash> 
 +$ dd if=/​dev/​cdrom of=file.iso bs=1M
 </​code>​ </​code>​
-    * Ștergeți primele două link-uri/nume și obsevați păstrarea inode-ului ​și reducerea numărului de link-uri la 1 pentru ultimul nume:<code bash> + 
-unlink first.txt +Comanda copiază octet cu octet conținutul CD-ului/DVD-ului, indicat de dispozitivul ''/​dev/​cdrom'' ​și îl scrie în fișierul ''​file.iso''​. Întrucât comanda ''​dd''​ acționează și pe dispozitive,​ va reieși un fișier în format ''​.iso'',​ copia sector cu sector a discului. 
-rm second.txt + 
-ls -i third.txt +Pentru a urmări evoluția comenzii, dintr-un alt terminal putem rula comanda:<code bash> 
-ls -l third.txt+$ kill -USR1 $(pidof dd)
 </​code>​ </​code>​
-      * ''​unlink''​ ș''​rm'' ​pot fi folosite interschimbabil+Livrarea semnalului ​''​USR1'' ​procesului ''​dd''​ înseamnă afișarea unui raport de stare din partea comenzii ​''​dd'' ​(adică în primul terminal)
-  - Urmăriți numărul de link-uri/nume aferente unui director golNumărul este 2: un link este numele efectiv al directorului,​ iar altul este referința '.' (punct, //dot//) către ​director însuși:<​code ​bash+ 
-cd /tmp +==== Folosire operație de control (ioctl) ==== 
-mkdir /tmp/test-d + 
-ls -ld /tmp/test-d+Dorim să urmărim câteva cazuri ​de folosire a funcției [[http://​man7.org/​linux/​man-pages/man2/ioctl.2.html|ioctl]]. Funcția ​este utilizată pentru operații de control ​unui dispozitiv sau de citire a unei stări sau a configurații,​ acolo unde funcțiile [[http://​man7.org/​linux/​man-pages/​man2/​read.2.html|read]] sau [[http://​man7.org/​linux/​man-pages/​man2/​write.2.html|write]] nu pot fi folosite. Apelurile ​''​ioctl''​ sunt folosite în special pe fișiere speciale ​(dispozitivesockeți, terminale etc.); dezavantajul este că nu există o formă standard a operațiilor aferente și în general nu sunt portabile. O listă **incompletă** de operații se găsește în [[http://man7.org/linux/man-pages/​man2/​ioctl_list.2.html|pagina de manual ioctl_list]]. 
 + 
 +Pentru a urmări folosirea apelului ''​ioctl''​ accesăm subdirectorul ''​ioctl/'';​ urmărim conținutul fișierelor ''​cdrom-ioctl.c''​ și ''​hwaddr-ioctl.c''​. Fișierele implementează,​ respectiv, operații pe CD-ROM drive și pe socket pentru aflarea adresei hardware (MAC)
 + 
 +Pentru fișierul sursă ''​cdrom-ioctl.c''​ înlocuim valoarea macro-ului ''​CDROM_DEV_PATH''​ cu șirul ce reprezintă calea către ​CD-ROM. La fel, în fișierul ''​hwaddr-ioctl.c''​ înlocuim valoarea macro-ului ''​IFNAME''​ cu șirul ce reprezintă numele interfeței a cărei adresă hardware dorim să o determinăm. 
 + 
 +Compilăm fișierele folosind ''​make''​. Rezultă două fișiere în format executabil: ''​cdrom-ioctl'' ​și ''​hwaddr-ioctl''​. 
 + 
 +Cu ajutorul executabilului ''​cdrom-ioctl''​ putem executa trei tipuri de operații pe CD-ROM așa cum este indicat prin rularea sa fără argumente:<​code>​ 
 +$ ./cdrom-ioctl ​ 
 +You must provide exactly one argument. 
 + 
 +Usage: ./cdrom-ioctl e|l|u 
 + eject CD-ROM 
 + l - lock CD-ROM drive 
 + e - unlock CD-ROM drive
 </​code>​ </​code>​
-    * Creați un subdirector al directorului ​''​/tmp/test-d/''​. Numărul de link-uri va crește la 3, cu ajutorul referinței ​'..' ​(punct punct//dot dot//) de la subdirector:<​code bash> + 
-mkdir /tmp/test-d/​test-subd +În continuare putem rula comanda ​''​cdrom-ioctl''​ cu exact unul dintre argumentele ''​e'', ​''​l'',​ ''​u''​ pentru a deschide trapa CD-ROM drive-ului saua bloca/debloca deschiderea manuală a acestuia (din buton). După cum vedem din codul sursă, aceste trei operații sunt realizate cu un apel ''​ioctl''​ și cu parametrii aferenți (documentați în [[http://lxr.free-electrons.com/source/Documentation/ioctl/cdrom.txt?​v=3.13|sursele nucleului Linux]]): ''​CDROMEJECT'' ​și ''​CDROM_LOCKDOOR''​. 
-ls -ld /tmp/​test-d + 
-</​code>​ +Cu ajutorul executabilului ​''​hwaddr-ioctl''​ putem determina adresa hardware (MAC) a unei interfețe de rețea așa cum se întâmplă mai jos:<​code>​ 
-    * Creațun subfișier al directorul ​''​/​tmp/​test-d/​''​. Numărul de link-uri nu se va modifica, întrucât fișierul nu are o referință la directorul părinte:<code bash> +$ ./hwaddr-ioctl  
-touch /tmp/test-d/test-f +Hardware address for interface eth0 is 00:​21:​cc:​68:​d0:​53
-ls -ld /tmp/test-d +
-</code> +
-  - Creați un director simplu ​și vedeți ce spațiu ocupă pe disc, folosind comanda ​''​stat'':<​code ​bash+
-cd /tmp +
-mkdir /tmp/fill-d +
-stat -c %s /tmp/fill-d+
 </​code>​ </​code>​
-    * Copiați scriptul ''​create-long-filenames''​ din arhivă și rulați-l în directorul proaspăt creat:<code bash> + 
-cd /tmp/fill-d +Adresa hardware a fost obținută într-o structură [[http://lxr.free-electrons.com/source/include/uapi/linux/if.h?v=3.13#​L170|struct ifreq]] cu ajutorul unui apel ''​ioctl'' ​aplicat ​pe un descriptor ​de socketParametrul ​''​ioctl'' ​a fost ''​SIOCGIFHWADDR''​.
-# TODO: copy script +
-./create-long-filenames +
-</​code>​ +
-    * Observați conținutul directorului și noua dimensiune a acestuia:<​code bash> +
-ls -l /​tmp/​fill-d +
-stat -c %s /​tmp/​fill-d +
-</​code>​ +
-      * Dimensiunea directorului a crescut datorită numărului de intrări în director. +
-      * Dimensiunea directorului este multiplu de dimensiunea blocului sistemului. +
-  - Citirea intrărilor dintr-un director; simularea comenzii ''​ls''​ +
-    * Intrați în directorul ''​5-dirent/''​. +
-    * Consultați fișierul ''​dirent.c''​. +
-    * Compilați fișierul folosind comanda ''​make''​. +
-    * Rulați executabilul obținut dându-i ca argument un director:<​code bash> +
-./dirent tmp +
-./dirent ​/usr +
-./dirent /var/run +
-./dirent /usr/lib +
-</​code>​ +
-      * Observați afișarea intrărilor și a tipului acestora. +
-      * Structura ​''​struct dirent'' ​reține informațiile legate de o intrare dintr-un director. +
-    * Un director este, pe disc, un inode ale cărui bloc-uri conține un vector ​de intrări asemănătoare cu ''​struct dirent''​. +
-      * Intrările sunt citite de pe disc folosind apelul ​''​readdir''​, similar folosirii apelului ''​read''​ pentru fișiere. +
-      * La fel ca fișierele obișnuite (//regular files//) și directoarele folosesc intern un cursor de fișier care este actualizat după fiecare apel ''​readdir''​.+
so/cursuri/curs-10.1397488277.txt.gz · Last modified: 2014/04/14 18:11 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0