Differences

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

Link to this comparison view

so2:laboratoare:lab04:exercitii [2017/03/12 17:34]
octavian.purdila
so2:laboratoare:lab04:exercitii [2019/03/12 21:54] (current)
constantin.ghioc [1. [2p] Înregistrarea unui dispozitiv de tip caracter]
Line 1: Line 1:
 ====== Laborator 4: Exerciții ====== ====== Laborator 4: Exerciții ======
  
-Pentru desfășurarea laboratorului ​pornim ​de la [[http://​elf.cs.pub.ro/so2/res/laboratoare/lab04-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/​lab04-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 lab04-tasks.zip + 
-student@asgard:​~/​so2tree lab04-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 ''​lab04-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:​~/so2cp /​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 kernel. Apoi 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>​ </​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>​ +<note important>​ 
-# insmod ​modules/module-name.ko +Numele laboratorului curent este ''​device_drivers''​. 
-# rmmod module/module-name +</​note>​ 
-</​code> ​unde ''​module-name''​ este numele modulului de kernel.+ 
 +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 ./​device_drivers/​kernel ./​device_drivers/​extra/​char-driver-lin;​ 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 virtuale. Pentru 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>/<​task_name>''​. 
 + 
 +<code bash> 
 +root@qemux86:​~/​skels/​device_drivers#​ ls  
 +extra/ ​  ​kernel/ ​ user/ 
 +root@qemux86:​~/​skels/​device_drivers#​ ls kernel/ 
 +so2_cdev.ko 
 +</​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>​ 
 +root@qemux86:​~# insmod ​skels/<​lab_name>/<​task_name>/<​module_name>​.ko  
 +root@qemux86:​~# rmmod skels/<​lab_name>/<​task_name>/<​module_name>​.ko ​ 
 +</​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 generării scheletului ​de laborator, din ''​~/​so2/​linux/​tools/​labs/​skels''​
-  - Î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 pornim [[:​so2:​laboratoare:​lab02#​minicom|minicom]] sau un server UDP care să primească [[:​so2:​laboratoare:​lab02#​netconsole|mesajele de netconsole]]. Nu contează în ce director ne aflăm. Folosim comanda<​code bash>   - În al treilea tab de terminal pornim [[:​so2:​laboratoare:​lab02#​minicom|minicom]] sau un server UDP care să primească [[:​so2:​laboratoare:​lab02#​netconsole|mesajele de netconsole]]. Nu contează în ce director ne aflăm. Folosim comanda<​code bash>
-student@asgard:​~$ ​netcat ​-lup 6666+student@asgard:​~$ ​nc -l -p 6000 -u
 </​code>​ </​code>​
 </​note>​ </​note>​
 +
 +===== Exerciții =====
  
 <note warning> <note warning>
Line 37: Line 94:
 </​note>​ </​note>​
  
 +<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>​
  
 ===== [0.5p] Intro ===== ===== [0.5p] Intro =====
-Identificați,​ folosind cscope ​sau [[http://​lxr.free-electrons.com/​source/?​v=4.9|LXR]], definițiile următoarelor simboluri:+Identificați,​ folosind cscope, definițiile următoarelor simboluri:
   * structura ''​file'';​   * structura ''​file'';​
   * structura ''​file_operations'';​   * structura ''​file_operations'';​
   * constanta ''​generic_ro_fops'';​   * constanta ''​generic_ro_fops'';​
-  * funcțiile ''​vfs_read''​ și ''​do_sync_read''; ​+  * funcțiile ''​vfs_read'',​ ''​new_sync_read''​ și ''​generic_file_read_iter''; ​
  
-Urmăriți definiția funcției ''​vfs_read''​. Observați că pentru un dispozitiv care nu are funcția ''​read''​, dar care are definită ​funcția ​de citire asincronă ​''​aio_read''​se va apela ''​do_sync_read''​. Această funcție folosește ''​aio_read''​, iar apoi așteaptă primirea răspunsului pentru cererea de citire asincronă.+Urmăriți definiția funcției ''​vfs_read''​. Observați că pentru un dispozitiv care nu are funcția ''​read'' ​și nici funcția ''​read_iter''​ se va apela ''​new_sync_read''​. Această funcție folosește ''​read_iter'' ​care în mod implicit este definită la ''​generic_file_read_iter''​
  
 <note tip> <note tip>
-La căutarea simbolurilor în [[http://lxr.free-electrons.com/source/?v=4.9|LXR]], asiguraţi-vă că selectaţi aceeaşi versiune de kernel ca cea din laborator(4.9).+La căutarea simbolurilor în [[https://elixir.bootlin.com/linux/v4.15/source|LXR]], asiguraţi-vă că selectaţi aceeaşi versiune de kernel ca cea din laborator (4.19).
  
 Pentru cscope, folosiți comanda '':​cs f g //​nume//''​ pentru căutarea definiţiilor şi comanda '':​cs f s //​nume//''​ pentru căutarea simbolurilor. Pentru mai multe informaţii despre comenzile disponibile folosiţi comanda '':​help cscope''​. Pentru cscope, folosiți comanda '':​cs f g //​nume//''​ pentru căutarea definiţiilor şi comanda '':​cs f s //​nume//''​ pentru căutarea simbolurilor. Pentru mai multe informaţii despre comenzile disponibile folosiţi comanda '':​help cscope''​.
Line 55: Line 115:
 ===== [10.5p] Character Device Driver ===== ===== [10.5p] Character Device Driver =====
  
-==== 1. [1p] Înregistrarea unui dispozitiv de tip caracter ====+==== 1. [2p] Înregistrarea unui dispozitiv de tip caracter ====
  
 Driver-ul va controla un singur dispozitiv cu majorul ''​MY_MAJOR''​ și minorul ''​MY_MINOR ''​(macro-urile definite în fișierul ''​kernel/​so2_cdev.c''​) Ca prim pas, va trebui să creați fișierul de tip caracter ''/​dev/​so2_cdev''​ folosind utilitarul ''​mknod''​. Driver-ul va controla un singur dispozitiv cu majorul ''​MY_MAJOR''​ și minorul ''​MY_MINOR ''​(macro-urile definite în fișierul ''​kernel/​so2_cdev.c''​) Ca prim pas, va trebui să creați fișierul de tip caracter ''/​dev/​so2_cdev''​ folosind utilitarul ''​mknod''​.
Line 62: Line 122:
 Citiți secțiunea [[:​so2:​laboratoare:​lab04#​Identificator major și minor|Identificator major și minor]] din laborator. Citiți secțiunea [[:​so2:​laboratoare:​lab04#​Identificator major și minor|Identificator major și minor]] din laborator.
  
-Pentru a evita folosirea ''​mknod''​ la fiecare boot-are a mașinii, adăugați comanda ''​mknod''​ cu parametrii relevanți la finalul fișierului ''​qemu-vm/​fsimg/​etc/​rcS''​.+Pentru a evita folosirea ''​mknod''​ la fiecare boot-are a mașinii, adăugați comanda ''​mknod''​ cu parametrii relevanți la finalul fișierului ''/​etc/​rcS'' ​din mașina virtuală.
 </​note>​ </​note>​
  
 Implementați înregistrarea și deînregistrarea dispozitivului cu numele ''​so2_cdev'',​ respectiv în funcția de intrare și cea de ieșire a modulului. Nu uitați că driver-ul controlează un singur dispozitiv. La acest exercițiu nu este nevoie să folosiți apelurile ''​cdev_init''​ și ''​cdev_add''​. Le veți folosi la exercițiul 3. Implementați înregistrarea și deînregistrarea dispozitivului cu numele ''​so2_cdev'',​ respectiv în funcția de intrare și cea de ieșire a modulului. Nu uitați că driver-ul controlează un singur dispozitiv. La acest exercițiu nu este nevoie să folosiți apelurile ''​cdev_init''​ și ''​cdev_add''​. Le veți folosi la exercițiul 3.
 +Urmăriți comentariile marcate cu ''​TODO 1''​.
  
 <note tip> <note tip>
Line 71: Line 132:
 </​note>​ </​note>​
  
-Afișati, folosind ​macro-ul ​''​LOG_LEVEL'',​ un mesaj după operațiile de înregistrare,​ respectiv deînregistrare,​ care să confirme realizarea cu succes a acestora.+Afișati, folosind ''​pr_info'',​ un mesaj după operațiile de înregistrare,​ respectiv deînregistrare,​ care să confirme realizarea cu succes a acestora.
  
 Încărcați apoi modulul în kernel<​code>​ Încărcați apoi modulul în kernel<​code>​
Line 90: Line 151:
 rmmod so2_cdev rmmod so2_cdev
 </​code>​ </​code>​
 +
 ==== 2. [1p] Înregistrarea unui dispozitiv alocat ==== ==== 2. [1p] Înregistrarea unui dispozitiv alocat ====
 Modificați modulul de kernel pentru a încerca înregistrarea unui dispozitiv deja alocat. ​ Modificați modulul de kernel pentru a încerca înregistrarea unui dispozitiv deja alocat. ​
-Consultați [[http://lxr.free-electrons.com/​source/​include/​uapi/​asm-generic/​errno-base.h?v=4.9|LXR]] pentru a identifica eroarea întoarsă la înregistrarea modulului.+Consultați [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​uapi/​asm-generic/​errno-base.h|LXR]] pentru a identifica eroarea întoarsă la înregistrarea modulului.
  
 Reveniți la configurația inițială a modulului. Reveniți la configurația inițială a modulului.
Line 101: Line 163:
 ==== 3. [1p] Implementarea deschiderii și închiderii dispozitivului ==== ==== 3. [1p] Implementarea deschiderii și închiderii dispozitivului ====
 Rulați comanda ''​cat''​ peste dispozitivul de tip caracter creat (''/​dev/​so2_cdev''​). Citirea nu funcționează pentru că driver-ul nu are implementate funcțiile de deschidere, citire și închidere fișier. Rulați comanda ''​cat''​ peste dispozitivul de tip caracter creat (''/​dev/​so2_cdev''​). Citirea nu funcționează pentru că driver-ul nu are implementate funcțiile de deschidere, citire și închidere fișier.
 +Urmăriți comentariile marcate cu ''​TODO 2''​ pentru a realiza următoarele:​
   - Inițializați dispozitivul   - Inițializați dispozitivul
     * Citiți secțiunea [[:​so2:​laboratoare:​lab04#​Înregistrarea și deînregistrarea dispozitivelor de tip caracter|Înregistrarea și deînregistrarea dispozitivelor de tip caracter]] din laborator.     * Citiți secțiunea [[:​so2:​laboratoare:​lab04#​Înregistrarea și deînregistrarea dispozitivelor de tip caracter|Înregistrarea și deînregistrarea dispozitivelor de tip caracter]] din laborator.
Line 113: Line 176:
 Parcurgeți secțiunea [[:​so2:​laboratoare:​lab04#​open și release|open și release]]. Parcurgeți secțiunea [[:​so2:​laboratoare:​lab04#​open și release|open și release]].
 </​note>​ </​note>​
 +
 ==== 4. [1.5p] Restricționare acces ==== ==== 4. [1.5p] Restricționare acces ====
  
-Restricționați accesul la dispozitiv cu [[:​so2:​laboratoare:​lab03#​Variabile atomice|variabile atomice]], astfel încât un singur proces să poată deschide dispozitivul la un moment dat. Restul vor primi eroarea %%"​Device busy" (''​-EBUSY''​)%%. Restricționarea accesului se va face în funcția ''​open''​ expusă de driver.+Restricționați accesul la dispozitiv cu [[:​so2:​laboratoare:​lab03#​Variabile atomice|variabile atomice]], astfel încât un singur proces să poată deschide dispozitivul la un moment dat. Restul vor primi eroarea %%"​Device busy" (''​-EBUSY''​)%%. Restricționarea accesului se va face în funcția ''​open''​ expusă de driver. Urmăriți comentariile marcate cu ''​TODO 3''​.
   - Adăugați o variabilă de tip ''​atomic_t''​ în  structura dispozitivului. ​   - Adăugați o variabilă de tip ''​atomic_t''​ în  structura dispozitivului. ​
   - Inițializați variabila la inițializarea dispozitivului.   - Inițializați variabila la inițializarea dispozitivului.
-  - Folosiți variabila în funcția ''​open''​ pentru a restricționa accesul la dispozitiv. Recomandăm folosirea [[http://lxr.free-electrons.com/​source/​arch/​x86/​include/​asm/​atomic.h?v=4.9#L184|atomic_cmpxchg]] ((''​atomic_cmpxchg''​ întoarce **vechea** valoare a variabilei atomice)).+  - Folosiți variabila în funcția ''​open''​ pentru a restricționa accesul la dispozitiv. Recomandăm folosirea [[https://elixir.bootlin.com/​linux/​v4.15/​source/​arch/​x86/​include/​asm/​atomic.h#​L185|atomic_cmpxchg]] ((''​atomic_cmpxchg''​ întoarce **vechea** valoare a variabilei atomice)).
   - Resetați variabila în cadrul funcției de tip ''​release'',​ pentru a repermite accesul la dispozitiv.   - Resetați variabila în cadrul funcției de tip ''​release'',​ pentru a repermite accesul la dispozitiv.
   - Pentru a testa implementarea va trebui să simulați o utilizare îndelungată a dispozitivului. Apelați scheduler-ul la sfârşitul deschiderii dispozitivului:<​code c>   - Pentru a testa implementarea va trebui să simulați o utilizare îndelungată a dispozitivului. Apelați scheduler-ul la sfârşitul deschiderii dispozitivului:<​code c>
Line 136: Line 200:
 Mai multe detalii despre parametrii funcției găsiți [[https://​www.khronos.org/​registry/​cl/​sdk/​1.1/​docs/​man/​xhtml/​atomic_cmpxchg.html | aici]]. Mai multe detalii despre parametrii funcției găsiți [[https://​www.khronos.org/​registry/​cl/​sdk/​1.1/​docs/​man/​xhtml/​atomic_cmpxchg.html | aici]].
  
-Un exemplu de folosire găsiți [[http://lxr.free-electrons.com/​source/​lib/​dump_stack.c?v=4.9#L24|aici]].+Un exemplu de folosire găsiți [[https://elixir.bootlin.com/​linux/​v4.15/​source/​lib/​dump_stack.c#​L28|aici]].
 </​note>​ </​note>​
 +
 ==== 5. [2.5p] Citirea de mesaje ==== ==== 5. [2.5p] Citirea de mesaje ====
-Implementați funcția ''​read''​ în driver.+ 
 +Implementați funcția ''​read''​ în driver. Urmăriți comentariile marcate cu ''​TODO 4''​.
   - Păstrați în cadrul structurii dispozitivului un buffer pe care să îl inițializați la mesajul dat de macro-ul ''​MESSAGE''​. Inițializarea acestui buffer se va face odată cu inițializarea dispozitivului.   - Păstrați în cadrul structurii dispozitivului un buffer pe care să îl inițializați la mesajul dat de macro-ul ''​MESSAGE''​. Inițializarea acestui buffer se va face odată cu inițializarea dispozitivului.
   - La un apel ''​read''​ copiați în bufferul de user space conținutul buffer-ului din kernel space.   - La un apel ''​read''​ copiați în bufferul de user space conținutul buffer-ului din kernel space.
-    * Folosiți funcția [[http://lxr.free-electrons.com/​source/​include/​asm-generic/uaccess.h?v=4.9#L270|copy_to_user]] pentru a copia informații din kernel space în user space.+    * Folosiți funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/uaccess.h#L152|copy_to_user]] pentru a copia informații din kernel space în user space.
     * Ignorați pentru moment parametrii ''​size''​ și ''​offset''​. Puteți presupune că buffer-ul din user space este suficient de mare. Nu este nevoie să verificați validitatea argumentului ''​size''​ al funcției ''​read''​.     * Ignorați pentru moment parametrii ''​size''​ și ''​offset''​. Puteți presupune că buffer-ul din user space este suficient de mare. Nu este nevoie să verificați validitatea argumentului ''​size''​ al funcției ''​read''​.
     * Valoarea întoarsă de apelul ''​read''​ este numărul de octeți transmiși din buffer-ul din kernel space către buffer-ul din user space.     * Valoarea întoarsă de apelul ''​read''​ este numărul de octeți transmiși din buffer-ul din kernel space către buffer-ul din user space.
Line 170: Line 236:
 Prin dereferențierea parametrului ''​offset''​ se permite citirea și deplasarea poziției curente din fișier. Valoarea acesteia trebuie actualizată de fiecare dată când o citire se efectuează cu succes. Prin dereferențierea parametrului ''​offset''​ se permite citirea și deplasarea poziției curente din fișier. Valoarea acesteia trebuie actualizată de fiecare dată când o citire se efectuează cu succes.
 </​note>​ </​note>​
 +
 ==== 6. [1.5p] Scrierea de mesaje ==== ==== 6. [1.5p] Scrierea de mesaje ====
-Adăugați posibilitatea de a scrie un mesaj care să îl înlocuiască pe cel predefinit. Implementați funcția ''​write''​ în driver.+ 
 +Adăugați posibilitatea de a scrie un mesaj care să îl înlocuiască pe cel predefinit. Implementați funcția ''​write''​ în driver. Urmăriți comentariile marcate cu ''​TODO 5''​.
  
 Ignorați pe moment parametrul ''​offset''​. Puteți presupune că buffer-ul driverului este suficient de mare. Nu este nevoie să verificați validitatea argumentului ''​size''​ al funcției ''​write''​. Ignorați pe moment parametrul ''​offset''​. Puteți presupune că buffer-ul driverului este suficient de mare. Nu este nevoie să verificați validitatea argumentului ''​size''​ al funcției ''​write''​.
Line 186: Line 254:
 </​note>​ </​note>​
  
-==== 7. [2p] Operație de tip ''​ioctl''​. ====+==== 7. [1p] Operație de tip ''​ioctl''​. ====
  
-Pentru acest exercițiu dorim să adăugăm operația ioctl ''​MY_IOCTL_PRINT''​ care să afișeze mesajul dat de macro-ul ''​IOCTL_MESSAGE''​ din driver.+Pentru acest exercițiu dorim să adăugăm operația ioctl ''​MY_IOCTL_PRINT''​ care să afișeze mesajul dat de macro-ul ''​IOCTL_MESSAGE''​ din driver. Urmăriți comentariile marcate cu ''​TODO 6''​.
  
 Pentru aceasta: Pentru aceasta:
   - Implementați funcția ''​ioctl''​ în driver.   - Implementați funcția ''​ioctl''​ în driver.
-  - Trebuie să scrieți un program în user-space (''​user/​so2_cdev_test.c''​) care să apeleze funcția ''​ioctl''​ cu parametrii corespunzători. În fișierul de testare trebuie să apelați ''​ioctl''​ pentru fișierul dispozitivului. 
   - Folosiți ''​printk''​ pentru a afișa mesajul din driver.   - Folosiți ''​printk''​ pentru a afișa mesajul din driver.
 +  - Pentru testare, vom folosi un program în user-space (''​user/​so2_cdev_test.c''​) care să apeleze funcția ''​ioctl''​ cu parametrii corespunzători.
  
 <note tip> <note tip>
-Macrodefiniția ''​MY_IOCTL_PRINT''​ este definită în fișierul ''​include/​so2_cdev.h''​ din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab04-tasks.zip|arhiva de sarcini]] a laboratorului (folosește ''​_IOC''​ pentru a defini operația)+Macrodefiniția ''​MY_IOCTL_PRINT''​ este definită în fișierul ''​include/​so2_cdev.h''​ din scheletul ​laboratorului (folosește ''​_IOC''​ pentru a defini operația). Acest fișier antet este inclus de ambele fișiere sursă (modulul de kernel și programul de test din user space).
  
 Citiți secțiunile [[:​so2:​laboratoare:​lab04#​ioctl|ioctl]] și [[:​so2:​laboratoare:​lab04#​open și release|open și release]] ​ din laborator. Citiți secțiunile [[:​so2:​laboratoare:​lab04#​ioctl|ioctl]] și [[:​so2:​laboratoare:​lab04#​open și release|open și release]] ​ din laborator.
Line 202: Line 270:
  
 <note tip> <note tip>
-Pentru a compila codul sursă de user space folosiți compilatorul ​''​gcc-5''​. ​Pentru aceasta rulați comanda:<​code>​ +Codul sursă de user space este compilat automat în momentul în care rulați ''​make build''​. ​După ''​make copy'',​ veți găsi executabilul în directorul ''​/home/root/skels/device_drivers/​user''​.
-/usr/bin/gcc-5 -m32 -static -Wall -g -o so2_cdev_test so2_cdev_test.c +
-</code> +
- +
-Executabilul rezultat trebuie să îl copiați pe mașina virtuală la fel ca modulul de kernel și să îl rulați pe mașina virtuală pentru a valida implementarea corectă a ''​ioctl''​.+
 </​note>​ </​note>​
  
  
 ==== Extra ==== ==== Extra ====
 +
 +<​note>​Urmăriți comentariile marcate cu ''​TODO 7''​.</​note>​
  
 1. (**2 karma**) Ioctl cu transmitere de mesaje 1. (**2 karma**) Ioctl cu transmitere de mesaje
so2/laboratoare/lab04/exercitii.1489332891.txt.gz · Last modified: 2017/03/12 17:34 by octavian.purdila
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