Differences

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

Link to this comparison view

so2:laboratoare:lab07:exercitii [2017/04/05 13:27]
razvan.deaconescu [4. [2p] Citirea datelor de pe 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>​
  
Line 124: 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>​
Line 136: Line 191:
 ==== 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. 
 + 
 +<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>​
  
-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''​).+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 [[http://lxr.free-electrons.com/​source/​block/​bio.c?v=4.9#L863|submit_bio_wait]].+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> <note tip>
-Ca argument pentru [[http://lxr.free-electrons.com/​source/​arch/​x86/​mm/​highmem_32.c?v=4.9#L55 | kmap_atomic]] folosiți chiar pagina alocată mai sus în cod în cadrul variabilei ''​page''​.+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>​
  
Line 159: Line 218:
 </​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 189: 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> <note tip>
Line 204: 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 [[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#L120|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.1491388075.txt.gz · Last modified: 2017/04/05 13:27 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