Differences

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

Link to this comparison view

so2:laboratoare:lab03:exercitii [2018/03/04 20:54]
ionel.ghita [[0.5p] Intro]
so2:laboratoare:lab03:exercitii [2018/03/06 23:09] (current)
anda.nicolae [2. [1p] Folosirea de operații blocante în context atomic]
Line 105: Line 105:
  
 ==== 1. [1p] Alocarea de memorie în Linux ==== ==== 1. [1p] Alocarea de memorie în Linux ====
 +
 +<​note>​
 +Înainte de rezolvarea exercițiilor,​ generați scheletul de laborator. Această operație este descrisă mai sus.
 +</​note>​
  
 Intrați în directorul ''​1-mem/''​ și parcurgeți conținutul fișierului ''​mem.c''​. Intrați în directorul ''​1-mem/''​ și parcurgeți conținutul fișierului ''​mem.c''​.
 Observați folosirea apelului ''​kmalloc''​ pentru alocare de memorie. Observați folosirea apelului ''​kmalloc''​ pentru alocare de memorie.
-  - Compilați codul sursă într-un modul de kernel ​folosind comanda ​''​make''​.+  - Compilați codul sursă într-un modul de kernel ​și copiați-l pe mașina virtuală, conform informațiilor de mai sus (''​make ​build'' ​și ''​make copy''​).
   - Încărcați modulul în kernel folosind comanda ''​insmod mem.ko''​.   - Încărcați modulul în kernel folosind comanda ''​insmod mem.ko''​.
   - Vizualizați mesajele nucleului folosind comanda ''​dmesg''​.   - Vizualizați mesajele nucleului folosind comanda ''​dmesg''​.
Line 119: Line 123:
 ==== 2. [1p] Folosirea de operații blocante în context atomic ==== ==== 2. [1p] Folosirea de operații blocante în context atomic ====
  
