This shows you the differences between two versions of the page.
so:laboratoare:laborator-11 [2019/05/12 15:31] ioana_elena.ciornei |
so:laboratoare:laborator-11 [2022/05/19 16:54] (current) liza_elena.babu [Înainte de laborator: Feedback] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Laborator 11 - Operații IO avansate - Linux ====== | ====== Laborator 11 - Operații IO avansate - Linux ====== | ||
- | |||
- | ===== Materiale Ajutătoare ===== | ||
- | |||
- | * [[http://elf.cs.pub.ro/so/res/laboratoare/lab11-slides.pdf | lab11-slides.pdf]] | ||
- | * [[http://elf.cs.pub.ro/so/res/laboratoare/lab11-refcard.pdf | lab11-refcard.pdf]] | ||
Line 14: | Line 9: | ||
==== Linux ==== | ==== Linux ==== | ||
+ | * [[#linux_-_multiplexarea_io|Linux - multiplexarea I/O]] | ||
+ | * [[#select|select]] | ||
+ | * [[#poll|poll]] | ||
+ | * [[#epoll|epoll]] | ||
+ | * [[#linux_-_generalizarea_multiplexarii|Linux - generalizarea multiplexării]] | ||
+ | * [[#eventfd|eventfd]] | ||
+ | * [[#signalfd|signalfd]] | ||
+ | * [[#linux_-_operatii_asincrone|Linux - operații asincrone]] | ||
+ | * [[#zero-copy_io|Zero-copy I/O]] | ||
+ | * [[#vectored_io|Vectored I/O]] | ||
+ | |||
+ | <hidden> | ||
+ | ===== Înainte de laborator: Feedback ===== | ||
+ | |||
+ | Pentru a îmbunătăți cursul de SO, componentele sale și modul de desfășurare, ne sunt foarte utile opiniile voastre. Pentru aceasta, vă rugăm să accesați și completați formularul de feedback de pe site-ul acs.curs.pub.ro. Trebuie să fiți autentificați și înrolați în cadrul cursului. | ||
+ | |||
+ | Formularul este anonim și este activ în perioada 11 mai 2020 - 22 mai 2020. Rezultatele vor fi vizibile în cadrul echipei cursului doar după încheierea sesiunii. Este accesibil la link-ul “Formular feedback” a paginii principale a cursului de SO al seriei voastre pe acs.curs.pub.ro. Nu este în meta-cursul disponibil tuturor seriilor. | ||
+ | |||
+ | Vă invităm să evaluați activitatea echipei de SO și să precizați punctele tari și punctele slabe și sugestiile voastre de îmbunătățire a disciplinei. Feedback-ul vostru ne ajută să creștem calitatea materiei în anii următori și să îmbunătățim disciplinele pe care le veți face în continuare. | ||
+ | |||
+ | Vom publica la începutul semestrului viitor analiza feedback-ului vostru. | ||
+ | |||
+ | Ne interesează în special: | ||
+ | |||
+ | * Ce nu v-a plăcut și ce credeți că nu a mers bine? | ||
+ | * De ce nu v-a plăcut și de ce credeți că nu a mers bine? | ||
+ | * Ce ar trebuie să facem ca lucrurile să fie plăcute și să meargă bine? | ||
+ | </hidden> | ||
===== Linux - multiplexarea I/O ===== | ===== Linux - multiplexarea I/O ===== | ||
Line 60: | Line 83: | ||
Dezavantaje: | Dezavantaje: | ||
- | * lungimea setului de descriptori este definită cu ajutorul lui FD_SETSIZE, și implicit are valoarea 64; | + | * lungimea setului de descriptori este definită cu ajutorul lui ''FD_SETSIZE'', și implicit are valoarea 1024; |
* este necesar ca seturile de descriptori să fie reconstruite la fiecare apel ''select''; | * este necesar ca seturile de descriptori să fie reconstruite la fiecare apel ''select''; | ||
* la apariția unui eveniment pe unul dintre descriptori, toți descriptorii puși în set înainte de ''select'' trebuie testați pentru a vedea pe care dintre ei a apărut evenimentul; | * la apariția unui eveniment pe unul dintre descriptori, toți descriptorii puși în set înainte de ''select'' trebuie testați pentru a vedea pe care dintre ei a apărut evenimentul; | ||
Line 314: | Line 337: | ||
Pentru a asigura în Linux posibilitatea așteptării de evenimente multiple s-a definit interfața ''eventfd''. Cu ajutorul acestei interfețe și combinat cu interfețele de multiplexare I/O existente, kernel-ul poate notifica o aplicație utilizator de orice tip de eveniment. | Pentru a asigura în Linux posibilitatea așteptării de evenimente multiple s-a definit interfața ''eventfd''. Cu ajutorul acestei interfețe și combinat cu interfețele de multiplexare I/O existente, kernel-ul poate notifica o aplicație utilizator de orice tip de eveniment. | ||
- | |||
- | Interfața ''eventfd'' este prezentă în nucleul Linux începând cu versiunea 2.6.22 și este suportată de către glibc începând cu versiunea 2.8. | ||
Interfața ''eventfd'' permite unificarea mecanismelor de notificare ale kernel-ului într-un descriptor de fișier care va fi folosit de utilizator. | Interfața ''eventfd'' permite unificarea mecanismelor de notificare ale kernel-ului într-un descriptor de fișier care va fi folosit de utilizator. | ||
Line 430: | Line 451: | ||
==== Linux AIO ==== | ==== Linux AIO ==== | ||
- | Standardul ''POSIX.1b'' definește un nou set de operații I/O care pot reduce semnificativ timpul pe care o aplicație îl petrece așteptând pentru I/O. Noile funcții permit unui program să inițieze una sau mai multe operații de I/O și să-și continue lucrul normal în timp ce operațiile de I/O sunt executate în paralel. | + | Începând cu versiunea 2.5.32, kernelul Linux expune un set de operații I/O care pot reduce semnificativ timpul pe care o aplicație îl petrece așteptând pentru I/O. Noile funcții permit unui program să inițieze una sau mai multe operații de I/O și să-și continue lucrul normal în timp ce operațiile de I/O sunt executate în paralel. |
Această funcționalitate este disponibilă dacă se instalează biblioteca ''libaio'': <code bash> | Această funcționalitate este disponibilă dacă se instalează biblioteca ''libaio'': <code bash> | ||
Line 776: | Line 797: | ||
} | } | ||
</code> | </code> | ||
- | ===== Exercițiul 0 - Joc interactiv (2p) ===== | ||
- | * Detalii desfășurare [[http://ocw.cs.pub.ro/courses/so/meta/notare#joc_interactiv|joc]]. | + | ===== Exerciții ===== |
- | + | ||
- | ===== Linux (9p) ===== | + | |
- | + | ||
- | În rezolvarea laboratorului folosiți arhiva de sarcini [[http://elf.cs.pub.ro/so/res/laboratoare/lab11-tasks.zip | lab11-tasks.zip]] | + | |
<note important> | <note important> | ||
- | Acest laborator se desfășoară în echipe. O echipă este formată din 2 studenți. În cazul în care numărul de studenți prezenți este impar, o singură echipă va avea dreptul de a avea 3 studenți. | + | În cadrul laboratoarelor vom folosi repository-ul de git al materiei SO - https://github.com/systems-cs-pub-ro/so. Va trebui sa clonați repository-ul pe masinile virtuale folosind comanda: ''git clone https://github.com/systems-cs-pub-ro/so''. Dacă doriți să descărcați repositoryul în altă locație, folosiți comanda ''git clone https://github.com/systems-cs-pub-ro/so ${target}''. |
- | Discutați exercițiile și colaborați pe parcursul întregului laborator. Have fun! :-) | + | Pentru a actualiza repository-ul, folosiți comanda ''git pull origin master'' din interiorul directorului în care se află repository-ul. Recomandarea este să îl actualizați cât mai frecvent, înainte să începeți lucrul, pentru a vă asigura că aveți versiunea cea mai recentă. În cazul în care gitul detectează conflicte la nivelul vreunui fişier, folosiți următoarele comenzi pentru a vă păstra modificările: |
+ | <code> | ||
+ | git stash | ||
+ | git pull origin master | ||
+ | git stash pop | ||
+ | </code> | ||
+ | |||
+ | Pentru mai multe informații despre folosirea utilitarului git, urmați ghidul de la https://gitimmersion.com. | ||
</note> | </note> | ||
- | ==== Exercițiul 1 - poll (1p) ==== | + | ==== Linux ==== |
+ | |||
+ | === Exercițiul 1 - poll === | ||
Intrați în directorul ''1-pollpipe''. Parcurgeți fișierul ''poll.c'' pentru a vedea un exemplu de folosire al funcției ''poll''. | Intrați în directorul ''1-pollpipe''. Parcurgeți fișierul ''poll.c'' pentru a vedea un exemplu de folosire al funcției ''poll''. | ||
Line 809: | Line 834: | ||
- | ==== Exercițiul 2 - epoll (2p) ==== | + | === Exercițiul 2 - epoll === |
Intrați în directorul ''2-epollpipe'' și parcurgeți fișierul ''epoll.c''. Considerând cerința de la exercițiul anterior, în loc de ''poll'' folosiți ''epoll''. | Intrați în directorul ''2-epollpipe'' și parcurgeți fișierul ''epoll.c''. Considerând cerința de la exercițiul anterior, în loc de ''poll'' folosiți ''epoll''. | ||
Line 826: | Line 851: | ||
* Eliminați pipe-ul din multiplexor (folosind ''epoll_ctl'' cu opțiunea ''EPOLL_CTL_DEL'') și închideți-l folosind ''close''. | * Eliminați pipe-ul din multiplexor (folosind ''epoll_ctl'' cu opțiunea ''EPOLL_CTL_DEL'') și închideți-l folosind ''close''. | ||
* Incremenetați valoarea variabilei ''recv_msgs''. | * Incremenetați valoarea variabilei ''recv_msgs''. | ||
- | ==== Exercițiul 3 - eventfd (2p) ==== | + | |
+ | === Exercițiul 3 - eventfd === | ||
Pornind de la codul scris pentru execițiul anterior, notificați serverul de terminarea unui client utilizând ''eventfd''. Clientul transmite mesaje către server și, când dorește să închidă comunicația, va trimite un mesaj pe canalul de control reprezentat de ''eventfd''. Acum, ''epoll'' este folosit pentru a demultiplexa atât descriptorii de pipe, cât și descriptorul de ''eventfd''. | Pornind de la codul scris pentru execițiul anterior, notificați serverul de terminarea unui client utilizând ''eventfd''. Clientul transmite mesaje către server și, când dorește să închidă comunicația, va trimite un mesaj pe canalul de control reprezentat de ''eventfd''. Acum, ''epoll'' este folosit pentru a demultiplexa atât descriptorii de pipe, cât și descriptorul de ''eventfd''. | ||
Line 839: | Line 865: | ||
Dacă descriptorul întors în urma ''epoll_wait'' este descriptorul de ''eventfd'', atunci veți citi ''64'' de biți de pe acest descriptor (folosind ''read''). Dacă primii 32 biți sunt valoarea descrisă de macro-ul ''MAGIC_EXIT'', atunci **scoate** capătul pipe-ului corespunzător din ''epoll'' și închide acel capăt (adică folosește ''epoll_ctl'' cu opțiunea ''EPOLL_CTL_DEL'' și apoi ''close''). Pentru a extrage ultimii 32 de biți din mesajul de ''64'' de biți primit pe descriptorul de ''eventfd'', reprezentând indexul clientului, folosiți funcția ''get_index'' definită local în program. | Dacă descriptorul întors în urma ''epoll_wait'' este descriptorul de ''eventfd'', atunci veți citi ''64'' de biți de pe acest descriptor (folosind ''read''). Dacă primii 32 biți sunt valoarea descrisă de macro-ul ''MAGIC_EXIT'', atunci **scoate** capătul pipe-ului corespunzător din ''epoll'' și închide acel capăt (adică folosește ''epoll_ctl'' cu opțiunea ''EPOLL_CTL_DEL'' și apoi ''close''). Pentru a extrage ultimii 32 de biți din mesajul de ''64'' de biți primit pe descriptorul de ''eventfd'', reprezentând indexul clientului, folosiți funcția ''get_index'' definită local în program. | ||
| | ||
- | ==== Exercițiul 4 - async I/O (KAIO) (2p) ==== | + | === Exercițiul 4 - async I/O (KAIO) === |
Intrați în directorul ''4-kaio'' și parcurgeți fișierul ''kaio.c''. Completați zonele lipsă pentru a programa scrierea a 4 fișiere cu numele date de variabila ''files''. | Intrați în directorul ''4-kaio'' și parcurgeți fișierul ''kaio.c''. Completați zonele lipsă pentru a programa scrierea a 4 fișiere cu numele date de variabila ''files''. | ||
Line 847: | Line 873: | ||
Parcurgeți secțiunea [[#linux_aio|Linux AIO]] și consultați exemplul lui [[http://www.xmailserver.org/eventfd-aio-test.c | Davide Libenzi]]. Urmăriți comentariile cu // TODO 1 // | Parcurgeți secțiunea [[#linux_aio|Linux AIO]] și consultați exemplul lui [[http://www.xmailserver.org/eventfd-aio-test.c | Davide Libenzi]]. Urmăriți comentariile cu // TODO 1 // | ||
- | Compilați și rulați programul. Va trebui să aveți 4 fișiere de dimensiune 8192 octeți create în ''/tmp''. | + | Compilați și rulați programul. Va trebui să aveți 4 fișiere de dimensiune ''BUFSIZ'' octeți create în ''/tmp''. |
**Atenţie!** În cazul în care, la compilare, header-ul 'libaio' nu este găsit rulaţi <code bash> | **Atenţie!** În cazul în care, la compilare, header-ul 'libaio' nu este găsit rulaţi <code bash> | ||
Line 854: | Line 880: | ||
- | ==== Exercițiul 5 - async I/O (KAIO) (2p) ==== | + | === Exercițiul 5 - async I/O (KAIO) === |
Folosiți ''eventfd'' pentru așteptarea operațiilor asincrone. Porniți de la codul scris pentru execițiul anterior. | Folosiți ''eventfd'' pentru așteptarea operațiilor asincrone. Porniți de la codul scris pentru execițiul anterior. | ||
Line 863: | Line 889: | ||
Parcurgeți secțiunea [[#linux_aio|Linux AIO]] și urmăriți comentariile cu // TODO 2 //. Consultați exemplul lui [[http://www.xmailserver.org/eventfd-aio-test.c | Davide Libenzi]]. | Parcurgeți secțiunea [[#linux_aio|Linux AIO]] și urmăriți comentariile cu // TODO 2 //. Consultați exemplul lui [[http://www.xmailserver.org/eventfd-aio-test.c | Davide Libenzi]]. | ||
- | Compilați și rulați programul. Va trebui să aveți 4 fișiere de dimensiune 8192 octeți create în ''/tmp''. | + | Compilați și rulați programul. Va trebui să aveți 4 fișiere de dimensiune 8192 octeți create în ''/tmp''. |
- | ===== BONUS ===== | + | |
+ | ==== BONUS ==== | ||
- | - **(1 so karma)** ''signalfd'' | + | - ''signalfd'' |
* Modificați codul de la exercițiul 2 pentru a permite notificarea de terminare a clienților bazată pe semnale. | * Modificați codul de la exercițiul 2 pentru a permite notificarea de terminare a clienților bazată pe semnale. | ||
* Server-ul: | * Server-ul: | ||
Line 874: | Line 901: | ||
* Consultați secțiunea [[#signalfd|signalfd]] | * Consultați secțiunea [[#signalfd|signalfd]] | ||
* [[ http://linux.die.net/man/2/signalfd | man signalfd ]] | * [[ http://linux.die.net/man/2/signalfd | man signalfd ]] | ||
- | ===== Soluții ===== | ||
- | [[http://elf.cs.pub.ro/so/res/laboratoare/lab11-sol.zip | Soluţii laborator 11]] |