Differences

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

Link to this comparison view

so2:laboratoare:lab11 [2014/05/02 10:48]
daniel.baluta [Laborator 12 - Maparea memoriei]
so2:laboratoare:lab11 [2017/05/07 19:19] (current)
octavian.purdila update lxr links to use 4.9
Line 18: Line 18:
 ===== Materiale ajutătoare ===== ===== Materiale ajutătoare =====
  
-  *[[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab12-slides.pdf|Slide-uri de suport pentru laborator]]+  *[[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab11-slides.pdf|Slide-uri de suport pentru laborator]]
   *[[http://​elf.cs.pub.ro/​so2/​res/​extra/​so2_reference.pdf|SO2 Reference Card]]   *[[http://​elf.cs.pub.ro/​so2/​res/​extra/​so2_reference.pdf|SO2 Reference Card]]
  
Line 25: Line 25:
 În kernel-ul Linux există posibilitatea mapării unui spaţiu de adresă kernel într-un spaţiu de adresă utilizator. În acest fel se elimină overhead-ul datorat copierii informaţiei din user-space în kernel-space (şi invers). Acest lucru poate fi realizat prin intermediul unui device driver şi a interfeţei dispozitiv (''/​dev''​) a acestuia în user-space. În kernel-ul Linux există posibilitatea mapării unui spaţiu de adresă kernel într-un spaţiu de adresă utilizator. În acest fel se elimină overhead-ul datorat copierii informaţiei din user-space în kernel-space (şi invers). Acest lucru poate fi realizat prin intermediul unui device driver şi a interfeţei dispozitiv (''/​dev''​) a acestuia în user-space.
  
-Această facilitate poate fi folosită prin completarea operaţiei [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​fs.h#​L1497|mmap]] din structura [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​fs.h#​L1485|struct file_operations]] asociată dispozitivului şi utilizând apelul ''​mmap''​ din user-space.+Această facilitate poate fi folosită prin completarea operaţiei [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​fs.h#​L1708|mmap]] din structura [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​fs.h#​L1696|struct file_operations]] asociată dispozitivului şi utilizând apelul ''​mmap''​ din user-space.
  
 ==== Structuri de lucru cu memoria ==== ==== Structuri de lucru cu memoria ====
Line 31: Line 31:
 Înainte de a discuta despre mecanismul de memory-mapping peste un dispozitiv, vom prezenta câteva din structurile de bază legate de subsistemul de management al memoriei în kernel-ul Linux. Înainte de a discuta despre mecanismul de memory-mapping peste un dispozitiv, vom prezenta câteva din structurile de bază legate de subsistemul de management al memoriei în kernel-ul Linux.
  
-Cateva din structurile importante sunt: [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L34|struct page]], [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L130|struct vm_area_struct]] şi [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L222|struct mm_struct]].+Cateva din structurile importante sunt: [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L45|struct page]], [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L300|struct vm_area_struct]] şi [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L396|struct mm_struct]].
  
 ==== Structura ''​page''​ ==== ==== Structura ''​page''​ ====
  
