Differences

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

Link to this comparison view

so2:laboratoare:lab03 [2017/03/06 12:04]
razvan.deaconescu
so2:laboratoare:lab03 [2018/03/04 20:32] (current)
ionel.ghita [Resurse utile]
Line 39: Line 39:
 Memoria virtuală a unui proces nu se poate accesa direct din kernel. În general este descurajată total accesarea spațiului de adresă al unui process, dar există situații în care un device driver trebuie să o facă. Cazul tipic este cel în care device driver-ul trebuie să acceseze un buffer din user-space. În acest caz, device driverul trebuie să folosească funcții speciale și nu să acceseze direct bufferul. Acest lucru este necesar pentru a preveni accesarea unor zone invalide de memorie. Memoria virtuală a unui proces nu se poate accesa direct din kernel. În general este descurajată total accesarea spațiului de adresă al unui process, dar există situații în care un device driver trebuie să o facă. Cazul tipic este cel în care device driver-ul trebuie să acceseze un buffer din user-space. În acest caz, device driverul trebuie să folosească funcții speciale și nu să acceseze direct bufferul. Acest lucru este necesar pentru a preveni accesarea unor zone invalide de memorie.
  
-O altă diferență față de programarea din userspace, relativ la lucrul cu memoria, este datorată stivei, stivă a cărei dimensiune este fixă și limitată. În nucleul Linux 2.6.x se folosește implicit o stivă de ''​4K'',​ iar în Windows se folosește o stivă de ''​12K''​. Din această cauză, trebuie evitate alocarea unor structuri de mari dimensiuni pe stivă sau folosirea apelurilor recursive.+O altă diferență față de programarea din userspace, relativ la lucrul cu memoria, este datorată stivei, stivă a cărei dimensiune este fixă și limitată. În nucleul Linux se folosește implicit o stivă de ''​4K'',​ iar în Windows se folosește o stivă de ''​12K''​. Din această cauză, trebuie evitate alocarea unor structuri de mari dimensiuni pe stivă sau folosirea apelurilor recursive.
  
 ==== Contexte de execuție ==== ==== Contexte de execuție ====
Line 73: Line 73:
 </​code>​ </​code>​
  
