Differences

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

Link to this comparison view

so2:laboratoare:lab06:exercitii [2017/03/28 12:49]
razvan.deaconescu [3. [2p] Controlare timer folosind ioctl]
so2:laboratoare:lab06:exercitii [2018/03/28 09:17] (current)
ionel.ghita [4. [1.5p] Operații blocante]
Line 1: Line 1:
 ====== Laborator 6: Exerciții ====== ====== Laborator 6: Exerciții ======
  
-Pentru desfășurarea laboratorului ​pornim ​de la [[http://​elf.cs.pub.ro/so2/res/laboratoare/lab06-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 ''​asgard''​):<code bash> +===== Pregătirea laboratorului ===== 
-student@asgard:​~$ cd so2/ + 
-student@asgard:​~/​so2$ wget http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab06-tasks.zip +Pentru rezolvarea laboratorului,​ vom lucra în același director din care pornim ​mașina virtuală (''​~/so2/linux/tools/labs''​). 
-student@asgard:​~/​so2$ unzip lab06-tasks.zip + 
-student@asgard:​~/​so2tree lab06-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 ''​lab06-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 ​''​asgard''​ș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@asgard:~/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@asgard:~/so2/qemu-so2$ make+tools/labs $ make clean 
 +tools/labs $ LABS=<​lab name> make skels 
 +</​code>​ 
 + 
 +<note important>​ 
 +Numele laboratorului curent este ''​deferred_work''​. 
 +</​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 ./​deferred_work/​6-kthread ./​deferred_work/​1-2-timer ./​deferred_work/​3-4-5-deferred/​kernel;​ 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/deferred_work#​ ls 
 +1-2-timer ​      ​3-4-5-deferred ​ 6-kthread 
 +root@qemux86:​~/​skels/​deferred_work#​ ls 1-2-timer/​ 
 +timer.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>​
Line 41: Line 96:
  
 ===== [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. [2p] Timer ==== ==== 1. [2p] Timer ====
Line 46: Line 105:
 Urmărim crearea unui modul simplu de kernel care să afișeze un mesaj la ''​TIMER_TIMEOUT''​ secunde de la încărcarea modulului în kernel. Urmărim crearea unui modul simplu de kernel care să afișeze un mesaj la ''​TIMER_TIMEOUT''​ secunde de la încărcarea modulului în kernel.
  
-În directorul ''​1-2-timer/'' ​din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab06-tasks.zip|arhiva de sarcini]] a laboratorului ​este scheletul de cod ''​timer.c''​ de unde să porniți pentru implementare. Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator.+În directorul ''​1-2-timer/''​ este scheletul de cod ''​timer.c''​ de unde să porniți pentru implementare. Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator.
  
 <​note>​ <​note>​
Line 70: Line 129:
 Ne propunem să afișăm informații despre procesul curent după **N** secunde de la primirea unei comezi de tipul ''​ioctl''​ apelată din user space. **N** este transmis ca paramentru prin ''​ioctl''​. Ne propunem să afișăm informații despre procesul curent după **N** secunde de la primirea unei comezi de tipul ''​ioctl''​ apelată din user space. **N** este transmis ca paramentru prin ''​ioctl''​.
  
-Porniți de la fișierele din subdirectorul ''​3-4-5-deferred/​kernel/'' ​din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab06-tasks.zip|arhiva de sarcini]] a laboratorului. Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator.+Porniți de la fișierele din subdirectorul ''​3-4-5-deferred/​kernel/''​. Urmăriți secțiunile marcate cu ''​TODO 1''​ în scheletul de laborator.
  
 Va trebui să implementați următoarele operații ''​ioctl''​. Va trebui să implementați următoarele operații ''​ioctl''​.
Line 103: Line 162:
 </​note>​ </​note>​
  
-Activați și dezactivați timer-ul prin apelul operațiilor ioctl din user-space. Utilizați programul ''​3-4-5-deferred/​user/​test/''​ din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab06-tasks.zip|arhiva de sarcini]]. Rulați programul pentru a testa planificarea și dezactivarea unui timer. Programul primește ca parametri în linie de comandă operația de tip ioctl și parametrii acesteia (dacă e cazul).+Activați și dezactivați timer-ul prin apelul operațiilor ioctl din user-space. Utilizați programul ''​3-4-5-deferred/​user/​test/''​ din scheletul laboratorului. Rulați programul pentru a testa planificarea și dezactivarea unui timer. Programul primește ca parametri în linie de comandă operația de tip ioctl și parametrii acesteia (dacă e cazul).
  
 Executabilul rezultat (''​test''​) trebuie să îl copiați pe mașina virtuală QEMU la fel ca modulul de kernel și să îl rulați pe mașina virtuală pentru a valida implementarea corectă a ''​ioctl''​. Executabilul rezultat (''​test''​) trebuie să îl copiați pe mașina virtuală QEMU la fel ca modulul de kernel și să îl rulați pe mașina virtuală pentru a valida implementarea corectă a ''​ioctl''​.
  
-</​note>​ 
  
 <note tip> <note tip>
