This shows you the differences between two versions of the page.
so2:laboratoare:lab03:exercitii [2018/03/04 21:31] ionel.ghita [3. [2.5p] Alocarea și lucrul cu memoria în kernel] |
so2:laboratoare:lab03:exercitii [2018/03/06 23:09] (current) anda.nicolae [2. [1p] Folosirea de operații blocante în context atomic] |
||
---|---|---|---|
Line 123: | 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 și copiați-l pe mașina virtuală, conform informațiilor de mai sus (''make build'' și ''make copy''). | - 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''. | ||
Line 146: | Line 146: | ||
- (**TODO 2**) Folosiți funcția completată anterior pentru a inițializa cele 4 structuri cu următoarele informații: | - (**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 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 176: | 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 201: | 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 213: | 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 229: | 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. |