Differences

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

Link to this comparison view

so2:laboratoare:lab07:exercitii [2017/04/03 17:45]
razvan.deaconescu [3. [2p] RAM disc]
so2:laboratoare:lab07:exercitii [2018/04/12 11:40] (current)
elena.sandulescu [6. [2p] Prelucrarea cererilor din coada la nivel de bio]
Line 1: Line 1:
 ====== Laborator 7: Exerciții ====== ====== Laborator 7: Exerciții ======
  
-Pentru desfășurarea laboratorului ​pornim ​de la [[http://​elf.cs.pub.ro/so2/res/laboratoare/lab07-tasks.zip|arhiva ​de sarcini a laboratorului]]. Descărcăși decomprimăm arhiva în directorul ''​so2/'' ​din directorul home al utilizatorului ''​student''​ de pe sistemul de bază (stația ''​eg106-pc''​):<code bash> +===== Pregătirea laboratorului ===== 
-student@eg106-pc:​~$ cd so2/ + 
-student@eg106-pc:​~/​so2$ wget http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab07-tasks.zip +Pentru rezolvarea laboratorului,​ vom lucra în același director din care pornim ​mașina virtuală (''​~/so2/linux/tools/labs''​). 
-student@eg106-pc:​~/​so2$ unzip lab07-tasks.zip + 
-student@eg106-pc:​~/​so2tree lab07-tasks+Pașii ​de rezolvare sunt următorii: 
 +  * pregătirea scheletului de laborator 
 +  * compilarea modulelor de Kernel 
 +  * copierea modulelor pe mașina virtuală 
 +  * pornirea mașinii virtuale ​și testarea modulelor 
 + 
 +==== Pregătirea scheletului de laborator ==== 
 + 
 +Scheletul de laborator este generat din sursele din directorul ''​tools/labs/​templates''​. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda: 
 + 
 +<code bash> 
 +tools/labs make skels
 </​code>​ </​code>​
-În cadrul directorului ''​lab07-tasks/''​ se găsesc resursele necesare pentru dezvoltarea exercițiilor de mai jos: fișiere schelet de cod sursă, fișiere Makefile și Kbuild, scripturi și programe de test. 
  
-Vom dezvolta exercițiile pe sistemul ​de bază (stația ​''​eg106-pc''​și apoi le vom testa pe [[:so2:​resurse:​masini-virtuale|mașina virtuală ​QEMU]]. După editarea și compilarea unui modul de kernel îl vom copia în directorul dedicat pentru ​mașina virtuală ​QEMU folosind ​o comandă de forma<code bash> +Pentru a genera scheletul pentru un singur laborator, vom folosi variabila ​de mediu ''​LABS''​
-student@eg106-pc:~/so2$ cp /path/to/module.ko ​~/so2/qemu-so2/fsimg/​root/​modules+ 
-</​code> ​unde ''​/​path/​to/​module.ko'' ​este calea către fișierul obiect aferent modulului de kernelApoi vom porni, din directorul ''​~/so2/qemu-so2/'', ​mașina virtuală ​QEMU folosind comanda<code bash> +<code bash> 
-student@eg106-pc:~/so2/qemu-so2$ make+tools/labs $ make clean 
 +tools/labs $ LABS=<​lab name> make skels 
 +</​code>​ 
 + 
 +<note important>​ 
 +Numele laboratorului curent este ''​block_device_drivers''​. 
 +</​note>​ 
 + 
 +Similar, putem genera ​și scheletul pentru un singur exercițiu, atribuind valoarea ''<​lab_name>/<​task_name>''​ variabilei ''​LABS''​. 
 + 
 +<​note>​ 
 +Scheletul este generat în directorul ''​tools/​labs/​skels''​. 
 +</​note>​ 
 + 
 +==== Compilarea modulelor ==== 
 + 
 +Comanda ''​make build''​ compilează toate modulele din directorul ''​skels''​. 
 + 
 +<code bash> 
 +student@eg106:~/so2/​linux/​tools/​labs$ make build 
 +echo "# autogenerated,​ do not edit " > skels/​Kbuild 
 +echo "​ccflags-y += -Wno-unused-function -Wno-unused-label -Wno-unused-variable " >> skels/​Kbuild 
 +for i in ./​block_device_drivers/​1-2-3-6-ram-disk/​kernel ./​block_device_drivers/​4-5-relay-disk;​ do echo "obj-m += $i/" >> skels/​Kbuild;​ done 
 +</​code>​ 
 + 
 +==== Copierea modulelor pe mașina virtuală ​==== 
 + 
 +Putem copia modulele generate pe mașina virtuală folosind ​target-ul ''​copy''​ al comenzii make, atunci când mașina virtuală este oprită. 
 + 
 +<code bash> 
 +student@eg106:​~/​so2/​linux/tools/labs$ make copy 
 +student@eg106:​~/so2/linux/tools/labs$ make boot 
 +</​code>​ 
 + 
 +Alternativ, putem copia fișierele prin ''​scp''​, pentru e evita repornirea mașinii virtualePentru detalii despre folosirea interacțiunea prin rețea cu mașina virtuală citiți [[https://ocw.cs.pub.ro/​courses/​so2/resurse/​masini-virtuale#​interactiunea_cu_masina_virtuala|Interacțiunea cu mașina virtuală]]. 
 + 
 +==== Testarea modulelor ==== 
 + 
 +Modulele generate sunt copiate pe mașina virtuală în directorul ''/​home/​root/​skels/<​lab_name>''​. 
 + 
 +<code bash> 
 +root@qemux86:​~/​skels/​block_device_drivers#​ ls 
 +1-2-3-6-ram-disk ​ 4-5-relay-disk 
 +root@qemux86:~/skels/block_device_drivers#​ ls 4-5-relay-disk/​ 
 +relay-disk.ko
 </​code>​ </​code>​
  
-După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU pentru a încărca și descărca modulul de kernel:<​code>​ +După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU (sau în ''​minicom''​) ​pentru a încărca și descărca modulul de kernel:<​code>​ 
-# insmod ​modules/module-name.ko +root@qemux86:​~# insmod ​skels/<​lab_name>/<​task_name>/<​module_name>​.ko  
-# rmmod module/module-name +root@qemux86:​~# rmmod skels/<​lab_name>/<​task_name>/<​module_name>​.ko ​ 
-</​code> ​unde ''​module-name''​ este numele modulului de kernel.+</​code> ​
  
 <​note>​ <​note>​
 Pentru dezvoltarea laboratorului,​ este recomandat să folosim trei terminale sau, mai bine, trei tab-uri de terminal. Pentru a deschide un nou tab de terminal folosim combinația de taste ''​Ctrl+Shift+t''​. Cele trei tab-uri de terminal îndeplinesc următoarele roluri: Pentru dezvoltarea laboratorului,​ este recomandat să folosim trei terminale sau, mai bine, trei tab-uri de terminal. Pentru a deschide un nou tab de terminal folosim combinația de taste ''​Ctrl+Shift+t''​. Cele trei tab-uri de terminal îndeplinesc următoarele roluri:
   - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului.   - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului.
-  - În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/​descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ''​~/​so2/​qemu-so2/''​. +  - În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/​descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ''​~/​so2/​linux/tools/labs''​. 
-  - În al treilea tab de terminal accesăm directorul ''​~/​so2/​linux-4.9.11/''​ cu sursele nucleului unde putem folosi [[:​so2:​laboratoare:​lab01#​cscope|Vim și cscope]] pentru parcurgerea codului sursă.+  - În al treilea tab de terminal accesăm directorul ''​~/​so2/​linux/''​ cu sursele nucleului unde putem folosi [[:​so2:​laboratoare:​lab01#​cscope|Vim și cscope]] pentru parcurgerea codului sursă.
 student@eg106-pc:​~$ netcat -lup 6666 student@eg106-pc:​~$ netcat -lup 6666
 </​code>​ </​code>​
Line 31: Line 85:
   - În primul tab să fie deschis [[:​so2:​laboratoare:​lab07|breviarul laboratorului]].   - În primul tab să fie deschis [[:​so2:​laboratoare:​lab07|breviarul laboratorului]].
   - În al doilea tab să fie deschisă [[:​so2:​laboratoare:​lab07:​exercitii|pagina curentă]].   - În al doilea tab să fie deschisă [[:​so2:​laboratoare:​lab07:​exercitii|pagina curentă]].
-  - În al treilea tab să fie deschisă [[http://lxr.free-electrons.com/source/?v=4.9|pagina LXR]] pentru parcurgerea codului sursă din nucleu.+  - În al treilea tab să fie deschisă [[https://elixir.bootlin.com/linux/v4.15/source|pagina LXR]] pentru parcurgerea codului sursă din nucleu.
  
 </​note>​ </​note>​
Line 49: Line 103:
  
 ===== [10.5p] Exerciții ===== ===== [10.5p] Exerciții =====
 +
 +<note important>​
 +Înainte de începerea rezolvării laboratorului,​ rulați comanda ''​%%git pull --rebase%%''​ in directorul ''​~/​so2/​linux'',​ pentru a obține ultima versiune a scheletului de laborator.
 +</​note>​
  
 ==== 1. [1p] Dispozitiv de tip bloc ==== ==== 1. [1p] Dispozitiv de tip bloc ====
  
-Creați un modul de kernel care să permită înregistrarea,​ respectiv deînregistrarea unui dispozitiv de tip bloc. Porniți de la fișierele din directorul ''​1-2-3-6-ram-disk/''​ din arhiva de sarcini a laboratorului.+Creați un modul de kernel care să permită înregistrarea,​ respectiv deînregistrarea unui dispozitiv de tip bloc. Porniți de la fișierele din directorul ''​1-2-3-6-ram-disk/​kernel''​ din scheletul ​laboratorului.
  
 Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator. Folosiți macrodefinițiile existente (''​MY_BLOCK_MAJOR'',​ ''​MY_BLKDEV_NAME''​). Verificați valoarea întoarsă de funcția de înregistrare și, în caz de eroare, întoarceți cod de eroare. Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator. Folosiți macrodefinițiile existente (''​MY_BLOCK_MAJOR'',​ ''​MY_BLKDEV_NAME''​). Verificați valoarea întoarsă de funcția de înregistrare și, în caz de eroare, întoarceți cod de eroare.
Line 64: Line 122:
 </​note>​ </​note>​
  
-Schimbați valoarea macroului ''​MY_BLOCK_MAJOR''​ la valoarea ''​7''​. Compilați modulul, copiați-l pe mașina virtuală și încărcați-l în nucleu. Observați că încărcarea eșuează întrucât există deja un alt driver/​dispozitiv care are majorul ''​7''​ înregistrat în nucleu.+Schimbați valoarea macroului ''​MY_BLOCK_MAJOR''​ la valoarea ''​254''​. Compilați modulul, copiați-l pe mașina virtuală și încărcați-l în nucleu. Observați că încărcarea eșuează întrucât există deja un alt driver/​dispozitiv care are majorul ''​254''​ înregistrat în nucleu.
  
 Restaurați valoarea ''​240''​ pentru macroul ''​MY_BLOCK_MAJOR''​. Restaurați valoarea ''​240''​ pentru macroul ''​MY_BLOCK_MAJOR''​.
  
-==== 2. [1.5p] Înregistrare disc ====+==== 2. [2p] Înregistrare disc ====
  
 Modificați modulul anterior pentru a adăuga un disc asociat driverului. Analizați macrodefinițiile,​ structura ''​struct my_block_dev''​ și funcțiile existente din fișierul ''​ram-disk.c''​. Modificați modulul anterior pentru a adăuga un disc asociat driverului. Analizați macrodefinițiile,​ structura ''​struct my_block_dev''​ și funcțiile existente din fișierul ''​ram-disk.c''​.
  
-Decomentați apelurile de funcții ''​create_block_device''​ și ''​delete_block_device''​.+Urmăriți comentariile marcate cu ''​TODO 2''​. Folosiți funcțiile ''​create_block_device''​ și ''​delete_block_device''​.
  
 <note tip> <note tip>
Line 79: Line 137:
 </​note>​ </​note>​
  
-Urmăriți secțiunile marcate cu ''​TODO 2''​ în scheletul de laborator. ​Completați funcția ''​my_block_request''​ pentru prelucrarea cozii de cereri fără a face o prelucrare efectivă a cererii: afișați mesajul ''​%%"​request received"​%%''​ și următoarele informații:​ sectorul de start, dimensiunea totală, dimensiunea datelor din bio-ul curent, direcția de tratare.+Completați funcția ''​my_block_request''​ pentru prelucrarea cozii de cereri fără a face o prelucrare efectivă a cererii: afișați mesajul ''​%%"​request received"​%%''​ și următoarele informații:​ sectorul de start, dimensiunea totală, dimensiunea datelor din bio-ul curent, direcția de tratare. Pentru a valida tipul unei cereri, folosiți funcția [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blkdev.h#​L264|blk_rq_is_passthrough]] (funcția returnează ''​0''​ în cazul de care suntem interesați,​ atunci când cererea este generată de către sistemul de fișiere).
  
 <note tip> <note tip>
Line 85: Line 143:
 </​note>​ </​note>​
  
-Folosiți [[http://lxr.free-electrons.com/​source/​block/​blk-core.c?v=4.9#L2879|__blk_end_request_all]] pentru încheierea prelucrării cererii.+Folosiți [[https://elixir.bootlin.com/​linux/​v4.15/​source/​block/​blk-core.c#​L3206|__blk_end_request_all]] pentru încheierea prelucrării cererii.
  
 Inserați modulul în kernel. Folosiți ''​dmesg''​ pentru a observa un mesaj transmis de modul. În momentul adăugării dispozitivului se transmite o cerere către acesta. Verificați prezența ''/​dev/​myblock''​ și dacă nu există creați dispozitivul folosind comanda<​code>​ Inserați modulul în kernel. Folosiți ''​dmesg''​ pentru a observa un mesaj transmis de modul. În momentul adăugării dispozitivului se transmite o cerere către acesta. Verificați prezența ''/​dev/​myblock''​ și dacă nu există creați dispozitivul folosind comanda<​code>​
Line 100: Line 158:
 Modificați modulul anterior pentru a crea un RAM disc: cererile către dispozitiv vor rezulta în citiri/​scrieri într-o zonă de memorie. ​ Modificați modulul anterior pentru a crea un RAM disc: cererile către dispozitiv vor rezulta în citiri/​scrieri într-o zonă de memorie. ​
  
-Zona de memorie aferentă ''​%%dev->​data%%''​ este deja alocată în codul sursă din modul folosind [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=4.9#L1752 | vmalloc]]((Pentru simplitate, se folosește funcția vmalloc pentru alocarea vectorului în memorie; funcția vmalloc alocă o zonă de memorie contiguă în spațiul de adrese virtuale, iar funcția vfree o dealocă. Mai multe despre alocarea memoriei în kernel găsiți în [[http://​lwn.net/​images/​pdf/​LDD3/​ch08.pdf | Linux Device Drivers 3rd Edition, Chapter 8. Allocating memory]])). Pentru dezalocare în modul se folosește [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=4.9#L1514 | vfree]].+Zona de memorie aferentă ''​%%dev->​data%%''​ este deja alocată în codul sursă din modul folosind [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​vmalloc.c#​L1829 | vmalloc]]((Pentru simplitate, se folosește funcția vmalloc pentru alocarea vectorului în memorie; funcția vmalloc alocă o zonă de memorie contiguă în spațiul de adrese virtuale, iar funcția vfree o dealocă. Mai multe despre alocarea memoriei în kernel găsiți în [[http://​lwn.net/​images/​pdf/​LDD3/​ch08.pdf | Linux Device Drivers 3rd Edition, Chapter 8. Allocating memory]])). Pentru dezalocare în modul se folosește [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​vmalloc.c#​L1581 | vfree]].
  
 <​note>​ <​note>​
Line 109: Line 167:
  
 <note tip> <note tip>
-Pentru a afla dimensiunea datelor din request folosiți macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​blkdev.h?v=4.9#L865|blk_rq_cur_bytes]]. **Nu** folosiți macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​blkdev.h?v=4.9#L860|blk_rq_bytes]].+Pentru a afla dimensiunea datelor din request folosiți macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blkdev.h#​L1032|blk_rq_cur_bytes]]. **Nu** folosiți macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blkdev.h#​L1027|blk_rq_bytes]]
 +</​note>​ 
 + 
 +<note tip> 
 +Pentru a afla buffer-ul cererii folosiți construcția ''​bio_data(rq->​bio)''​.
 </​note>​ </​note>​
  
Line 120: Line 182:
 </​note>​ </​note>​
  
-Pentru testare folosiți fișierul de test ''​ram-disk-test.c''​. Îl compilați folosindpe sistemul fiziccomanda<​code>​ +Pentru testare folosiți fișierul de test ''​user/ram-disk-test.c'', ​care se compilează automat la ''​make build''​se copiază pe mașina virtuală la ''​make copy'' ​și se rulează ​folosind, pe mașina virtuală QEMU, comanda<​code>​
-make -f Makefile.test +
-</​code>​ +
-și apoi îl rulați ​folosind, pe mașina virtuală QEMU, comanda<​code>​+
 ./​ram-disk-test ./​ram-disk-test
 </​code>​ </​code>​
 Nu este nevoie să încărcați modulul în nucleu, va fi încărcat de test prin rularea comenzii de mai sus. Nu este nevoie să încărcați modulul în nucleu, va fi încărcat de test prin rularea comenzii de mai sus.
  
-Există posibilitatea ca unele teste să pice din cauza nesincronizării datelor transmise (flush).+Există posibilitatea ca unele teste să pice din cauza nesincronizării datelor transmise (//flush//).
  
 ==== 4. [2p] Citirea datelor de pe disc ==== ==== 4. [2p] Citirea datelor de pe disc ====
  
-Scopul acestui exercițiu este să citiți datele de pe discul ''​PHYSICAL_DISK_NAME''​ direct din kernel.+Scopul acestui exercițiu este să citiți datele de pe discul ''​PHYSICAL_DISK_NAME'' ​(''/​dev/​vdb''​) ​direct din kernel.
  
-Urmăriți comentariile marcate cu ''​TODO 4''​ în directorul ''​4-5-relay-disk/'' ​și completați funcțiile ​''​open_disk'' ​și ''​close_disk''​. Folosiți funcțiile [[http://​lxr.free-electrons.com/​source/​fs/​block_dev.c?​v=4.9#​L1467 | blkdev_get_by_path]] ​și [[http://​lxr.free-electrons.com/​source/​fs/​block_dev.c?​v=4.9#​L1619 | blkdev_put]]. Dispozitivul trebuie deschis în mod read-write exclusiv (''​FMODE_READ | FMODE_WRITE | FMODE_EXCL''​), iar ca holder trebuie să folosiți modulul curent ​(''​THIS_MODULE''​).+<note important>​ 
 +Înainte de rezolvarea exercițiului,​ este necesar să adaugăm discul la mașina virtuală. Pentru aceasta, generați un fișier pe care îl vom folosi ca imaginea discului folosind comanda <​code>​dd if=/​dev/​zero of=qemu/​mydisk.img bs=1024 count=1</code> ​și adăugați argumentul ​''​-drive file=qemu/​mydisk.img,​if=virtio,​format=raw'' ​comenzii ​''​qemu''​, în fișierul ''​qemu/​Makefile''​ (în variabila ​''​QEMU_OPTS''​) 
 +</​note>​
  
-Completați funcția ''​send_test_bio''​. Va trebui să creați un nou bio pe care să-l completați,​ să-l submiteți și să-l așteptați. Citiți primul sector al discului. Pentru așteptare folosiți [[http://lxr.free-electrons.com/​source/​block/​bio.c?v=4.9#L863|submit_bio_wait]].+Urmăriți comentariile marcate cu ''​TODO 4''​ în directorul ''​4-5-relay-disk/''​ și completați funcțiile ''​open_disk''​ și ''​close_disk''​. Folosiți funcțiile [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​block_dev.c#​L1642 | blkdev_get_by_path]] și [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​block_dev.c#​L1752 | blkdev_put]]. Dispozitivul trebuie deschis în mod read-write exclusiv (''​FMODE_READ | FMODE_WRITE | FMODE_EXCL''​),​ iar ca holder trebuie să folosiți modulul curent (''​THIS_MODULE''​). 
 + 
 +Completați funcția ''​send_test_bio''​. Va trebui să creați un nou bio pe care să-l completați,​ să-l submiteți și să-l așteptați. Citiți primul sector al discului. Pentru așteptare folosiți [[https://elixir.bootlin.com/​linux/​v4.15/​source/​block/​bio.c#​L928|submit_bio_wait]].
  
 <note tip> <note tip>
-Primul sector al discului este sectorul cu indexul ''​0''​. La această valoare trebuie inițializat câmpul ''​bi_iter.bi_sector''​ al structurii [[http://lxr.free-electrons.com/​source/​include/​linux/​blk_types.h?v=4.9#L25|bio]].+Primul sector al discului este sectorul cu indexul ''​0''​. La această valoare trebuie inițializat câmpul ''​bi_iter.bi_sector''​ al structurii [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blk_types.h#​L50|bio]].
  
-Pentru operația de citire folosiți macro-urile ''​REQ_OP_READ''​ și [[http://lxr.free-electrons.com/​source/​include/​linux/​blk_types.h?v=4.9#L95|bio_set_op_attrs]].+Pentru operația de citire folosiți macro-urile ''​REQ_OP_READ''​ și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blk_types.h#​L271|bio_set_op_attrs]].
  
 </​note>​ </​note>​
  
-După terminarea operației afișați primii 3 octeți din datele citite de bio. Folosiți formatul ''​%%"​%02x"​%%''​ la ''​printk''​ pentru afișarea datelor și macrourile [[http://lxr.free-electrons.com/​source/​arch/​x86/​mm/​highmem_32.c?v=4.9#L55 | kmap_atomic]],​ respectiv [[http://lxr.free-electrons.com/​source/​include/​linux/​highmem.h?v=4.9#L124 | kunmap_atomic]].+După terminarea operației afișați primii 3 octeți din datele citite de bio. Folosiți formatul ''​%%"​%02x"​%%''​ la ''​printk''​ pentru afișarea datelor și macrourile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​arch/​x86/​mm/​highmem_32.c#​L55 | kmap_atomic]],​ respectiv [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​highmem.h#​L125 | kunmap_atomic]]. 
 + 
 +<note tip> 
 +Ca argument pentru [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​arch/​x86/​mm/​highmem_32.c#​L55 | kmap_atomic]] folosiți chiar pagina alocată mai sus în cod în cadrul variabilei ''​page''​. 
 +</​note>​
  
 <note tip> <note tip>
-Urmăriți secțiunea [:​so2:​laboratoare:​lab07#​folosirea_continutului_unei_structuri_bio|Folosirea conținutului unei structuri bio]] și [[:​so2:​laboratoare:​lab07#​asteptarea_incheierii_unei_structuri_bio|Așteptarea încheierii unei structuri bio]].+Urmăriți secțiunea ​[[:​so2:​laboratoare:​lab07#​folosirea_continutului_unei_structuri_bio|Folosirea conținutului unei structuri bio]] și [[:​so2:​laboratoare:​lab07#​asteptarea_incheierii_unei_structuri_bio|Așteptarea încheierii unei structuri bio]].
 </​note>​ </​note>​
  
-Pentru testare folosiți scriptul ''​test-relay-disk''​. Nu este nevoie să încărcați modulul în nucleu, va fi încărcat de test. Pentru a rula scriptul folosiți comanda<​code>​+Pentru testare folosiți scriptul ''​test-relay-disk'',​ care este copiat pe mașina virtuală la ''​make copy''​. Dacă nu este copiat, asigurați-vă că este executabil (''​chmod +x test-relay-disk''​). Nu este nevoie să încărcați modulul în nucleu, va fi încărcat de test. Pentru a rula scriptul folosiți comanda<​code>​
 ./​test-relay-disk ./​test-relay-disk
 </​code>​ </​code>​
 Scriptul scrie ''​%%"​abc"​%%''​ la începutul discului indicat de ''​PHYSICAL_DISK_NAME''​. În urma rulării, modulul va afișa ''​61 62 63''​ (valorile hexazecimale corespunzătoare). Scriptul scrie ''​%%"​abc"​%%''​ la începutul discului indicat de ''​PHYSICAL_DISK_NAME''​. În urma rulării, modulul va afișa ''​61 62 63''​ (valorile hexazecimale corespunzătoare).
  
-==== 5. [2p] Scrierea unui mesaj pe disc ====+==== 5. [1.5p] Scrierea unui mesaj pe disc ====
  
 Urmăriți comentariile marcate cu ''​TODO 5''​ pentru scrierea unui mesaj (''​BIO_WRITE_MESSAGE''​) pe disc.  Urmăriți comentariile marcate cu ''​TODO 5''​ pentru scrierea unui mesaj (''​BIO_WRITE_MESSAGE''​) pe disc. 
  
-Trebuie să actualizați funcția ''​send_test_bio'' ​pentru a primi ca argument tipul operației (citire sau scriere). Apelați în ''​relay_init''​ funcția pentru citire iar în ''​relay_exit''​ funcția pentru scriere. Recomandăm folosirea macro-urilor ​ ''​REQ_OP_READ''​ și ''​REQ_OP_WRITE''​.+Funcția ''​send_test_bio'' ​primește ​ca argument tipul operației (citire sau scriere). Apelați în ''​relay_init''​ funcția pentru citire iar în ''​relay_exit''​ funcția pentru scriere. Recomandăm folosirea macro-urilor ​ ''​REQ_OP_READ''​ și ''​REQ_OP_WRITE''​.
  
-În cadrul funcției ''​send_test_bio'',​ dacă operația este de scriere, completați buffer-ul aferent bio-ului cu mesajul ''​BIO_WRITE_MESSAGE''​. Folosiți macrourile [[http://lxr.free-electrons.com/​source/​arch/​x86/​mm/​highmem_32.c?v=4.9#L55 | kmap_atomic]],​ respectiv [[http://lxr.free-electrons.com/​source/​include/​linux/​highmem.h?v=4.9#L124 | kunmap_atomic]] pentru lucrul cu buffer-ul aferent bio-ului.+În cadrul funcției ''​send_test_bio'',​ dacă operația este de scriere, completați buffer-ul aferent bio-ului cu mesajul ''​BIO_WRITE_MESSAGE''​. Folosiți macrourile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​arch/​x86/​mm/​highmem_32.c#​L55 | kmap_atomic]],​ respectiv [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​highmem.h#​L125 | kunmap_atomic]] pentru lucrul cu buffer-ul aferent bio-ului.
  
 <note tip> <note tip>
-Trebuie să actualizați tipul operației [[http://lxr.free-electrons.com/​source/​include/​linux/​blk_types.h#​L46|structurii bio]] folosind macrodefiniția ''​bio_set_op_attrs''​+Trebuie să actualizați tipul operației [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blk_types.h#​L50|structurii bio]] folosind macrodefiniția ''​bio_set_op_attrs''​
 </​note>​ </​note>​
  
Line 174: Line 241:
  
 ==== 6. [2p] Prelucrarea cererilor din coada la nivel de bio ==== ==== 6. [2p] Prelucrarea cererilor din coada la nivel de bio ====
 +
 +În implementarea de la exercițiul 3, am prelucrat doar un ''​bio_vec''​ al ''​bio''​-ului curent din ''​request''​. Dorim să prelucrăm toate ''​bio_vec''​-urile din toate ''​bio''​-urile. Pentru aceasta vom parcurge toate ''​bio''​-urile ''​request''​-ului și toate ''​bio_vec''​-urile (numite și //​segmente//​) fiecărui ''​bio''​.
  
 Adăugați, în cadrul implementării ramdisk-ului (directorul ''​1-2-3-6-ram-disk''​) suport pentru prelucrarea cererilor din coada de cereri la nivel de bio. Urmăriți comentariile marcate cu ''​TODO 6''​. Adăugați, în cadrul implementării ramdisk-ului (directorul ''​1-2-3-6-ram-disk''​) suport pentru prelucrarea cererilor din coada de cereri la nivel de bio. Urmăriți comentariile marcate cu ''​TODO 6''​.
Line 179: Line 248:
 Configurați macro-ul ''​USE_BIO_TRANSFER''​ la valoarea 1. Configurați macro-ul ''​USE_BIO_TRANSFER''​ la valoarea 1.
  
-Implementați funcția ''​my_xfer_request''​. Folosiți [[http://lxr.free-electrons.com/​source/​include/​linux/​blkdev.h?v=4.9#L754|rq_for_each_segment]] pentru a parcurge structurile [[http://lxr.free-electrons.com/​source/​include/​linux/​bvec.h?v=4.9#L29 | bio_vec]] ale fiecărui [[http://lxr.free-electrons.com/​source/​include/​linux/​blk_types.h?v=4.9#L25 | bio]] din [[http://lxr.free-electrons.com/​source/​include/​linux/​blkdev.h?v=4.9#L88|request]].+Implementați funcția ''​my_xfer_request''​. Folosiți [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blkdev.h#​L927|rq_for_each_segment]] pentru a parcurge structurile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​bvec.h#​L30 | bio_vec]] ale fiecărui [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blk_types.h#​L50 | bio]] din [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​blkdev.h#​L135|request]]. 
 + 
 +<note tip> 
 +Urmăriți indicațiile și secvențele de cod din secțiunea [[:​so2:​laboratoare:​lab07#​folosirea_continutului_unei_structuri_bio|Folosirea conținutului unei structuri bio]]. 
 +</​note>​
  
 <note tip> <note tip>
Line 190: Line 263:
  
 <note tip> <note tip>
-Folosiți macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L2510|bio_data_dir]] pentru a afla direcția de citire sau scriere pentru un bio.+Folosiți macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​bio.h#L76|bio_data_dir]] pentru a afla direcția de citire sau scriere pentru un bio.
 </​note>​ </​note>​
  
-Folosiți macrourile ​''​kmap_atomic''​, respectiv ​''​kunmap_atomic'' ​pentru maparea paginilor fiecărui bio și accesarea bufferelor acestuia. Pentru transferul efectiv, apelați funcția ''​my_block_transfer''​ implementată la exercițiul anterior.+Folosiți macrourile ​[[https://​elixir.bootlin.com/​linux/​v4.15/​source/​arch/​x86/​mm/​highmem_32.c#​L55|kmap_atomic]], respectiv ​[[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​highmem.h#​L125|kunmap_atomic]] pentru maparea paginilor fiecărui bio și accesarea bufferelor acestuia. Pentru transferul efectiv, apelați funcția ''​my_block_transfer''​ implementată la exercițiul anterior.
  
-Pentru testare folosiți fișierul de test ''​ram-disk-test.c''​. ​Îl compilați folosind, pe sistemul fizic, comanda<​code>​ +Pentru testare folosiți fișierul de test ''​ram-disk-test.c''​.
-make -f Makefile.test+
 </​code>​ </​code>​
-și apoi îl rulați folosind, pe mașina virtuală QEMU, comanda<​code>​+îl rulați folosind, pe mașina virtuală QEMU, comanda<​code>​
 ./​ram-disk-test ./​ram-disk-test
 </​code>​ </​code>​
so2/laboratoare/lab07/exercitii.1491230753.txt.gz · Last modified: 2017/04/03 17:45 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