Differences

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

Link to this comparison view

so2:laboratoare:lab09 [2018/04/24 19:20]
anda.nicolae [Structura dentry]
so2:laboratoare:lab09 [2021/05/03 11:06] (current)
teodor_stefan.dutu [Operații pentru inode - inode_operations]
Line 103: Line 103:
 O bună parte din superoperații (componentele structurii [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1803 | struct super_operations]],​ utilizate de superbloc) sunt folosite în lucrul cu inode-uri. În continuare sunt prezentate acestea: O bună parte din superoperații (componentele structurii [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1803 | struct super_operations]],​ utilizate de superbloc) sunt folosite în lucrul cu inode-uri. În continuare sunt prezentate acestea:
  
-  *''​alloc_inode'':​ alocă un inode. De obicei, în cadrul acestei structuri se alocă o structură ''​fsname_inode_info''​ și se efectuează inițializările de bază ale inode-ului VFS (folosind [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L360 | inode_init_once]]). În [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]], pentru alocare este folosită funcția [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​tools/​testing/​radix-tree/​linux/​slab.h#​L14 | kmem_cache_alloc]] care interacționează cu subsistemul [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​mm/​slab.c| SLAB]]. La fiecare alocare se apelează [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​slab_def.h#​L39| constructorul]] cache-ului, în cazul [[http://lxr.free-electrons.com/​source/​fs/​minix/?​v=4.9 ​| minix]] funcția [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#​L82|init_once]]. Alternativ, se poate folosi [[http://lxr.free-electrons.com/​source/​include/​linux/​slab.h?v=4.9#L478 | kmalloc]], caz în care va trebui apelată funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L359 | inode_init_once]]. Funcția ''​alloc_inode''​ va fi apelată de funcțiile [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L900 | new_inode]] și [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L1087 | iget_locked]].+  *''​alloc_inode'':​ alocă un inode. De obicei, în cadrul acestei structuri se alocă o structură ''​fsname_inode_info''​ și se efectuează inițializările de bază ale inode-ului VFS (folosind [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L360 | inode_init_once]]). În [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]], pentru alocare este folosită funcția [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​tools/​testing/​radix-tree/​linux/​slab.h#​L14 | kmem_cache_alloc]] care interacționează cu subsistemul [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​mm/​slab.c| SLAB]]. La fiecare alocare se apelează [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​slab_def.h#​L39| constructorul]] cache-ului, în cazul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]] funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L82|init_once]]. Alternativ, se poate folosi [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​slab.h#​L436 | kmalloc]], caz în care va trebui apelată funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L360 | inode_init_once]]. Funcția ''​alloc_inode''​ va fi apelată de funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L901 | new_inode]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L1088 | iget_locked]].
   *''​write_inode'':​ salvează/​actualizează pe disc inode-ul primit ca parametru; pentru actualizarea inode-ului, deși ineficient, pentru începători este recomandat să folosească următoarea secvență de operații:   *''​write_inode'':​ salvează/​actualizează pe disc inode-ul primit ca parametru; pentru actualizarea inode-ului, deși ineficient, pentru începători este recomandat să folosească următoarea secvență de operații:
-    *încarcă inode-ul de pe disc cu ajutorul funcției [[http://lxr.free-electrons.com/​source/​include/​linux/​buffer_head.h?v=4.9#L298 | sb_bread]];​ +    *încarcă inode-ul de pe disc cu ajutorul funcției [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​buffer_head.h#​L304 | sb_bread]];​ 
-    *modifică [[http://lxr.free-electrons.com/​source/​include/​linux/​buffer_head.h?v=4.9#L53|buffer-ul]] în concordanță cu inode-ul de salvat; +    *modifică [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​buffer_head.h#​L54|buffer-ul]] în concordanță cu inode-ul de salvat; 
-    *marchează buffer-ul murdar (dirty) cu ajutorul funcției [[http://lxr.free-electrons.com/​source/​fs/​buffer.c?v=4.9#L1136 | mark_buffer_dirty]];​ kernel-ul se va ocupa apoi de scrierea lui pe disc;  +    *marchează buffer-ul murdar (dirty) cu ajutorul funcției [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​buffer.c#​L1094 | mark_buffer_dirty]];​ kernel-ul se va ocupa apoi de scrierea lui pe disc;  
-    *un exemplu este funcția [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L603 | minix_write_inode]] din sistemul de fișiere [[http://lxr.free-electrons.com/​source/​fs/​minix/?​v=4.9 ​| minix]]+    *un exemplu este funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L602 | minix_write_inode]] din sistemul de fișiere [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]]
   *''​evict_inode'':​ șterge de pe disc și din memorie orice informație referitoare la numărul inode-ului primit în câmpul ''​i_ino''​ (atât inode-ul de pe disc cât și blocurile de date asociate). Aceasta implică realizarea următoarelor operații:   *''​evict_inode'':​ șterge de pe disc și din memorie orice informație referitoare la numărul inode-ului primit în câmpul ''​i_ino''​ (atât inode-ul de pe disc cât și blocurile de date asociate). Aceasta implică realizarea următoarelor operații:
     *șterge inode-ul de pe disc;     *șterge inode-ul de pe disc;
     *actualizează hărțile de biți pe disc (în cazul în care există)     *actualizează hărțile de biți pe disc (în cazul în care există)
-    *șterge inode-ul din page cache prin apelarea funcției [[http://lxr.free-electrons.com/​source/​mm/​truncate.c?v=4.9#L387 | truncate_inode_pages]];​+    *șterge inode-ul din page cache prin apelarea funcției [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​truncate.c#​L468 | truncate_inode_pages]];​
     *șterge inode-ul din memorie prin apelarea funcției ''​clear_inode''​ ;     *șterge inode-ul din memorie prin apelarea funcției ''​clear_inode''​ ;
-    *un exemplu este funcția [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L27 | minix_evict_inode]] din sistemul de fișiere [[http://lxr.free-electrons.com/​source/​fs/​minix/?​v=4.9 ​| minix]].+    *un exemplu este funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L27 | minix_evict_inode]] din sistemul de fișiere [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]].
   *''​destroy_inode''​ eliberează memoria ocupată de inode   *''​destroy_inode''​ eliberează memoria ocupată de inode
  
Line 121: Line 121:
 Operațiile pentru inode sunt descrise de structura [[http://​lxr.free-electrons.com/​source/​include/​linux/​fs.h?​v=4.9#​L604 | struct inode_operations]]. Operațiile pentru inode sunt descrise de structura [[http://​lxr.free-electrons.com/​source/​include/​linux/​fs.h?​v=4.9#​L604 | struct inode_operations]].
  
-Inode-urile sunt de mai multe tipuri: fișier, director, fișier special (pipe, fifo), dispozitiv de tip bloc, dispozitiv de tip caracter, link etc. Din acest motiv, operațiile pe care trebuie un inode să le implementeze sunt diferite pentru fiecare tip de inode. Mai jos vor fi prezentate în detaliu operațiile implementate pentru un [[#Inode-urile_de_tip_fi.C8.99ier|inode de tip fișier]] și un [[#Opera.C8.9Bii_asupra_inode-urilor_de_tip_director|inode de tip director]].+Inode-urile sunt de mai multe tipuri: fișier, director, fișier special (pipe, fifo), dispozitiv de tip bloc, dispozitiv de tip caracter, link etc. Din acest motiv, operațiile pe care trebuie un inode să le implementeze sunt diferite pentru fiecare tip de inode. Mai jos vor fi prezentate în detaliu operațiile implementate pentru un [[#inode-urile_de_tip_fisier|inode de tip fișier]] și un [[#operatii_asupra_inode-urilor_de_tip_director|inode de tip director]].
  
 Operațiile unui inode sunt inițializate și accesate folosind câmpul ''​i_op''​ al structurii [[http://​lxr.free-electrons.com/​source/​include/​linux/​fs.h?​v=4.9#​L604 | struct inode]]. Operațiile unui inode sunt inițializate și accesate folosind câmpul ''​i_op''​ al structurii [[http://​lxr.free-electrons.com/​source/​include/​linux/​fs.h?​v=4.9#​L604 | struct inode]].
Line 129: Line 129:
 Structura ''​file''​ corespunde unui fișier deschis de un proces și există doar în memorie, fiind asociată unui inode. Este entitatea din VFS cea mai apropiată de user-space; câmpurile structurii conțin informații familiare ale unui fișier din user-space (modul de acces, poziția în fișier, etc.), iar operațiile cu aceasta sunt apeluri de sistem cunoscute (''​read'',​ ''​write'',​ etc.). Structura ''​file''​ corespunde unui fișier deschis de un proces și există doar în memorie, fiind asociată unui inode. Este entitatea din VFS cea mai apropiată de user-space; câmpurile structurii conțin informații familiare ale unui fișier din user-space (modul de acces, poziția în fișier, etc.), iar operațiile cu aceasta sunt apeluri de sistem cunoscute (''​read'',​ ''​write'',​ etc.).
  
-Operațiile pentru ''​file''​ sunt descrise de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L1696 | struct file_operations]].+Operațiile pentru ''​file''​ sunt descrise de structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1692 | struct file_operations]].
  
-Pentru a inițializa operațiile pe ''​file''​ pentru un sistem de fișiere, se folosește câmpul ''​i_fop''​ al structurii [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L604 | struct inode]]. La deschiderea unui fișier, VFS-ul inițializează câmpul ''​f_op''​ al structurii [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L880 | struct file]] cu adresa din ''​inode->​i_fop'',​ astfel încât apeluri de sistem ulterioare să folosească valoarea stocată în ''​file->​f_op''​.+Pentru a inițializa operațiile pe ''​file''​ pentru un sistem de fișiere, se folosește câmpul ''​i_fop''​ al structurii [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L565 | struct inode]]. La deschiderea unui fișier, VFS-ul inițializează câmpul ''​f_op''​ al structurii [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L852 | struct file]] cu adresa din ''​inode->​i_fop'',​ astfel încât apeluri de sistem ulterioare să folosească valoarea stocată în ''​file->​f_op''​.
  
 ===== Inode-urile de tip fișier ===== ===== Inode-urile de tip fișier =====
Line 139: Line 139:
 ==== Operații asupra inode-urilor de tip fișier ==== ==== Operații asupra inode-urilor de tip fișier ====
  
-În sistemul de fișiere [[http://lxr.free-electrons.com/​source/​fs/​minix/?​v=4.9 ​| minix]], pentru operațiile pe un inode este definită structura [[http://lxr.free-electrons.com/​source/​fs/​minix/​file.c?v=4.9#L48 | minix_file_inode_operations]],​ iar pentru operațiile pe ''​file''​ se definește structura [[http://lxr.free-electrons.com/​source/​fs/​minix/​file.c?v=4.9#L11 | minix_file_operations]]:​+În sistemul de fișiere [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]], pentru operațiile pe un inode este definită structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​file.c#​L49 | minix_file_inode_operations]],​ iar pentru operațiile pe ''​file''​ se definește structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​file.c#​L12 | minix_file_operations]]:​
  
 <code cpp> <code cpp>
Line 165: Line 165:
 </​code>​ </​code>​
  
-Funcțiile [[http://lxr.free-electrons.com/​source/​fs/​read_write.c?v=4.9#L135 | generic_file_llseek]],​ [[http://lxr.free-electrons.com/​source/​mm/​filemap.c?v=4.9#L2335 | generic_file_mmap]],​ [[http://lxr.free-electrons.com/​source/​mm/​filemap.c?v=4.9#L1912 | generic_file_read_iter]] și [[http://lxr.free-electrons.com/​source/​mm/​filemap.c?v=4.9#L2868 | generic_file_write_iter]] sunt implementate în kernel.+Funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​read_write.c#​L134 | generic_file_llseek]],​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​filemap.c#​L2733 | generic_file_mmap]],​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​filemap.c#​L2306 | generic_file_read_iter]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​filemap.c#​L3195 | generic_file_write_iter]] sunt implementate în kernel.
  
-Pentru sistemele de fișiere simple nu trebuie să se implementeze decât operația de trunchiere (apelul de sistem ''​truncate''​). Deși inițial exita o operație dedicată, începând cu 3.14, operația a fost înglobată în setattr: dacă dimensiunea pasată este diferită de dimensiunea curentă a inode-ului atunci va trebui efectuată o operație de trunchiere. Un exemplu de implementare a acestei verificări este prezentă în funcția [[http://lxr.free-electrons.com/​source/​fs/​minix/​file.c#​L26 | minix_setattr]]:​+Pentru sistemele de fișiere simple nu trebuie să se implementeze decât operația de trunchiere (apelul de sistem ''​truncate''​). Deși inițial exita o operație dedicată, începând cu 3.14, operația a fost înglobată în setattr: dacă dimensiunea pasată este diferită de dimensiunea curentă a inode-ului atunci va trebui efectuată o operație de trunchiere. Un exemplu de implementare a acestei verificări este prezentă în funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​file.c#​L25 | minix_setattr]]:​
  
 <code c> <code c>
Line 199: Line 199:
   * actualizarea hărților de biți pe disc (în cazul în care sunt folosite);   * actualizarea hărților de biți pe disc (în cazul în care sunt folosite);
   * actualizarea inode-ului;   * actualizarea inode-ului;
-  * completarea cu zero spațiul care a rămas nefolosit din ultimul bloc cu ajutorul funcției [[http://lxr.free-electrons.com/​source/​fs/​buffer.c?v=4.9#L2864 | block_truncate_page]].+  * completarea cu zero spațiul care a rămas nefolosit din ultimul bloc cu ajutorul funcției [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​buffer.c#​L2860 | block_truncate_page]].
  
-Un exemplu de implementarea a operației de trunchiere este funcția [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L641 | minix_truncate]] din sistemul de fișiere [[http://lxr.free-electrons.com/​source/​fs/​minix/?​v=4.9 ​| minix]].  ​+Un exemplu de implementarea a operației de trunchiere este funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L640 | minix_truncate]] din sistemul de fișiere [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix | minix]].  ​
  
  
Line 211: Line 211:
 Între spațiul de adrese al unui proces și fișiere există o strânsă legătură: execuția programelor se face aproape exclusiv prin maparea fișierului în spațiul de adresă al procesului. Întrucât această abordare funcționează foarte bine și este destul de generală, poate fi folosită și în cazul apelurilor de sistem obișnuite cum ar fi ''​read''​ și ''​write''​. Între spațiul de adrese al unui proces și fișiere există o strânsă legătură: execuția programelor se face aproape exclusiv prin maparea fișierului în spațiul de adresă al procesului. Întrucât această abordare funcționează foarte bine și este destul de generală, poate fi folosită și în cazul apelurilor de sistem obișnuite cum ar fi ''​read''​ și ''​write''​.
  
-Structura care descrie spațiul de adresă este [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L431 | struct address_space]] , iar operațiile cu aceasta sunt descrise de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L371 | struct address_space_operations]]. Pentru inițializarea operațiilor asupra spațiului de adresă, se completează câmpul ''​%%inode->​i_mapping->​a_ops%%''​ al inode-ului de tip fișier.+Structura care descrie spațiul de adresă este [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L391 | struct address_space]],​ iar operațiile cu aceasta sunt descrise de structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L331 | struct address_space_operations]]. Pentru inițializarea operațiilor asupra spațiului de adresă, se completează câmpul ''​%%inode->​i_mapping->​a_ops%%''​ al inode-ului de tip fișier.
  
-Un exemplu este structura [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L428 | minix_aops]] din sistemul de fișiere [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L442| minix]]:+Un exemplu este structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L428 | minix_aops]] din sistemul de fișiere [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L441| minix]]:
  
 <code cpp> <code cpp>
Line 231: Line 231:
 </​code>​ </​code>​
   ​   ​
-Funcția [[http://lxr.free-electrons.com/​source/​fs/​buffer.c?v=4.9#L2145 | generic_write_end ]] este deja implementată. Majoritatea funcțiilor specifice sunt foarte ușor de implementat,​ după cum urmează:+Funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​buffer.c#​L2144 | generic_write_end ]] este deja implementată. Majoritatea funcțiilor specifice sunt foarte ușor de implementat,​ după cum urmează:
  
 <code cpp> <code cpp>
Line 274: Line 274:
 </​code>​ </​code>​
  
-Tot ce mai trebuie făcut este să se implementeze [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#L375 | minix_get_block]],​ care trebuie să translateze un bloc al unui fișier într-un bloc de pe device. Dacă flag-ul ''​create''​ primit ca parametru este activat, trebuie alocat un nou bloc. În cazul în care se creează un bloc nou, trebuie marcată corespunzător harta de biți. Pentru a înștiința nucleul să nu mai citească blocul de pe disc, trebuie marcat ''​bh''​ cu [[http://lxr.free-electrons.com/​source/​fs/​minix/​itree_common.c#​L197|set_buffer_new]]. Trebuie asociat buffer-ul cu blocul cerut prin funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​buffer_head.h?v=4.9#L335 | map_bh]].+Tot ce mai trebuie făcut este să se implementeze [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L375 | minix_get_block]],​ care trebuie să translateze un bloc al unui fișier într-un bloc de pe device. Dacă flag-ul ''​create''​ primit ca parametru este activat, trebuie alocat un nou bloc. În cazul în care se creează un bloc nou, trebuie marcată corespunzător harta de biți. Pentru a înștiința nucleul să nu mai citească blocul de pe disc, trebuie marcat ''​bh''​ cu [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​itree_common.c#​L198|set_buffer_new]]. Trebuie asociat buffer-ul cu blocul cerut prin funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​buffer_head.h#​L341 | map_bh]].
  
 ===== Structura dentry ===== ===== Structura dentry =====
so2/laboratoare/lab09.1524586820.txt.gz · Last modified: 2018/04/24 19:20 by anda.nicolae
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