-Intrați în directorul ''​2-sched-spin/''​ și parcurgeți conținutul fișierului ''​sched-spin.c''​. **Hint**: Funcția [[http://lxr.free-electrons.com/​source/​kernel/​time/​timer.c?v=4.9#L1697|schedule_timeout]],​ coroborată cu macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​sched.h?v=4.9#L297|set_current_state]],​ forțează procesul curent să aștepte 5 secunde. +Intrați în directorul ''​2-sched-spin/''​ și parcurgeți conținutul fișierului ''​sched-spin.c''​. **Hint**: Funcția [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​kernel/​time/​timer.c#​L1725|schedule_timeout]],​ coroborată cu macro-ul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​sched.h#​L128|set_current_state]],​ forțează procesul curent să aștepte 5 secunde. 
-  - Compilați codul sursă într-un modul de kernel ​folosind comanda ​''​make''​.+  - Compilați codul sursă într-un modul de kernel ​și copiați-l pe mașina virtuală, conform informațiilor de mai sus (''​make build''​ și ''​make ​copy''​).
   - Încărcați modulul în kernel folosind comanda ''​insmod sched-spin.ko''​.   - Încărcați modulul în kernel folosind comanda ''​insmod sched-spin.ko''​.
     * Observați că se așteaptă 5 secunde până la definitivarea comenzii de inserare.     * Observați că se așteaptă 5 secunde până la definitivarea comenzii de inserare.
-  - Descărcați ​modului ​din kernel. +  - Descărcați ​modulul ​din kernel. 
-  - Decomentați liniile care conțin operații cu spinlock-uri. Compilați din nou codul sursă și reîncărcați modulul în kernel.+  - Modificați modulul în locurile marcate cu ''​TODO 0'',​ astfel încât să includețoperația de sleep într-o secțiune atomică, folosind ​spinlock-ul deja definit. Compilați din nou codul sursă și reîncărcați modulul în kernel. **Hint**: ''​spin_lock''​ și ''​spin_unlock''​.
  
 Ați obținut eroare. Urmăriți stack trace-ul. Care este cauza erorii? **Hint**: Urmăriți, în mesajul de eroare, linia care conține ''​BUG''​ pentru o descriere a erorii. Nu aveți voie să realizați operații blocante în context atomic. Contextul atomic este dat de o secțiune aflată între o operație de ''​lock''​ și una de ''​unlock''​ pe un spinlock. Ați obținut eroare. Urmăriți stack trace-ul. Care este cauza erorii? **Hint**: Urmăriți, în mesajul de eroare, linia care conține ''​BUG''​ pentru o descriere a erorii. Nu aveți voie să realizați operații blocante în context atomic. Contextul atomic este dat de o secțiune aflată între o operație de ''​lock''​ și una de ''​unlock''​ pe un spinlock.
Line 136: Line 140:
 Intrați în directorul ''​3-memory/''​ și parcurgeți conținutul fișierului ''​memory.c''​. Observați comentariile marcate cu TODO.  Intrați în directorul ''​3-memory/''​ și parcurgeți conținutul fișierului ''​memory.c''​. Observați comentariile marcate cu TODO. 
 Trebuie să alocați 4 structuri de tipul ''​struct task_info''​ și să le inițializați (în funcția ''​memory_init''​),​ apoi să le afișați și dezalocați (în funcția ''​memory_exit''​). Trebuie să alocați 4 structuri de tipul ''​struct task_info''​ și să le inițializați (în funcția ''​memory_init''​),​ apoi să le afișați și dezalocați (în funcția ''​memory_exit''​).
-  - (**TODO 1**) Structurile vor conținerespectiv:+  - (**TODO 1**) Alocați structura ''​struct task_info''​ și inițializați câmpurile acesteia: 
 +    * câmpul ''​pid''​ la PID-ul transmis ca parametru;​ 
 +    * câmpul ''​timestamp''​ la valoarea variabilei ''​jiffies''​care menține timpul de activitate al sistemului. 
 +      * **Hint**: Detalii despre variabila ''​jiffies''​ se găsesc în [[http://​ocw.cs.pub.ro/​courses/​so2/​laboratoare/​lab06#​timere|laboratorul 6]]. 
 +  - (**TODO 2**) Folosiți funcția completată anterior pentru a inițializa cele 4 structuri cu următoarele informații:
     * PID-ul procesului curent, dat de macro-ul ''​current'',​ de tipul ''​struct task_struct *''​.     * PID-ul procesului curent, dat de macro-ul ''​current'',​ de tipul ''​struct task_struct *''​.
-      * **Hint**: Căutați câmpul relevant pentru PID în structura [[http://lxr.free-electrons.com/​source/​include/​linux/​sched.h?v=4.9#L1475|task_struct]].+      * **Hint**: Căutați câmpul relevant pentru PID în structura [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​sched.h#​L520|task_struct]].
     * PID-ul procesului părinte al procesului curent.     * PID-ul procesului părinte al procesului curent.
       * **Hints**:       * **Hints**:
-        * Căutați câmpul relevant din structura [[http://lxr.free-electrons.com/​source/​include/​linux/​sched.h?v=4.9#L1475|task_struct]].+        * Căutați câmpul relevant din structura [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​sched.h#​L520|task_struct]].
         * Căutați după șirul "​parent"​.         * Căutați după șirul "​parent"​.
     * PID-ul procesului următor din lista de procese.     * PID-ul procesului următor din lista de procese.
       * **Hints**:       * **Hints**:
-        * Folosiți macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​sched.h?v=4.9#L2990|next_task]].+        * Folosiți macro-ul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​sched/signal.h#L500|next_task]].
         * Macro-ul întoarce pointer-ul la următorul proces, adică de tipul ''​struct task_struct *''​.         * Macro-ul întoarce pointer-ul la următorul proces, adică de tipul ''​struct task_struct *''​.
     * PID-ul următorului proces după următorul.     * PID-ul următorului proces după următorul.
-        * **Hint**: Folosiți de două ori macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​sched.h?v=4.9#L2990|next_task]]. +        * **Hint**: Folosiți de două ori macro-ul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​sched/signal.h#L500|next_task]].
-  - (**TODO 2**) Alocați structura ''​struct task_info''​ și inițializați câmpurile acesteia: +
-    * câmpul ''​pid''​ la PID-ul transmis ca parametru;​ +
-    * câmpul ''​timestamp''​ la valoarea variabilei ''​jiffies'',​ care menține timpul de activitate al sistemului. +
-      * **Hint**: Detalii despre variabila ''​jiffies''​ se găsesc în [[http://​ocw.cs.pub.ro/​courses/​so2/​laboratoare/​lab06#​timere|laboratorul 6]].+
   - (**TODO 3**) Afișați cele patru structuri.   - (**TODO 3**) Afișați cele patru structuri.
     * Folosiți ''​printk''​ pentru a afișa cele două câmpuri ale acestora: ''​pid''​ și ''​timestamp''​.     * Folosiți ''​printk''​ pentru a afișa cele două câmpuri ale acestora: ''​pid''​ și ''​timestamp''​.
Line 172: Line 176:
 ==== 4. [2p] Lucrul cu liste în kernel ==== ==== 4. [2p] Lucrul cu liste în kernel ====
  
-Intrați în directorul ''​4-list/''​. Parcurgeți conținutul fișierului ''​list.c''​ și observați comentariile marcate cu TODO. Procesul curent va adăuga cele patru structuri menționate anterior într-o listă. Lista va fi construită în funcția ''​list_init''​ și în funcția ''​task_info_add_for_current''​. Lista va fi afișată și ștearsă în funcția ''​list_exit''​ și în funcția ''​task_info_purge_list''​.+Intrați în directorul ''​4-list/''​. Parcurgeți conținutul fișierului ''​list.c''​ și observați comentariile marcate cu TODO. Procesul curent va adăuga cele patru structuri menționate anterior într-o listă. Lista va fi construită în funcția ''​list_init''​ și în funcția ''​task_info_add_for_current''​. Lista va fi afișată în funcția ''​task_info_print_list''​ și ștearsă ​în funcția ''​task_info_purge_list'',​ ambele fiind apelate din ''​list_exit''​.
  
-  ​- (**TODO 0**) Copiați de la exercițiul anterior (''​3-memory/''​) funcțiile și secțiunile indicate. +  - (**TODO 1**) Completați funcția ''​task_info_add_to_list''​ pentru a aloca o structură ''​struct task_info''​ și a o adăuga la listă. Funcția este deja apelată de 4 ori din ''​task_info_add_for_current''​.
-  ​- (**TODO 1**) Completați funcția ''​task_info_add_to_list''​ pentru a aloca o structură ''​struct task_info''​ și a o adăuga la listă.+
   - (**TODO 2**) Completați funcția ''​task_info_purge_list''​ pentru a șterge toate elementele din listă.   - (**TODO 2**) Completați funcția ''​task_info_purge_list''​ pentru a șterge toate elementele din listă.
-  - Compilați modulul de kernel. Încărcați și descărcați modulul urmărind mesajele afișate de kernel.+  - Compilați modulul de kernel ​și copiați-l pe mașina virtuală. Încărcați și descărcați modulul urmărind mesajele afișate de kernel.
   ​   ​
 <note tip> <note tip>
 Revedeți secțiunea [[:​so2:​laboratoare:​lab03#​Liste|Liste]] din laborator. Revedeți secțiunea [[:​so2:​laboratoare:​lab03#​Liste|Liste]] din laborator.
  
-Atunci când ștergeți elemente din listă, va trebui să folosiți apelul [[http://lxr.free-electrons.com/​source/​include/​linux/​list.h?v=4.9#L422|list_for_each_safe]]. Puteți folosi și apelul [[http://lxr.free-electrons.com/​source/​include/​linux/​list.h?v=4.9#L516|list_for_each_entry_safe]].+Atunci când ștergeți elemente din listă, va trebui să folosiți apelul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​list.h#​L436|list_for_each_safe]]. Puteți folosi și apelul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​list.h#​L543|list_for_each_entry_safe]].
 </​note>​ </​note>​
  
Line 197: Line 200:
     * Facilitatea de expirare este implementată deja în funcția ''​task_info_remove_expired''​.     * Facilitatea de expirare este implementată deja în funcția ''​task_info_remove_expired''​.
   ​   ​
-  - (**TODO 0**) Copiați de la ''​3-memory''​ și/sau ''​4-list''​ secțiuni de cod acolo unde sunt indicate astfel. 
   - (**TODO 1**) Implementați funcția ''​task_info_find_pid''​ așa cum este descris mai sus și în comentariul funcției.   - (**TODO 1**) Implementați funcția ''​task_info_find_pid''​ așa cum este descris mai sus și în comentariul funcției.
   - (**TODO 2**) Modificați un câmp al unui element din listă astfel încât acesta să nu expire. **Hint**: Trebuie să nu satisfacă o parte a condiției de expirare din funcția ''​task_info_remove_expired''​.   - (**TODO 2**) Modificați un câmp al unui element din listă astfel încât acesta să nu expire. **Hint**: Trebuie să nu satisfacă o parte a condiției de expirare din funcția ''​task_info_remove_expired''​.
-  - Compilați, încărcați și descărcați modulul urmărind mesajele afișate. Va dura încărcarea modulului întrucât este prezent un "​sleep"​ prin intermediul funcției ''​schedule_timeout''​.+  - Compilați, copiați, încărcați și descărcați modulul urmărind mesajele afișate. Va dura încărcarea modulului întrucât este prezent un "​sleep"​ prin intermediul funcției ''​schedule_timeout''​.
  
 <note tip> <note tip>
Line 209: Line 211:
  
 Intrați în directorul ''​6-list-sync/''​. Intrați în directorul ''​6-list-sync/''​.
-  - Copiați fișierul ​''​5-list-full/​list-full.c''​ (rezolvarea anterioară) în ''​6-list-sync/​list-sync.c''​. +  - Fișierul ''​6-list-sync/​list-sync.c'' ​conține aceeași funcționalitate ca cea adăugată la exercițiul anterior
-  - Folosiți un spinlock sau un read-write lock pentru a sincroniza accesul la lista folosită. +  - Folosiți un spinlock sau un read-write lock pentru a sincroniza accesul la lista folosită. Urmăriți comentariile marcate cu **TODO**
-  - Compilați, încărcați și descărcați modulul de kernel.+  - Compilați, copiați, încărcați și descărcați modulul de kernel.
  
 <note tip> <note tip>
Line 225: Line 227:
 Pentru exportarea funcțiilor de mai sus, din modulul de la ''​6-list-sync/''​ este nevoie de următorii pași: Pentru exportarea funcțiilor de mai sus, din modulul de la ''​6-list-sync/''​ este nevoie de următorii pași:
   - Funcțiile nu trebuie să fie statice.   - Funcțiile nu trebuie să fie statice.
-  - Folosiți ​macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​export.h?v=4.9#L70|EXPORT_SYMBOL]] pentru a exporta simbolurile în kernel. De exemplu: ''​EXPORT_SYMBOL(task_info_remove_expired);''​. Macro-ul trebuie folosit pentru fiecare funcție, **după** definirea funcției+  - Se folosește ​macro-ul [[https://elixir.bootlin.com/​linux/​v4.15.7/​source/​include/​linux/​export.h#​L77|EXPORT_SYMBOL]] pentru a exporta simbolurile în kernel. De exemplu: ''​EXPORT_SYMBOL(task_info_remove_expired);''​. Macro-ul trebuie folosit pentru fiecare funcție, **după** definirea funcției.
-  - Anunțați modulul de test de prezența funcțiilor exportate. După ce ați compilat modulul de la ''​6-list-sync/'',​ analizaţi fişierul ''​6-list-sync/​Module.symvers'',​ după care copiaţi-l în ''​7-list-test/''​.+
   - Eliminați din modulul de la ''​6-list-sync/''​ secvența cu evitarea expirării unui element al listei (se bate cap în cap cu ce face testul).   - Eliminați din modulul de la ''​6-list-sync/''​ secvența cu evitarea expirării unui element al listei (se bate cap în cap cu ce face testul).
   - Compilați și încărcați modulul de la ''​6-list-sync/''​. Odată încărcat va expune funcțiile exportate și vor putea fi folosite de modulul de test. Puteţi verifica acest lucru căutând numele funcţiilor în ''/​proc/​kallsyms''​ înainte şi după încărcarea modulului.   - Compilați și încărcați modulul de la ''​6-list-sync/''​. Odată încărcat va expune funcțiile exportate și vor putea fi folosite de modulul de test. Puteţi verifica acest lucru căutând numele funcţiilor în ''/​proc/​kallsyms''​ înainte şi după încărcarea modulului.
so2/laboratoare/lab03/exercitii.1520189684.txt.gz · Last modified: 2018/03/04 20:54 by ionel.ghita
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