Differences

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

Link to this comparison view

so2:laboratoare:lab11:exercitii [2017/03/05 19:32]
octavian.purdila [1. (**3 puncte**) Mapare de memorie fizic contiguă în user space]
so2:laboratoare:lab11:exercitii [2019/05/08 09:53] (current)
constantin.ghioc [2. [3p] Mapare de memorie virtual contiguă în user space]
Line 1: Line 1:
 ====== Laborator 11: Exerciții ====== ====== Laborator 11: Exerciții ======
  
-Pentru desfășurarea ​laboratorului pornim ​de la [[http://​elf.cs.pub.ro/so2/res/laboratoare/lab11-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 ​''​mjolnir''​):<code bash> + 
-student@mjolnir:​~$ cd so2/ +===== Pregătirea laboratorului ​===== 
-student@mjolnir:​~/​so2$ wget http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab11-tasks.zip + 
-student@mjolnir:​~/​so2$ unzip lab11-tasks.zip +Pentru rezolvarea laboratorului,​ vom lucra în același director din care pornim ​mașina virtuală (''​~/so2/linux/tools/labs''​). 
-student@mjolnir:​~/​so2tree lab11-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 ==== 
 + 
 +Pentru rezolvarea laboratorului trebuie sa activam suportul de netfilter din kernel. In meniul deschis cu ''​make menuconfig''​ 
 +activati optiunea ​''​Networking support/​Networking options/​Network packet filtering framework (Netfilter)''​
 + 
 +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 ''​lab11-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 ​''​mjolnir''​) ș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@mjolnir:​~/so2cp /​path/​to/​module.ko ~/​so2/​qemu-vm/​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-vm/''​ mașina virtuală QEMU folosind comanda<code bash> +<code bash> 
-student@mjolnir:​~/​so2/​qemu-vm$ ​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 ''​memory_mapping''​
-# rmmod module/module-name +</note> 
-</codeunde ''​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>​ <​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+Alt+t''​. ​Cele trei tab-uri de terminal îndeplinesc următoarele roluri: +Scheletul ​este generat în directorul ​''​tools/​labs/​skels''​. 
-  - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtaulă QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului. +</​note>​ 
-  - Î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-vm/​''​. + 
-  - Î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> +==== Compilarea modulelor ==== 
-student@mjolnir:~$ netcat ​-lup 6666+ 
 +Comanda ''​make build''​ compilează toate modulele din directorul ''​skels''​. 
 + 
 +<code bash> 
 +student@eg106:~/​so2/​linux/​tools/​labsmake 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 ./​memory_mapping/​vmmap ./​memory_mapping/​kmmap;​ do echo "obj-m += $i/" >> skels/​Kbuild;​ done 
 +...
 </​code>​ </​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>''​.
 +
 +<code bash>
 +root@qemux86:​~/​skels/​memory_mapping#​ ls
 +kmmap  test   vmmap
 +root@qemux86:​~/​skels/​memory_mapping#​ ls vmmap/
 +vmmap.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>​
 +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 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/''​ cu sursele nucleului unde putem folosi [[:​so2:​laboratoare:​lab01#​cscope|Vim și cscope]] pentru parcurgerea codului sursă.<​code>​
 +student@eg106-pc:​~$ netcat -lup 6666
 +</​code>​
 +
 +</​note>​
 +
 +===== 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>​ </​note>​
  
 ==== 1. [3p] Mapare de memorie fizic contiguă în user space ==== ==== 1. [3p] Mapare de memorie fizic contiguă în user space ====
-    * Utilizați scheletul de modul de kernel din directorul ''​lin/kmmap/''​ pentru a crea o mapare a memoriei driver-ului în user-space.+    * Utilizați scheletul de modul de kernel din directorul ''​kmmap/''​ pentru a crea o mapare a memoriei driver-ului în user-space.
       * Memoria driver-ului este alocată folosind ''​kmalloc''​.       * Memoria driver-ului este alocată folosind ''​kmalloc''​.
       * Completați zonele marcate cu ''​TODO 1''​.       * Completați zonele marcate cu ''​TODO 1''​.
       * Parcurgeți secțiunea [[:​so2:​laboratoare:​lab11#​Kernel-space|Maparea memoriei. Kernel-space]].       * Parcurgeți secțiunea [[:​so2:​laboratoare:​lab11#​Kernel-space|Maparea memoriei. Kernel-space]].
-    * Alocați, în funcția de inițializare a modulului, o zonă de memorie de ''​NPAGES+1''​ pagini folosind ''​kmalloc''​. +    * Alocați, în funcția de inițializare a modulului, o zonă de memorie de ''​NPAGES+2''​ pagini folosind ''​kmalloc''​. 
-      * O pagină în kernel are dimensiunea [[http://lxr.free-electrons.com/​source/​arch/​x86/​include/​asm/​page_types.h?v=3.13#​L9|PAGE_SIZE]].+      * O pagină în kernel are dimensiunea [[http://elixir.free-electrons.com/linux/v4.9/​source/​arch/​x86/​include/​asm/​page_types.h#​L9|PAGE_SIZE]].
        * Zona alocată din spațiul kernel este indicată de ''​kmalloc_area''​.        * Zona alocată din spațiul kernel este indicată de ''​kmalloc_area''​.
-       * Dimensiunea ''​NPAGES+1''​ este necesară pentru aliniere.+       * Dimensiunea ''​NPAGES+2''​ este necesară pentru aliniere.
     * Adresa ​ ''​kmalloc_ptr''​ (variabilă globală) obținută în urma apelului ''​kmalloc''​ trebuie aliniată la adresa unei pagini.     * Adresa ​ ''​kmalloc_ptr''​ (variabilă globală) obținută în urma apelului ''​kmalloc''​ trebuie aliniată la adresa unei pagini.
       * Pentru aceasta, va trebui să alocați o pagină în plus față de numărul de pagini necesare și să folosiți formula:<​code>​       * Pentru aceasta, va trebui să alocați o pagină în plus față de numărul de pagini necesare și să folosiți formula:<​code>​
Line 43: Line 109:
 </​code>​ </​code>​
     * Activați/​dezactivați bitul ''​PG_reserved''​ al fiecărei pagini cu ajutorul funcțiilor ''​SetPageReserved''​ (în funcția de inițializare a modulului), respectiv ''​ClearPageReserved''​ (în funcția de ieșire a modulului).     * Activați/​dezactivați bitul ''​PG_reserved''​ al fiecărei pagini cu ajutorul funcțiilor ''​SetPageReserved''​ (în funcția de inițializare a modulului), respectiv ''​ClearPageReserved''​ (în funcția de ieșire a modulului).
-      * Folosiți [[http://lxr.free-electrons.com/​source/​tools/virtio/linux/kernel.h?v=3.13#L35|virt_to_page]] pentru a traduce paginile virtuale în pagini fizice folosite de funcțiile ''​SetPageReserved''​ și ''​ClearPageReserved''​.+      * Folosiți [[http://elixir.free-electrons.com/linux/v4.9/source/arch/x86/include/asm/page.h#L68|virt_to_page]] pentru a traduce paginile virtuale în pagini fizice folosite de funcțiile ''​SetPageReserved''​ și ''​ClearPageReserved''​.
     * Pentru verificare (folosind testul indicat mai jos) completați primii 4 octeți din fiecare pagină alocată cu valorile, respectiv, ''​0xaa'',''​0xbb'',''​0xcc'',''​0xdd''​.     * Pentru verificare (folosind testul indicat mai jos) completați primii 4 octeți din fiecare pagină alocată cu valorile, respectiv, ''​0xaa'',''​0xbb'',''​0xcc'',''​0xdd''​.
     * Implementați funcția ''​mmap''​ pentru driver.     * Implementați funcția ''​mmap''​ pentru driver.
-      * Pentru mapare folosiți funcția [[http://lxr.free-electrons.com/​source/​mm/​memory.c?v=3.13#L2319|remap_pfn_range]]. +      * Pentru mapare folosiți funcția [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​memory.c#​L1760|remap_pfn_range]]. 
-    * Al treilea argument primit de [[http://lxr.free-electrons.com/​source/​mm/​memory.c?v=3.13#L2319|remap_pfn_range]] este un număr de pagină fizică (''​pfn''​ -- //page frame number//​). +    * Al treilea argument primit de [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​memory.c#​L1760|remap_pfn_range]] este un număr de pagină fizică (''​pfn''​ -- //page frame number//​). 
-      * Pentru conversia din adresă kernel virtuală (adică ''​kmalloc_area''​) în adresă fizică utilizați [[http://lxr.free-electrons.com/​source/​arch/​x86/​include/​asm/​io.h?v=3.13#L98|virt_to_phys]]. +      * Pentru conversia din adresă kernel virtuală (adică ''​kmalloc_area''​) în adresă fizică utilizați [[http://elixir.free-electrons.com/linux/v4.9/​source/​arch/​x86/​include/​asm/​io.h#​L118|virt_to_phys]]. 
-      * Shiftați rezultatul cu [[http://lxr.free-electrons.com/​source/​arch/​x86/​include/​asm/​page_types.h?v=3.13#L7|PAGE_SHIFT]] biți pentru a obține ''​pfn''​.+      * Shiftați rezultatul cu [[http://elixir.free-electrons.com/linux/v4.9/​source/​arch/​x86/​include/​asm/​page_types.h#​L8|PAGE_SHIFT]] biți pentru a obține ''​pfn''​.
     * Încărcați modulul în kernel.     * Încărcați modulul în kernel.
-    * Pentru testare utilizați testul din directorul ''​lin/test''​. +    * Pentru testare utilizați testul din directorul ''​test/''​.
-      * Compilați testul folosind comanda ''​make''​.+
       * Rulați testul folosind comanda ''​./​mmap-test''​.       * Rulați testul folosind comanda ''​./​mmap-test''​.
       * Dacă totul merge bine testul va afișa mesaje ''​matched''​.       * Dacă totul merge bine testul va afișa mesaje ''​matched''​.
     * Descărcați modulul din kernel.     * Descărcați modulul din kernel.
  
-==== 2. (**3 puncte**) ​Mapare de memorie ​virtual contiguă în user space ==== +==== 2. [3p] Mapare de memorie ​fizic discontiguă în user space ==== 
-    * Utilizați scheletul de modul de kernel din directorul ''​lin/vmmap/''​ pentru a crea o mapare a memoriei driver-ului în user-space.+    * Utilizați scheletul de modul de kernel din directorul ''​vmmap/''​ pentru a crea o mapare a memoriei driver-ului în user-space.
       * Memoria driver-ului este alocată folosind ''​vmalloc''​.       * Memoria driver-ului este alocată folosind ''​vmalloc''​.
-      * Completați zonele marcate cu ''​TODO ​2''​.+      * Completați zonele marcate cu ''​TODO ​1''​.
       * Parcurgeți secțiunea [[:​so2:​laboratoare:​lab11#​Kernel-space|Maparea memoriei. Kernel-space]] din laborator.       * Parcurgeți secțiunea [[:​so2:​laboratoare:​lab11#​Kernel-space|Maparea memoriei. Kernel-space]] din laborator.
     * Alocați ​ o zonă de memorie de ''​NPAGES''​ pagini în funcția de inițializare a modulului folosind ''​vmalloc''​.     * Alocați ​ o zonă de memorie de ''​NPAGES''​ pagini în funcția de inițializare a modulului folosind ''​vmalloc''​.
Line 66: Line 131:
       * Alocarea cu ''​vmalloc''​ întoarce adrese aliniate la dimensiunea paginii; nu este nevoie de operații suplimentare.       * Alocarea cu ''​vmalloc''​ întoarce adrese aliniate la dimensiunea paginii; nu este nevoie de operații suplimentare.
     * Activați/​dezactivați bitul ''​PG_reserved''​ al fiecărei pagini cu ajutorul funcțiilor ''​SetPageReserved''​ (în funcția de inițializare a modulului), respectiv ''​ClearPageReserved''​ (în funcția de ieșire a modulului);     * Activați/​dezactivați bitul ''​PG_reserved''​ al fiecărei pagini cu ajutorul funcțiilor ''​SetPageReserved''​ (în funcția de inițializare a modulului), respectiv ''​ClearPageReserved''​ (în funcția de ieșire a modulului);
-      * Folosiți [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=3.13#L222|vmalloc_to_page]] pentru a traduce paginile virtuale în pagini fizice folosite de funcțiile ''​SetPageReserved''​ și ''​ClearPageReserved''​.+      * Folosiți [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​vmalloc.c#​L235|vmalloc_to_page]] pentru a traduce paginile virtuale în pagini fizice folosite de funcțiile ''​SetPageReserved''​ și ''​ClearPageReserved''​.
     * Pentru verificare folosind testul, completați primii 4 octeți din fiecare pagină alocată cu următoarele valori: ''​0xaa'',''​0xbb'',''​0xcc'',''​0xdd''​.     * Pentru verificare folosind testul, completați primii 4 octeți din fiecare pagină alocată cu următoarele valori: ''​0xaa'',''​0xbb'',''​0xcc'',''​0xdd''​.
     * Implementați funcția ''​mmap''​ pentru driver.     * Implementați funcția ''​mmap''​ pentru driver.
-    * Pentru conversia din adresă kernel virtuală în adresă fizică utilizați [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=3.13#L256|vmalloc_to_pfn]]. +    * Pentru conversia din adresă kernel virtuală în adresă fizică utilizați [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​vmalloc.c#​L269|vmalloc_to_pfn]]. 
-      * [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=3.13#L256|vmalloc_to_pfn]] întoarce un index de pagină (//page frame number//), astfel că **nu** este nevoie de shift la dreapta.+      * [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​vmalloc.c#​L269|vmalloc_to_pfn]] întoarce un index de pagină (//page frame number//), astfel că **nu** este nevoie de shift la dreapta.
     * Paginile alocate cu ''​vmalloc''​ nu sunt fizic contigue.     * Paginile alocate cu ''​vmalloc''​ nu sunt fizic contigue.
-      * Apelați [[http://lxr.free-electrons.com/​source/​mm/​memory.c?v=3.13#L2319|remap_pfn_range]] pentru **fiecare** pagină virtuală.+      * Apelați [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​memory.c#​L1760|remap_pfn_range]] pentru **fiecare** pagină virtuală.
         * Adică veți avea nevoie de un ciclu for și veți incrementa adresa virtuală kernel (''​vmalloc_area''​) cu câte o pagină și veți obține pentru fiecare adresă virtuală astfel obținută ''​pfn''​-ul. ​         * Adică veți avea nevoie de un ciclu for și veți incrementa adresa virtuală kernel (''​vmalloc_area''​) cu câte o pagină și veți obține pentru fiecare adresă virtuală astfel obținută ''​pfn''​-ul. ​
       * Folosiți ''​vmalloc_area_ptr''​ pentru parcurgerea spațiului virtual din kernel space.       * Folosiți ''​vmalloc_area_ptr''​ pentru parcurgerea spațiului virtual din kernel space.
         * Nu modificați variabila globală ''​vmalloc_area''​.         * Nu modificați variabila globală ''​vmalloc_area''​.
-    * Argumentul pentru [[http://lxr.free-electrons.com/​source/​mm/​vmalloc.c?v=3.13#L256|vmalloc_to_pfn]] este o adresă virtuală din kernel space. +    * Argumentul pentru [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​vmalloc.c#​L269|vmalloc_to_pfn]] este o adresă virtuală din kernel space. 
-      * Al doilea argument pentru [[http://lxr.free-electrons.com/​source/​mm/​memory.c?v=3.13#L2319|remap_pfn_range]] este o adresă virtuală din cadrul unui VMA. +      * Al doilea argument pentru [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​memory.c#​L1760|remap_pfn_range]] este o adresă virtuală din cadrul unui VMA. 
-      * Al treilea argument pentru [[http://lxr.free-electrons.com/​source/​mm/​memory.c?v=3.13#L2319|remap_pfn_range]] este pfn-ul paginii virtuale din kernel-space care se dorește remapată.+      * Al treilea argument pentru [[http://elixir.free-electrons.com/linux/v4.9/​source/​mm/​memory.c#​L1760|remap_pfn_range]] este pfn-ul paginii virtuale din kernel-space care se dorește remapată.
     * Încărcați modulul în kernel.     * Încărcați modulul în kernel.
-    * Pentru testare utilizați testul din directorul ''​lin/test''​. +    * Pentru testare utilizați testul din directorul ''​test/''​.
-      * Compilați testul folosind comanda ''​make''​.+
       * Rulați testul folosind comanda ''​./​mmap-test''​.       * Rulați testul folosind comanda ''​./​mmap-test''​.
       * Dacă totul merge bine testul va afișa mesaje ''​matched''​.       * Dacă totul merge bine testul va afișa mesaje ''​matched''​.
Line 87: Line 151:
  
  
-==== 3. (**2 puncte**) ​Operații de read/write în memoria mapată ====+==== 3. [2p] Operații de read/write în memoria mapată ====
     * Modificați **unul dintre** modulele anterioare astfel încât să permiteți operații read/write pe dispozitiv.     * Modificați **unul dintre** modulele anterioare astfel încât să permiteți operații read/write pe dispozitiv.
       * E vorba de un exercițiu didactic ca să vedem că același spațiu poate fi folosit și cu apel-ul ''​mmap''​ și cu apeluri de tipul ''​read''​ și ''​write''​.       * E vorba de un exercițiu didactic ca să vedem că același spațiu poate fi folosit și cu apel-ul ''​mmap''​ și cu apeluri de tipul ''​read''​ și ''​write''​.
       * Operațiile de citire și scriere vor acționa chiar asupra zonei de memorie alocate.       * Operațiile de citire și scriere vor acționa chiar asupra zonei de memorie alocate.
-      * Completați zonele marcate cu ''​TODO ​3''​.+      * Completați zonele marcate cu ''​TODO ​2''​.
       * Revedeți [[so2:​laboratoare:​lab04 | Laboratorul 4]]       * Revedeți [[so2:​laboratoare:​lab04 | Laboratorul 4]]
     * **Ignorați** parametrul ''​offset''​ trimis operației de read/write.     * **Ignorați** parametrul ''​offset''​ trimis operației de read/write.
-    * Pentru testare utilizați testul din directorul ''​lin/test''​. +    * Pentru testare utilizați testul din directorul ''​test/''​. 
-      * Definiți macroul ​''​TASK_3'' ​în ''​mmap_test.c''​ +      * Rulați testul folosind comanda ​''​./mmap-test 3''​. 
-  - (**3 puncte**) ​Afișare memorie mapată în ''​procfs''​+ 
 + 
 +==== 4. [3p] Afișare memorie mapată în ''​procfs'' ​====
     * Folosind **unul dintre** modulele anterioare, creați un fișier ''​procfs''​ în care să afișați totalul memoriei mapate de procesul apelant.     * Folosind **unul dintre** modulele anterioare, creați un fișier ''​procfs''​ în care să afișați totalul memoriei mapate de procesul apelant.
-      * Completați zonele marcate cu ''​TODO ​4''​. +      * Completați zonele marcate cu ''​TODO ​3''​. 
-    * Creați o intrare nouă în ''​procfs''​ (''​PROC_ENTRY_NAME'',​ definit în ''​mmap-test.h''​) care va afișa totalul memoriei mapate de procesul care a apelat read-ul pe acel fișier. Folosiți apelul [[http://lxr.free-electrons.com/​source/​include/​linux/​proc_fs.h?v=3.13#​L30|proc_create]].+    * Creați o intrare nouă în ''​procfs''​ (''​PROC_ENTRY_NAME'',​ definit în ''​mmap-test.h''​) care va afișa totalul memoriei mapate de procesul care a apelat read-ul pe acel fișier. Folosiți apelul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​proc_fs.h#​L30|proc_create]].
         * Pentru parametrul ''​mode''​ folosiți ''​0'',​ iar pentru parametrul ''​parent''​ folosiți ''​NULL''​.         * Pentru parametrul ''​mode''​ folosiți ''​0'',​ iar pentru parametrul ''​parent''​ folosiți ''​NULL''​.
         * Operațiile sunt descrise în structura ''​my_proc_file_ops''​.         * Operațiile sunt descrise în structura ''​my_proc_file_ops''​.
-    * În funcția de ieșire a modulului ștergeți intrarea ''​PROC_ENTRY_NAME''​ folosind [[http://lxr.free-electrons.com/​source/​fs/​proc/​generic.c?v=3.13#L484|remove_proc_entry]]. +    * În funcția de ieșire a modulului ștergeți intrarea ''​PROC_ENTRY_NAME''​ folosind [[http://elixir.free-electrons.com/linux/v4.9/​source/​fs/​proc/​generic.c#​L548|remove_proc_entry]]. 
-    * O utilizare (complexă) și descriere a interfeței [[http://lxr.free-electrons.com/​source/​include/​linux/​seq_file.h?v=3.13#L18|seq_file]] se găsește aici [[http://​tldp.org/​LDP/​lkmpg/​2.6/​html/​x861.html | acest exemplu]].+    * O utilizare (complexă) și descriere a interfeței [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​seq_file.h#​L15|seq_file]] se găsește aici [[http://​tldp.org/​LDP/​lkmpg/​2.6/​html/​x861.html | acest exemplu]].
     * Pentru acest exercițiu este suficientă doar o simplă utilizare a interfeței,​ descrisă [[http://​lwn.net/​Articles/​22355/​ | aici]]. Căutați **extra-simple**. ​     * Pentru acest exercițiu este suficientă doar o simplă utilizare a interfeței,​ descrisă [[http://​lwn.net/​Articles/​22355/​ | aici]]. Căutați **extra-simple**. ​
-<note important>​ 
-Atenție, funcția ''​create_proc_entry''​ nu mai este disponibilă în versiunea 3.13 a kernelului. Va trebui să folosiţi funcţia [[http://​lxr.free-electrons.com/​source/​include/​linux/​proc_fs.h?​v=3.13#​L30|proc_create]],​ care primeşte ca parametru suplimentar un pointer către operaţiile de tip fişier ce vor fi folosite pentru intrarea procfs. 
-</​note>​ 
     * În funcția de afișare ''​my_seq_show''​ va trebui să:     * În funcția de afișare ''​my_seq_show''​ va trebui să:
-      * Obțineți structura [[http://lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?v=3.13#L344|mm_struct]] a procesului curent folosind funcția [[http://lxr.free-electrons.com/​source/​kernel/fork.c?v=3.13#L656|get_task_mm]].+      * Obțineți structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​mm_types.h#​L396|mm_struct]] a procesului curent folosind funcția [[http://elixir.free-electrons.com/linux/v4.9/source/include/linux/sched.h#L2912|get_task_mm]].
         * Procesul curent este indicat de variabila ''​current''​ de tip ''​struct task_struct *''​.         * Procesul curent este indicat de variabila ''​current''​ de tip ''​struct task_struct *''​.
-      * Iterați prin toată lista de structuri [[http://lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?v=3.13#L240|vm_area_struct]] asociată procesului.+      * Iterați prin toată lista de structuri [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​mm_types.h#​L300|vm_area_struct]] asociată procesului.
         * Folosiți variabila ''​vma_iterator''​.         * Folosiți variabila ''​vma_iterator''​.
         * Porniți de la ''​%%mm->​mmap%%''​.         * Porniți de la ''​%%mm->​mmap%%''​.
-        * Folosiți câmpul ''​vm_next''​ al [[http://lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?v=3.13#L240|vm_area_struct]] pentru a parcurge lista de zone de memorie (vma-uri -- //virtual memory areas//).+        * Folosiți câmpul ''​vm_next''​ al [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​mm_types.h#​L300|vm_area_struct]] pentru a parcurge lista de zone de memorie (vma-uri -- //virtual memory areas//).
         * Opriți-vă când ajungeți la ''​NULL''​.         * Opriți-vă când ajungeți la ''​NULL''​.
       * Vă bazați pe ''​vm_start''​ și ''​vm_end''​ pentru fiecare structură pentru a deduce dimensiunea totală.       * Vă bazați pe ''​vm_start''​ și ''​vm_end''​ pentru fiecare structură pentru a deduce dimensiunea totală.
       * Afișați, folosind ''​%%printk("​%lx %lx\n, ... )%%'',​ ''​vm_start''​ și ''​vm_end''​ pentru fiecare structură ''​vm_area_struct''​.       * Afișați, folosind ''​%%printk("​%lx %lx\n, ... )%%'',​ ''​vm_start''​ și ''​vm_end''​ pentru fiecare structură ''​vm_area_struct''​.
-      * Pentru a "​elibera"​ structura [[http://lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?v=3.13#L344|mm_struct]],​ decrementați reference counter-ul structurii folosind [[http://lxr.free-electrons.com/​source/​kernel/​fork.c#​L691|mmput]]. +      * Pentru a "​elibera"​ structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​mm_types.h#​L396|mm_struct]],​ decrementați reference counter-ul structurii folosind [[http://elixir.free-electrons.com/linux/v4.9/​source/​kernel/​fork.c#​L877|mmput]]. 
-      * Folosiți [[http://lxr.free-electrons.com/​source/​fs/​seq_file.c#​L410|seq_printf]] pentru a scrie în fișier.+      * Folosiți [[http://elixir.free-electrons.com/linux/v4.9/​source/​fs/​seq_file.c#​L413|seq_printf]] pentru a scrie în fișier.
         * Afișați **doar** domensiunea totală, fără alt mesaj/șir de caractere. **Nu** afișați nici măcar newline (''​\n''​).         * Afișați **doar** domensiunea totală, fără alt mesaj/șir de caractere. **Nu** afișați nici măcar newline (''​\n''​).
-    * În funcția ''​my_seq_open''​ înregistrați funcția de afișare (''​my_seq_show''​) folosind apelul [[http://lxr.free-electrons.com/​source/​fs/​seq_file.c?v=3.13#L584|single_open]].+    * În funcția ''​my_seq_open''​ înregistrați funcția de afișare (''​my_seq_show''​) folosind apelul [[http://elixir.free-electrons.com/linux/v4.9/​source/​fs/​seq_file.c#​L566|single_open]].
       * Ca al treilea argument pentru ''​single_open''​ puteți folosi ''​NULL''​.       * Ca al treilea argument pentru ''​single_open''​ puteți folosi ''​NULL''​.
-    * Pentru testare utilizați testul din directorul ''​lin/test''​. +    * Pentru testare utilizați testul din directorul ''​test/''​. 
-      * Definiți ''​TASK_4''​ în ''​mmap_test.c''​+      * Rulați testul folosind comanda ​''​./mmap-test 4''​.
-      * Rulați testul.+
         * Testul așteaptă un timp (are o instrucțiune ''​sleep''​ internă).         * Testul așteaptă un timp (are o instrucțiune ''​sleep''​ internă).
         * Cât timp testul așteaptă, folosiți în altă consolă comanda ''​pmap''​ pentru a vedea mapările testului și a le compara cu cele obținute.         * Cât timp testul așteaptă, folosiți în altă consolă comanda ''​pmap''​ pentru a vedea mapările testului și a le compara cu cele obținute.
           * Puteți folosi comanda în forma<​code>​           * Puteți folosi comanda în forma<​code>​
-pmap $(pidof mmap-test)+cat /proc/$(pidof mmap-test)/maps
 </​code>​ </​code>​
 <​note>​ <​note>​
-          * Pentru a accesa altă consolă ​în mașina virtuală folosiți combinația de taste ''​Alt+F2''​.+          * Pentru a accesa altă consolă ​porniți ​mașina virtuală ​în mod grafic și folosiți combinația de taste ''​Alt+F2''​.
           * Pentru a reveni înapoi în prima consolă folosiți combinația de taste ''​Alt+F1''​.           * Pentru a reveni înapoi în prima consolă folosiți combinația de taste ''​Alt+F1''​.
 </​note>​ </​note>​
so2/laboratoare/lab11/exercitii.1488735152.txt.gz · Last modified: 2017/03/05 19:32 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