-Structura [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L34|struct page]] este utilizată pentru a încorpora informaţii despre toate paginile fizice din sistem. Kernel-ul deţine o structură ''​struct page''​ pentru toate paginile din sistem+Structura [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L45|struct page]] este utilizată pentru a încorpora informaţii despre toate paginile fizice din sistem. Kernel-ul deţine o structură ''​struct page''​ pentru toate paginile din sistem.
- +
-Printre câmpurile importante ale acestei structuri amintim: +
-  *[[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​mm_types.h#​L37|_count]],​ contorul de utilizare al paginii; când acesta devine 0 pagina este adăugată la lista de pagini libere; +
-  *[[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​mm_types.h#​L89|virtual]],​ adresa virtuală în spaţiul kernel asociată acestei pagini fizice; paginile din ''​ZONE_DMA''​ sau ''​ZONE_NORMAL''​ sunt tot timpul mapate; paginile din ''​ZONE_HIHGMEM''​ nu sunt tot timpul mapate; Aceste constante se găsesc în [[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​mmzone.h#​L191|enum zone_type]] +
-  *[[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​mm_types.h#​L35|flags]],​ un set de flag-uri care descriu atributele paginii.+
  
 Există numeroase funcţii care interacţionează cu această structură: Există numeroase funcţii care interacţionează cu această structură:
-  *[[http://lxr.linux.no/#linux+v2.6.35/​arch/​x86/​include/​asm/​page.h#​L51|virt_to_page]] întoarce pagina asociată unei adrese virtuale; +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​arch/​x86/​include/​asm/​page.h#​L68|virt_to_page]] întoarce pagina asociată unei adrese virtuale; 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​asm-generic/​memory_model.h#​L73|pfn_to_page]] întoarce pagina asociată pentru un număr de pagină (''​page frame number''​);​ +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​asm-generic/​memory_model.h#​L81|pfn_to_page]] întoarce pagina asociată pentru un număr de pagină (''​page frame number''​);​ 
-  *[[http://lxr.linux.no/#linux+v2.6.35/mm/highmem.c#L331|page_address]] întoarce adresa virtuală a paginii transmise ca parametru.+  *[[http://elixir.free-electrons.com/linux/v4.9/source/include/​linux/​mm.h#L1013|page_address]] întoarce adresa virtuală a paginii transmise ca parametru.
  
 ==== Structura ''​vm_area_struct''​ ==== ==== Structura ''​vm_area_struct''​ ====
  
-Structura [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L130|struct vm_area_struct]] deţine informaţii despre o zonă de memorie virtuală contiguă. Zonele de memorie ale unui proces pot fi vizualizate inspectând ''​procfs'':​+Structura [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L300|struct vm_area_struct]] deţine informaţii despre o zonă de memorie virtuală contiguă. Zonele de memorie ale unui proces pot fi vizualizate inspectând ''​procfs'':​
  
 <code bash> <code bash>
Line 69: Line 64:
  
 O structură ''​vm_area_struct''​ este creată la fiecare apel ''​mmap''​ din user-space. Un driver care are suport pentru operaţia de ''​mmap''​ trebuie să completeze şi să iniţializeze structura ''​vm_area_struct''​ asociată. Cele mai importante câmpuri ale acestei structuri sunt: O structură ''​vm_area_struct''​ este creată la fiecare apel ''​mmap''​ din user-space. Un driver care are suport pentru operaţia de ''​mmap''​ trebuie să completeze şi să iniţializeze structura ''​vm_area_struct''​ asociată. Cele mai importante câmpuri ale acestei structuri sunt:
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L132|vm_start]],​ [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L133|vm_end]], reprezintă începutul, respectiv, sfârşitul zonei de memorie (aceste câmpuri apar şi in ''/​proc/​*/​maps''​);​ +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L303|vm_start]],​ [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L304|vm_end]], reprezintă începutul, respectiv, sfârşitul zonei de memorie (aceste câmpuri apar şi in ''/​proc/​*/​maps''​);​ 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L176|vm_file]], pointer-ul la structura de fişier asociată (dacă există); +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L351|vm_file]], pointer-ul la structura de fişier asociată (dacă există); 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L174|vm_pgoff]],​ offset-ul zonei în cadrul fişierului;​ +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L349|vm_pgoff]],​ offset-ul zonei în cadrul fişierului;​ 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L140|vm_flags]],​ un set de indicatori;​ +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L324|vm_flags]],​ un set de indicatori;​ 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L171|vm_ops]], un set de funcţii de lucru asupra acestei zone. +  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L346|vm_ops]], un set de funcţii de lucru asupra acestei zone. 
-  *[[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L137|vm_next, vm_prev]], ''​vm_area''​-urile aferente unui proces sunt înlănțuite printr-o listă+  *[[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L308|vm_next]][[http://​elixir.free-electrons.com/​linux/​v4.9/​source/​include/​linux/​mm_types.h#​L308|vm_prev]], ''​vm_area''​-urile aferente unui proces sunt înlănțuite printr-o listă
  
 ==== Structura ''​mm_struct''​ ==== ==== Structura ''​mm_struct''​ ====
  
-Structura [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​mm_types.h#​L222|struct mm_struct]] înglobează toate zonele de memorie asociate unui proces; folosind câmpul ''​mm''​ al structurii [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​sched.h#​L1173|task_struct]] se poate obţine structura ''​mm_struct''​ asociată procesului curent.+Structura [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​mm_types.h#​L396|struct mm_struct]] înglobează toate zonele de memorie asociate unui proces; folosind câmpul ''​mm''​ al structurii [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​sched.h#​L1475|task_struct]] se poate obţine structura ''​mm_struct''​ asociată procesului curent.
  
 ==== Maparea memoriei ==== ==== Maparea memoriei ====
Line 84: Line 79:
 Maparea memoriei (''​memory mapping''​) este una dintre cele mai interesante caracteristici ale unui sistem Unix. Din punct de vedere al unui driver, facilitatea de ''​memory-mapping''​ permite accesul direct al memoriei unui dispozitiv din user-space. Maparea memoriei (''​memory mapping''​) este una dintre cele mai interesante caracteristici ale unui sistem Unix. Din punct de vedere al unui driver, facilitatea de ''​memory-mapping''​ permite accesul direct al memoriei unui dispozitiv din user-space.
  
-Pentru a asocia unui driver o operaţie ''​mmap'',​ trebuie utilizat câmpul [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​fs.h#​L1497|mmap]] din structura [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​fs.h#​L1485|struct file_operations]] asociată dispozitivului. Metoda astfel asociată este utilizată în cazul unui apel ''​mmap''​ din user-space.+Pentru a asocia unui driver o operaţie ''​mmap'',​ trebuie utilizat câmpul [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​fs.h#​L1708|mmap]] din structura [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​fs.h#​L1696|struct file_operations]] asociată dispozitivului. Metoda astfel asociată este utilizată în cazul unui apel ''​mmap''​ din user-space.
  
 ==== User-space ==== ==== User-space ====
Line 103: Line 98:
 </​code>​ </​code>​
  
-Câmpul ''​filp''​ reprezintă pointer-ul la structura [[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​fs.h#​L914| struct file]] creată o dată cu deschiderea dispozitivului din user-space. Câmpul ''​vma''​ este utilizat pentru a indica spaţiul de adresă virtual folosit pentru maparea memoriei dispozitivului. Un driver va putea aloca memorie (folosind ''​kmalloc''​ sau ''​vmalloc''​),​ urmând ca un set de procese să poată mapa în spaţiul propriu de adresă adresa alocată în driver.+Câmpul ''​filp''​ reprezintă pointer-ul la structura [[http://​lxr.free-electrons.com/source/​include/​linux/​fs.h#​L866|struct file]] creată o dată cu deschiderea dispozitivului din user-space. Câmpul ''​vma''​ este utilizat pentru a indica spaţiul de adresă virtual folosit pentru maparea memoriei dispozitivului. Un driver va putea aloca memorie (folosind ''​kmalloc''​ sau ''​vmalloc''​),​ urmând ca un set de procese să poată mapa în spaţiul propriu de adresă adresa alocată în driver.
  
 ===== ''​remap_pfn_range''​ ===== ===== ''​remap_pfn_range''​ =====
  
-Pentru maparea unui spaţiu de memorie fizică în spaţiul virtual utilizator, reprezentat de structura ''​struct vm_area_struct'',​ se folosește apelul [[http://lxr.linux.no/#linux+v2.6.35/mm/memory.c#L1851| remap_pfn_range]]. Acesta va mapa un spaţiu de adresă fizic contiguu în spaţiul virtual reprezentat de ''​struct vm_area_struct'':​+Pentru maparea unui spaţiu de memorie fizică în spaţiul virtual utilizator, reprezentat de structura ''​struct vm_area_struct'',​ se folosește apelul [[http://elixir.free-electrons.com/linux/v4.9/source/include/​linux/​mm.h#L2193|remap_pfn_range]]. Acesta va mapa un spaţiu de adresă fizic contiguu în spaţiul virtual reprezentat de ''​struct vm_area_struct'':​
 <code C> <code C>
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
Line 116: Line 111:
   *''​vma'',​ spaţiul de memorie virtuală în cadrul căruia se face maparea;   *''​vma'',​ spaţiul de memorie virtuală în cadrul căruia se face maparea;
   *''​addr'',​ spaţiul virtual de adresă de unde se începe remaparea; se vor construi tabele de pagini pentru spaţiul virtual de adresă cuprins intre ''​addr''​ şi ''​addr + size'';​   *''​addr'',​ spaţiul virtual de adresă de unde se începe remaparea; se vor construi tabele de pagini pentru spaţiul virtual de adresă cuprins intre ''​addr''​ şi ''​addr + size'';​
-  *''​pfn'',​ numărul paginii fizice (''​page frame number''​) în care se mapează adresa virtuală; de obicei acesta se obţine prin shifting-ul adresei fizice [[http://lxr.linux.no/#linux+v2.6.35/​arch/​x86/​include/​asm/​page_types.h#​L7| PAGE_SHIFT]] biţi la dreapta+  *''​pfn'',​ numărul paginii fizice (''​page frame number''​) în care se mapează adresa virtuală; de obicei acesta se obţine prin shifting-ul adresei fizice [[http://elixir.free-electrons.com/linux/v4.9/source/​arch/​x86/​include/​asm/​page_types.h#​L8|PAGE_SHIFT]] biţi la dreapta
   *''​size'',​ dimensiunea (în octeţi) a spaţiului de memorie care va fi remapat;   *''​size'',​ dimensiunea (în octeţi) a spaţiului de memorie care va fi remapat;
   *''​prot'',​ caracteristicile de protecţie pentru noul spaţiu de adresă.   *''​prot'',​ caracteristicile de protecţie pentru noul spaţiu de adresă.
Line 136: Line 131:
 În exemplul de mai sus se realizează o mapare a zonei fizice începând de la numărul de pagină ''​phys_pgoff''​ în întreg spaţiul virtual de adresă reprezentat de ''​vma''​. În exemplul de mai sus se realizează o mapare a zonei fizice începând de la numărul de pagină ''​phys_pgoff''​ în întreg spaţiul virtual de adresă reprezentat de ''​vma''​.
  
-Două funcţii care sunt utile sunt cele de translatare a unei adrese virtuale din spaţiul kernel în adrese fizice. Acestea sunt [[http://lxr.linux.no/#linux+v2.6.35/​arch/​x86/​include/​asm/​io.h#​L118| virt_to_phys]] pentru adrese alocate folosind ''​kmalloc''​ şi [[http://lxr.linux.no/#linux+v2.6.35/mm/vmalloc.c#L237| vmalloc_to_pfn]] pentru adrese alocate folosind ''​vmalloc''​.+Două funcţii care sunt utile sunt cele de translatare a unei adrese virtuale din spaţiul kernel în adrese fizice. Acestea sunt [[http://elixir.free-electrons.com/linux/v4.9/source/​arch/​x86/​include/​asm/​io.h#​L118| virt_to_phys]] pentru adrese alocate folosind ''​kmalloc''​ şi [[http://elixir.free-electrons.com/linux/v4.9/source/include/​linux/​mm.h#L473|vmalloc_to_pfn]] pentru adrese alocate folosind ''​vmalloc''​.
  
 Astfel, numărul de pagină ''​phys_pgoff''​ din exemplul de mai sus se va obţine în cazul unei adrese ''​kmalloc_area''​ alocate folosind ''​kmalloc''​ astfel: Astfel, numărul de pagină ''​phys_pgoff''​ din exemplul de mai sus se va obţine în cazul unei adrese ''​kmalloc_area''​ alocate folosind ''​kmalloc''​ astfel:
Line 155: Line 150:
 ===== ''​SetPageReserved''/''​ClearPageReserved''​ ===== ===== ''​SetPageReserved''/''​ClearPageReserved''​ =====
  
-Înainte de a fi utilizată, unei pagini îi va trebui activat bitul [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​page-flags.h#​L86|PG_reserved]]. Acest bit înseamnă că pagina nu poate fi evacuată pe disk (''​swap''​). Activarea se realizează cu ajutorul macroului [[http://lxr.linux.no/#linux+v2.6.35/​include/​linux/​page-flags.h#​L144|SetPageReserved]]. Macrodefiniţia primeşte ca parametru un pointer către structura de pagină, ''​struct page'',​ care se obţine din adresa virtuală din kernel cu ajutorul funcţiei ''​virt_to_page'',​ pentru adrese alocate folosind ''​kmalloc'':​+Înainte de a fi utilizată, unei pagini îi va trebui activat bitul [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​page-flags.h#​L85|PG_reserved]]. Acest bit înseamnă că pagina nu poate fi evacuată pe disk (''​swap''​). Activarea se realizează cu ajutorul macroului [[http://elixir.free-electrons.com/linux/v4.9/source/​include/​linux/​page-flags.h#​L194|SetPageReserved]]. Macrodefiniţia primeşte ca parametru un pointer către structura de pagină, ''​struct page'',​ care se obţine din adresa virtuală din kernel cu ajutorul funcţiei ''​virt_to_page'',​ pentru adrese alocate folosind ''​kmalloc'':​
 <code C> <code C>
 #define NPAGES 16 #define NPAGES 16
Line 166: Line 161:
 } }
 </​code>​ </​code>​
-şi cu ajutorul funcţiei [[http://lxr.linux.no/#linux+v2.6.35/​mm/​vmalloc.c#​L206|vmalloc_to_page]] pentru adrese alocate folosind ''​vmalloc'':​+şi cu ajutorul funcţiei [[http://elixir.free-electrons.com/linux/v4.9/source/​mm/​vmalloc.c#​L235|vmalloc_to_page]] pentru adrese alocate folosind ''​vmalloc'':​
 <code C> <code C>
 #define NPAGES 16 #define NPAGES 16
Line 178: Line 173:
 </​code>​ </​code>​
  
-Înainte de eliberarea paginii (''​kfree''/''​vfree''​),​ bitul de pagină rezervată trebuie dezactivat cu ajutorul macroului [[http://​lxr.linux.no/#​linux+v2.6.35/​include/​linux/​page-flags.h#​L148|ClearPageReserved]]. Acesta primeşte ca parametru acelaşi pointer către o structura de pagină care a fost dat la ''​SetPageReserved''​.+Înainte de eliberarea paginii (''​kfree''/''​vfree''​),​ bitul de pagină rezervată trebuie dezactivat cu ajutorul macroului [[http://​lxr.free-electrons.com/source/​include/​linux/​page-flags.h?v=4.9#L185|ClearPageReserved]]. Acesta primeşte ca parametru acelaşi pointer către o structura de pagină care a fost dat la ''​SetPageReserved''​.
  
  
-===== Exerciții ===== 
-<note important>​ 
-  * Toate exercițiile de Linux vor fi realizate în cadrul **mașinii virtuale** de Linux (dacă nu este specificat altfel), iar cele de Windows în cadrul **mașinii virtuale** de Windows. 
-  * Recomandăm să porniți VMware într-un workspace separat. 
-  * Excepție face folosirea LXR, puteți folosi mașina fizică pentru căutări. ​ În cazul folosirii cscope, folosiți mașina virtuală, mai precis directorul ''/​usr/​src/​linux''​. 
-</​note>​ 
- 
-  * Mașinile virtuale pot fi accesate, respectiv, prin Multicast DNS, folosind numele ''​spook.local''​ (Linux) și ''​chooch.local''​ Windows. 
-    * Pentru accesarea mașinilor virtuale puteți folosi SSH. Conturile mașinilor virtuale sunt: 
-      * Linux: root/​student (adică utilizatorul ''​root''​ cu parola ''​student'';​ conectare folosind comanda ''​ssh root@spook.local''​),​ student/​student (''​ssh student@spook.local''​) 
-      * Windows: Administrator/​student (''​ssh Administrator@spook.local''​),​ student/​student (''​ssh student@chooch.local''​) 
-    * Fiind vorba de kernel programming/​driver development veți folosi preponderent conturile privilegiate (''​root''​ respectiv ''​Administrator''​). 
-    * Există create două alias-uri SSH pentru conectare rapidă la mașinile virtuale: 
-      * Linux (root): ''​ssh linux''​ 
-      * Windows (Administrator):​ ''​ssh windows''​ 
-  * Pentru accesarea locală a sistemului de fișiere de pe mașinile virtuale puteți folosi Samba/CIFS, prin intermediul a două scripturi: 
-    * Montarea ''/​root/​share/''​ de pe mașina virtuală Linux în ''/​home/​student/​linux-share/''​ pe sistemul local se face folosind comanda ''​~/​bin/​mount-linux''​. 
-    * Montarea ''/​home/​Administrator/​share/''​ (Cygwin) de pe mașina virtuală Windows în ''/​home/​student/​windows-share/''​ pe sistemul local se face folosind comanda ''​~/​bin/​mount-windows''​. 
- 
-<note warning> 
-Înainte de a rezolva un exercițiu, citiți cu **atenție** toate bullet-urile acestuia. 
-</​note>​ 
-  
-==== Linux ==== 
- 
-  * Folosiți directorul ''​lin/''​ din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab12-tasks.zip | arhiva de sarcini]] a laboratorului. 
-  * Punctaj total: **7 puncte** 
- 
-<note important>​ 
-  * Pe mașina virtuală de Linux recomandăm:​ 
-    * Conectarea prin SSH de pe sistemul fizic folosind comanda ''​ssh linux''​. 
-    * Folosirea ''​wget''​ pentru descărcarea [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab12-tasks.zip | arhivei de sarcini]] a laboratorului. 
-  * În cazul apariției unui oops, reporniți mașina virtuală (sau faceți revert la un snapshot realizat anterior de voi). 
-</​note>​ 
- 
-  - (**2 puncte**) 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. 
-      * Memoria driver-ului este alocată folosind ''​kmalloc''​. 
-      * Completați zonele marcate cu ''​TODO 1''​. 
-      * Parcurgeți secțiunea [[#​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''​. 
-      * O pagină în kernel are dimensiunea [[http://​lxr.linux.no/​linux+*/​arch/​x86/​include/​asm/​page_types.h#​L8|PAGE_SIZE]]. 
-       * Zona alocată din spațiul kernel este indicată de ''​kmalloc_area''​. 
-       * Dimensiunea ''​NPAGES+1''​ este necesară pentru aliniere. 
-    * 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>​ 
-kmalloc_area = (char *)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK); 
-</​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). 
-      * Folosiți [[http://​lxr.free-electrons.com/​source/​tools/​virtio/​linux/​virtio.h?​v=3.7#​L32|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''​. 
-    * Implementați funcția ''​mmap''​ pentru driver. 
-      * Pentru mapare folosiți funcția [[http://​lxr.free-electrons.com/​source/​mm/​memory.c?​v=3.7#​L2282|remap_pfn_range]]. 
-    * Al treilea argument primit de [[http://​lxr.free-electrons.com/​source/​mm/​memory.c?​v=3.7#​L2282|remap_pfn_range]] este un număr de pagină fizică (''​pfn''​ -- //page frame number//). 
-      * Pentru conversia din adresă kernel virtuală în adresă fizică utilizați [[http://​lxr.free-electrons.com/​source/​arch/​x86/​include/​asm/​io.h?​v=3.7#​L98|virt_to_phys]]. 
-      * Shiftați rezultatul cu ''​PAGE_SHIFT''​ biți pentru a obține ''​pfn''​. 
-    * Încărcați modulul în kernel. 
-    * Pentru testare utilizați testul din directorul ''​lin/​test''​. 
-      * Compilați testul folosind comanda ''​make''​. 
-      * Rulați testul folosind comanda ''​./​mmap-test''​. 
-    * Descărcați modulul din kernel. 
-  - (**2 puncte**) Mapare de memorie virtual contiguă î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. 
-      * Memoria driver-ului este alocată folosind ''​vmalloc''​. 
-      * Completați zonele marcate cu ''​TODO 2''​. 
-      * Parcurgeți secțiunea [[#​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''​. 
-    * Zona alocată din spațiul kernel este indicată de ''​vmalloc_area''​ (variabilă globală). 
-      * 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); 
-      * Folosiți [[http://​lxr.free-electrons.com/​source/​mm/​vmalloc.c?​v=3.7#​L202|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''​. 
-    * 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.7#​L236|vmalloc_to_pfn]]. 
-      * [[http://​lxr.free-electrons.com/​source/​mm/​vmalloc.c?​v=3.7#​L236|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. 
-      * Apelați [[|remap_pfn_range]] pentru **fiecare** pagină virtuală. 
-      * Folosiți ''​vmalloc_area_ptr''​ pentru parcurgerea spațiului virtual din kernel space. 
-        * Nu modificați variabila globală ''​vmalloc_area''​. 
-    * Argumentul pentru [[http://​lxr.free-electrons.com/​source/​mm/​vmalloc.c?​v=3.7#​L236|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.7#​L2282|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.7#​L2282|remap_pfn_range]] este pfn-ul paginii virtuale din kernel-space care se dorește remapată. 
-    * Încărcați modulul în kernel. 
-    * Pentru testare utilizați testul din directorul ''​lin/​test''​. 
-      * Compilați testul folosind comanda ''​make''​. 
-      * Rulați testul folosind comanda ''​./​mmap-test''​. 
-    * Descărcați modulul din kernel. 
-  - (**1 punct**) 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. 
-      * Operațiile de citire și scriere vor acționa chiar asupra zonei de memorie alocate. 
-      * Completați zonele marcate cu ''​TODO 3''​. 
-      * Revedeți [[so2:​laboratoare:​lab04 | Laboratorul 4]] 
-    * **Ignorați** parametrul ''​offset''​ trimis operației de read/write. 
-    * Pentru testare utilizați testul din directorul ''​lin/​test''​. 
-      * Definiți macroul ''​TASK_3''​ în ''​mmap_test.c''​ 
-  - (**2 puncte**) 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. 
-      * Completați zonele marcate cu ''​TODO 4''​. 
-    * 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/​fs/​proc/​generic.c?​v=3.7#​L701|create_proc_entry]]. 
-      * 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.7#​L780|remove_proc_entry]]. 
-    * O utilizare (complexă) și descriere a interfeței [[http://​lxr.free-electrons.com/​source/​include/​linux/​seq_file.h?​v=3.7#​L18|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**. 
-    * Î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.7#​L311|mm_struct]] a procesului curent folosind funcția [[http://​lxr.linux.no/#​linux+v3.9.2/​kernel/​fork.c#​L661|get_task_mm]];​ 
-      * iterați prin toată lista de structuri [[http://​lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?​v=3.7#​L220|vm_area_struct]] asociată procesului; 
-      * 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''​. 
-      * decrementați reference counter-ul structurii [[http://​lxr.free-electrons.com/​source/​include/​linux/​mm_types.h?​v=3.7#​L311|mm_struct]] folosind [[http://​lxr.linux.no/#​linux+v3.9.2/​kernel/​fork.c#​L606|mmput]];​ 
-      * folosiți [[http://​lxr.linux.no/#​linux+v2.6.38/​include/​linux/​seq_file.h#​L86|seq_printf]] pentru a scrie în fișier. 
-        * Afișați **doar** domensiunea totală, fără alt mesaj/șir de caractere. 
-    * Înregistrați funcția de afișare folosind apelul [[http://​lxr.free-electrons.com/​source/​fs/​seq_file.c?​v=3.7#​L581|single_open]]. 
-    * Pentru testare utilizați testul din directorul ''​lin/​test''​. 
-      * Definiți ''​TASK_4''​ în ''​mmap_test.c''​. 
-      * Rulați testul în background după care folosiți comanda ''​pmap''​ pentru a vedea mapările testului și a le compara cu cele obținute. 
- 
- 
-==== Soluții ==== 
- 
-  * [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab12-sol.zip | Soluții exerciții laborator 12]] 
 ===== Resurse utile ===== ===== Resurse utile =====
  
Line 315: Line 188:
   - [[http://​www.ecst.csuchico.edu/​~beej/​guide/​ipc/​mmap.html|Memory Mapped Files]]   - [[http://​www.ecst.csuchico.edu/​~beej/​guide/​ipc/​mmap.html|Memory Mapped Files]]
   - [[http://​en.wikipedia.org/​wiki/​Mmap|mmap]]   - [[http://​en.wikipedia.org/​wiki/​Mmap|mmap]]
- 
- 
so2/laboratoare/lab11.1399016886.txt.gz · Last modified: 2014/05/02 10:48 by daniel.baluta
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