Line 135: Line 193:
 Observați că programul cauzează eroare pentru că se apelează o funcție blocantă în context atomic (handler-ul de timer rulează în context amânabil/​întrerupere). Observați că programul cauzează eroare pentru că se apelează o funcție blocantă în context atomic (handler-ul de timer rulează în context amânabil/​întrerupere).
  
 +<note tip>
 +Pentru a obține un pointer la datele private ale modulului (structura ''​my_device_data''​),​ puteți folosi macro-ul [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​timer.h#​L143|from_timer]],​
 + care este similar cu [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​tools/​include/​linux/​kernel.h#​L26|container_of]].
 +<code c>
 +static void timer_handler(struct timer_list *tl)
 +{
 +    struct my_device_data *data = from_timer(data,​ tl, timer);
 +    ...
 +}
 +</​code>​
 +</​note>​
 ==== 5. [1.5p] Workqueues ==== ==== 5. [1.5p] Workqueues ====
  
Line 142: Line 211:
  
 <note tip> <note tip>
-Adăugați un câmp ''​work''​ de tipul ''​struct work_struct''​ în structura de dispozitiv. Inițializați acest câmp. Submiterea work-ului după **N** secunde o veți face din rutina de tratare a timer-ului, folosind funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=3.13#L555|schedule_work]]. Timer-ul va fi planificat să ruleze după **N** secunde, rutina de tratare a timer-ului va planifica work-ul și acesta va rula cât mai aproape de acel moment. **Nu** folosiți funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=3.13#L571|schedule_delayed_work_on]].+Adăugați un câmp ''​work''​ de tipul ''​struct work_struct''​ în structura de dispozitiv. Inițializați acest câmp. Submiterea work-ului după **N** secunde o veți face din rutina de tratare a timer-ului, folosind funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L533|schedule_work]]. Timer-ul va fi planificat să ruleze după **N** secunde, rutina de tratare a timer-ului va planifica work-ul și acesta va rula cât mai aproape de acel moment. **Nu** folosiți funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L578|schedule_delayed_work_on]].
  
-Folosiți **workqueue**-ul implicit (adică **nu** creați un workqueue, adică **nu** apelați [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=3.13#L452|create_workqueue]]).+Folosiți **workqueue**-ul implicit (adică **nu** creați un workqueue, adică **nu** apelați [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L428|create_workqueue]]).
 </​note>​ </​note>​
  
Line 155: Line 224:
 Dorim să creăm un modul simplu în care să creăm un kernel thread cu ajutorul căruia să afișăm identificatorul procesului curent. Dorim să creăm un modul simplu în care să creăm un kernel thread cu ajutorul căruia să afișăm identificatorul procesului curent.
  
-Porniți de la fișierele din subdirectorul ''​6-kthread/''​ din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab06-tasks.zip|arhiva de sarcini]] a laboratorului și urmăriți TODO-urile din codul sursă.+Porniți de la fișierele din subdirectorul ''​6-kthread/''​ din scheletul ​laboratorului și urmăriți TODO-urile din codul sursă.
  
 Veți crea și veți porni kernel thread-ul la încărcarea modulului. Veți crea și veți porni kernel thread-ul la încărcarea modulului.
Line 161: Line 230:
 <note tip> <note tip>
 Pentru crearea unui thread aveți două opțiuni: Pentru crearea unui thread aveți două opțiuni:
-  * Apelați macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​kthread.h?v=3.13#L22|kthread_run]]. +  * Apelați macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kthread.h#​L35|kthread_run]]. 
-  * Apelați macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​kthread.h?v=3.13#L13|kthread_create]] care creează un thread suspendat și apoi apelați funcția [[http://lxr.free-electrons.com/​source/​kernel/​sched/​core.c?v=3.13#L1674|wake_up_process]] pentru rularea acestuia; așa cum se întâmplă în cadrul macro-ului [[http://lxr.free-electrons.com/​source/​include/​linux/​kthread.h?v=3.13#L22|kthread_run]].+  * Apelați macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kthread.h#​L15|kthread_create]] care creează un thread suspendat și apoi apelați funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​sched/​core.c#​L2137|wake_up_process]] pentru rularea acestuia; așa cum se întâmplă în cadrul macro-ului [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kthread.h#​L35|kthread_run]].
  
 Parcurgeți secțiunea [[:​so2:​laboratoare:​lab06#​Kernel threads|Kernel threads]] din laborator. Parcurgeți secțiunea [[:​so2:​laboratoare:​lab06#​Kernel threads|Kernel threads]] din laborator.
Line 207: Line 276:
 </​note>​ </​note>​
  
-În implementare porniți de la codul din subdirectorul ''​3-4-5-deferred/''​. Urmăriți secțiunile marcate cu ''​TODO ​karma''​ în scheletul de laborator.+În implementare porniți de la codul din subdirectorul ''​3-4-5-deferred/''​. Urmăriți secțiunile marcate cu ''​TODO ​4''​ în scheletul de laborator.
  
 <note tip> <note tip>
so2/laboratoare/lab06/exercitii.1490694565.txt.gz · Last modified: 2017/03/28 12:49 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