-Lista exhaustivă a erorilor și o sumară explicație găsiți în [[http://lxr.free-electrons.com/​source/​include/​uapi/​asm-generic/​errno-base.h?​v=4.9| include/​asm-generic/​errno-base.h]] și [[http://lxr.free-electrons.com/​source/​include/​uapi/​asm-generic/​errno.h?​v=4.9 | include/​asm-generic/​ernno.h]].+Lista exhaustivă a erorilor și o sumară explicație găsiți în [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​uapi/​asm-generic/​errno-base.h?​| include/​asm-generic/​errno-base.h]] și [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​uapi/​asm-generic/​errno.h?​ | include/​asm-generic/​ernno.h]].
  
 ==== Șiruri de caractere ==== ==== Șiruri de caractere ====
  
-În Linux, programatorului de kernel i se pun la dispoziție funcțiile uzuale de lucru pe șiruri: ''​strcpy'',​ ''​strncpy'',​ ''​strlcpy'',​ ''​strcat'',​ ''​strncat'',​ ''​strlcat'',​ ''​strcmp'',​ ''​strncmp'',​ ''​strnicmp'',​ ''​strchr'',​ ''​strnchr'',​ ''​strrchr'',​ ''​strstr'',​ ''​strlen'',​ ''​memset'',​ ''​memcpy'',​ ''​memmove'',​ ''​memscan'',​ ''​memcmp'',​ ''​memchr''​. Aceste funcții sunt declarate în headerul [[http://lxr.free-electrons.com/​source/​include/​linux/​string.h?​v=4.9|include/​linux/​string.h]] și sunt implementate în kernel în fișierul [[http://lxr.free-electrons.com/​source/​lib/​string.c?​v=4.9|lib/​string.c]].+În Linux, programatorului de kernel i se pun la dispoziție funcțiile uzuale de lucru pe șiruri: ''​strcpy'',​ ''​strncpy'',​ ''​strlcpy'',​ ''​strcat'',​ ''​strncat'',​ ''​strlcat'',​ ''​strcmp'',​ ''​strncmp'',​ ''​strnicmp'',​ ''​strchr'',​ ''​strnchr'',​ ''​strrchr'',​ ''​strstr'',​ ''​strlen'',​ ''​memset'',​ ''​memcpy'',​ ''​memmove'',​ ''​memscan'',​ ''​memcmp'',​ ''​memchr''​. Aceste funcții sunt declarate în headerul [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​string.h?​|include/​linux/​string.h]] și sunt implementate în kernel în fișierul [[http://elixir.bootlin.com/linux/v4.9/​source/​lib/​string.c?​|lib/​string.c]].
  
 ==== printk ==== ==== printk ====
  
-Echivalentul ''​printf''​ în kernel este ''​printk'',​ definit în [[http://lxr.free-electrons.com/​source/​include/​linux/​printk.h?​v=4.9|include/​linux/​printk.h]]. Sintaxa printk seamănă foarte mult cu cea a printf. Primul parametru al printk decide categoria de mesaje în care se încadrează mesajul curent:+Echivalentul ''​printf''​ în kernel este ''​printk'',​ definit în [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​printk.h?​|include/​linux/​printk.h]]. Sintaxa printk seamănă foarte mult cu cea a printf. Primul parametru al printk decide categoria de mesaje în care se încadrează mesajul curent:
  
 <code C> <code C>
Line 117: Line 117:
 ==== Alocare memorie ==== ==== Alocare memorie ====
  
-În Linux se poate aloca doar memorie **rezidentă**,​ cu ajutorul apelului [[http://lxr.free-electrons.com/​source/​include/​linux/​slab.h?​v=4.9#L425 | kmalloc]]. Un apel tipic kmalloc este prezentat în continuare:+În Linux se poate aloca doar memorie **rezidentă**,​ cu ajutorul apelului [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​slab.h?#​L425 | kmalloc]]. Un apel tipic kmalloc este prezentat în continuare:
  
 <code C> <code C>
Line 133: Line 133:
   *''​GFP_ATOMIC''​ - atunci când se folosește această valoare se garantează ca funcția kmalloc nu suspendă procesul curent; poate fi folosită oricând.   *''​GFP_ATOMIC''​ - atunci când se folosește această valoare se garantează ca funcția kmalloc nu suspendă procesul curent; poate fi folosită oricând.
  
-Complementara funcției ''​kmalloc''​ este [[http://lxr.free-electrons.com/​source/​mm/​slab.c?​v=4.9#L3804 | kfree]], funcție ce primește ca argument o zonă alocată de ''​kmalloc''​. Această funcție nu suspendă procesul curent și, în consecință,​ poate fi apelată din orice context.+Complementara funcției ''​kmalloc''​ este [[http://elixir.bootlin.com/linux/v4.9/​source/​mm/​slab.c?#​L3804 | kfree]], funcție ce primește ca argument o zonă alocată de ''​kmalloc''​. Această funcție nu suspendă procesul curent și, în consecință,​ poate fi apelată din orice context.
 ==== Liste ==== ==== Liste ====
  
-Pentru că listele înlănțuite sunt deseori folosite, Linux kernel API pune la dispoziție o modalitate unitară de definire și folosire a listelor. Aceasta implică folosirea unui element de tipul ''​struct list_head''​ în cadrul structurii pe care vrem să o considerăm nod al unei liste. Structura ''​list_head''​ este definită în [[ http://lxr.free-electrons.com/​source/​include/​linux/​list.h?​v=4.9 | include/​linux/​list.h]] alături de toate celelalte funcții ce lucrează pe liste. Codul următor arată definiția structurii ''​list_head''​ și folosirea unui element din acest tip într-o altă structură bine cunoscută din kernelul Linux:+Pentru că listele înlănțuite sunt deseori folosite, Linux kernel API pune la dispoziție o modalitate unitară de definire și folosire a listelor. Aceasta implică folosirea unui element de tipul ''​struct list_head''​ în cadrul structurii pe care vrem să o considerăm nod al unei liste. Structura ''​list_head''​ este definită în [[ http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​list.h?​ | include/​linux/​list.h]] alături de toate celelalte funcții ce lucrează pe liste. Codul următor arată definiția structurii ''​list_head''​ și folosirea unui element din acest tip într-o altă structură bine cunoscută din kernelul Linux:
  
 <code C> <code C>
Line 223: Line 223:
 Din exemplul de mai sus se observă că modalitatea de definire și folosire a unei liste (dublu înlănțuite) este generică și, în același timp, nu introduce un overhead suplimentar. Structura ''​list_head''​ este folosită pentru a menține legăturile între elementele listei. Se observă, de asemenea, că iterarea prin listă se face tot cu ajutorul acestei structuri, iar obținerea elementelor din listă se face cu ajutorul ''​list_entry''​. Această idee de implementare și folosire a unei liste nu este nouă, ea fiind descrisă în ''​The Art of Computer Programming''​ de Donald Knuth în anii '80. Din exemplul de mai sus se observă că modalitatea de definire și folosire a unei liste (dublu înlănțuite) este generică și, în același timp, nu introduce un overhead suplimentar. Structura ''​list_head''​ este folosită pentru a menține legăturile între elementele listei. Se observă, de asemenea, că iterarea prin listă se face tot cu ajutorul acestei structuri, iar obținerea elementelor din listă se face cu ajutorul ''​list_entry''​. Această idee de implementare și folosire a unei liste nu este nouă, ea fiind descrisă în ''​The Art of Computer Programming''​ de Donald Knuth în anii '80.
  
-Mai multe funcții și macrodefiniții de lucru cu liste kernel sunt prezentate și explicate în headerul [[http://lxr.free-electrons.com/​source/​include/​linux/​list.h?​v=4.9 | include/​linux/​list.h]].+Mai multe funcții și macrodefiniții de lucru cu liste kernel sunt prezentate și explicate în headerul [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​list.h?​ | include/​linux/​list.h]].
 ==== Locking ==== ==== Locking ====
  
 ==== Spinlock-uri ==== ==== Spinlock-uri ====
  
-''​spinlock_t''​ (definit in [[http://lxr.free-electrons.com/​source/​include/​linux/​spinlock.h?​v=4.9 | linux/​spinlock.h]]) este tipul de bază ce implementează conceptul de spinlock în Linux. El descrie un spinlock, iar operațiile asociate cu un spinlock sunt ''​spin_lock_init'',​ ''​spin_lock'',​ ''​spin_unlock''​. Un exemplu de utilizare este prezentat mai jos:+''​spinlock_t''​ (definit in [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​spinlock.h?​ | linux/​spinlock.h]]) este tipul de bază ce implementează conceptul de spinlock în Linux. El descrie un spinlock, iar operațiile asociate cu un spinlock sunt ''​spin_lock_init'',​ ''​spin_lock'',​ ''​spin_unlock''​. Un exemplu de utilizare este prezentat mai jos:
  
 <code C> <code C>
Line 287: Line 287:
 ==== Mutex ==== ==== Mutex ====
  
-Un mutex este reprezentat de o variabilă de tipul ''​struct mutex''​ (definit în [[http://lxr.free-electrons.com/​source/​include/​linux/​mutex.h?​v=4.9#L22 | linux/​mutex.h]]). Funcțiile și macro-urile pentru lucrul cu mutex sunt prezentate în continuare:+Un mutex este reprezentat de o variabilă de tipul ''​struct mutex''​ (definit în [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​mutex.h?#​L22 | linux/​mutex.h]]). Funcțiile și macro-urile pentru lucrul cu mutex sunt prezentate în continuare:
  
 <code C> <code C>
Line 308: Line 308:
 ==== Variabile atomice ==== ==== Variabile atomice ====
  
-De multe ori, este nevoie doar de sincronizarea accesului la o variabilă simplă, de exemplu un contor. Pentru ​ aceasta se poate folosi o variabilă de tip ''​atomic_t''​ (definit în [[http://lxr.free-electrons.com/​source/​include/​linux/​atomic.h?​v=4.9 | include/​linux/​atomic.h]]) care ține o valoare întreagă. Mai jos sunt prezentate unele operații care pot fi efectuate asupra unei variabile ''​atomic_t'':​+De multe ori, este nevoie doar de sincronizarea accesului la o variabilă simplă, de exemplu un contor. Pentru ​ aceasta se poate folosi o variabilă de tip ''​atomic_t''​ (definit în [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​linux/​atomic.h?​ | include/​linux/​atomic.h]]) care ține o valoare întreagă. Mai jos sunt prezentate unele operații care pot fi efectuate asupra unei variabile ''​atomic_t'':​
  
 <code C> <code C>
Line 417: Line 417:
 ==== Operatii atomice pe biți ==== ==== Operatii atomice pe biți ====
  
-Kernelul pune la dispoziție un set de funcții (în [[http://lxr.free-electrons.com/​source/​include/​asm-generic/​bitops/​atomic.h?​v=4.9#L50 | asm/​bitops.h]]) care modifică sau testează biți în mod atomic.+Kernelul pune la dispoziție un set de funcții (în [[http://elixir.bootlin.com/linux/v4.9/​source/​include/​asm-generic/​bitops/​atomic.h?#​L50 | asm/​bitops.h]]) care modifică sau testează biți în mod atomic.
  
 <code C> <code C>
Line 438: Line 438:
     * [[http://​lwn.net/​images/​pdf/​LDD3/​ch08.pdf | Chapter 8.  Allocating Memory]]     * [[http://​lwn.net/​images/​pdf/​LDD3/​ch08.pdf | Chapter 8.  Allocating Memory]]
     * [[http://​lwn.net/​images/​pdf/​LDD3/​ch11.pdf | Chapter 11. Data Types in the Kernel]]     * [[http://​lwn.net/​images/​pdf/​LDD3/​ch11.pdf | Chapter 11. Data Types in the Kernel]]
-  - [[http://www.gnugeneration.com/books/linux/​2.6.20/​kernel-api/​ | The Linux Kernel API]]+  - [[https://www.kernel.org/doc/htmldocs/​kernel-api/​ | The Linux Kernel API]]
   - [[http://​isis.poly.edu/​kulesh/​stuff/​src/​klist/​ | Linux Kernel Linked-List Explained]]   - [[http://​isis.poly.edu/​kulesh/​stuff/​src/​klist/​ | Linux Kernel Linked-List Explained]]
   - [[http://​kernelbook.sourceforge.net/​kernel-locking.html/​ | Unreliable Guide To Locking]]   - [[http://​kernelbook.sourceforge.net/​kernel-locking.html/​ | Unreliable Guide To Locking]]
   - [[http://​excess.org/​article/​2008/​07/​oclug-june-kernel-walkthrough/​ | Linux Kernel Walkthrough Screencast]]   - [[http://​excess.org/​article/​2008/​07/​oclug-june-kernel-walkthrough/​ | Linux Kernel Walkthrough Screencast]]
-  - [[http://linuxwell.com/​2012/​11/​10/​magical-container_of-macro/​| Magical container_of() Macro]]+  - [[http://radek.io/​2012/​11/​10/​magical-container_of-macro/​| Magical container_of() Macro]]
  
so2/laboratoare/lab03.1488794673.txt.gz · Last modified: 2017/03/06 12:04 by razvan.deaconescu
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