Differences

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

Link to this comparison view

so2:laboratoare:lab12 [2014/05/14 10:14]
constantin.serban1512 [Sysfs]
so2:laboratoare:lab12 [2018/05/17 09:18] (current)
elena.sandulescu [Structuri de bază în dispozitivele Linux]
Line 1: Line 1:
-====== Laborator 12 - Linux Device Model. Plug and Play======+ ====== Laborator 12 - Linux Device Model. Plug and Play ======
  
 ===== Obiectivele laboratorului ===== ===== Obiectivele laboratorului =====
  
-  * Dobândirea de cunoștințe legate de ''​Linux Device Model'' ​şi principalele componente ale acestuia: dispozitive,​ drivere, clase şi magistrale. +  * Dobândirea de cunoștințe legate de ''​Linux Device Model'' ​și principalele componente ale acestuia: dispozitive,​ drivere, clase și magistrale. 
-  * Cunoștințe legate de modul de funcţionare al mecanismelor ''​Hotplug''​ / ''​Plug and Play''​.+  * Cunoștințe legate de modul de funcționare al mecanismelor ''​Hotplug''​ / ''​Plug and Play''​.
  
 ===== Cuvinte cheie ===== ===== Cuvinte cheie =====
Line 20: Line 20:
   * [[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/​lab12-slides.pdf | Slide-uri de suport pentru laborator]]
  
-===== Noţiuni teoretice =====+===== Noțiuni teoretice =====
  
-**Plug and Play** este o tehnologie care oferă suport pentru adăugarea ​şi eliminarea automată a dispozitivelor în sistem. În acest mod se reduc conflictele legate de resursele folosite de acestea prin configurare automată la pornirea sistemului. Pentru a îndeplini aceste scopuri, sunt necesare următoarele caracteristici:​+**Plug and Play** este o tehnologie care oferă suport pentru adăugarea ​și eliminarea automată a dispozitivelor în sistem. În acest mod se reduc conflictele legate de resursele folosite de acestea prin configurare automată la pornirea sistemului. Pentru a îndeplini aceste scopuri, sunt necesare următoarele caracteristici:​
  
-  * Detectarea automată a adaugării ​şi eliminării dispozitivelor din sistem (dispozitivul ​şi magistrala acestuia trebuie sa anunţe driver-ul corespunzător că a apărut o modificare în configuraţie). +  * Detectarea automată a adaugării ​și eliminării dispozitivelor din sistem (dispozitivul ​și magistrala acestuia trebuie sa anunțe driver-ul corespunzător că a apărut o modificare în configurație). 
-  * Managementul resurselor (adrese, linii irq, canale DMA, zone de memorie), ce include alocarea resurselor către dispozitive ​şi rezolvarea conflictelor ce pot apărea.+  * Managementul resurselor (adrese, linii irq, canale DMA, zone de memorie), ce include alocarea resurselor către dispozitive ​și rezolvarea conflictelor ce pot apărea.
   * Dispozitivele trebuie să permită configurarea software (resursele dispozitivului – porturi, întreruperi,​ resurse DMA – trebuie să permită atribuirea din partea driver-ului).   * Dispozitivele trebuie să permită configurarea software (resursele dispozitivului – porturi, întreruperi,​ resurse DMA – trebuie să permită atribuirea din partea driver-ului).
   * Driver-ele necesare pentru dispozitive noi trebuie să fie încarcate automat de sistemul de operare atunci când este nevoie.   * Driver-ele necesare pentru dispozitive noi trebuie să fie încarcate automat de sistemul de operare atunci când este nevoie.
-  * Atunci când dispozitivul ​şi magistrala acestuia permit, sistemul ar trebui să poată adăuga sau elimina dispozitivul din sistem în timp ce acesta rulează, fără a fi necesară repornirea sistemului (''​hotplug''​).+  * Atunci când dispozitivul ​și magistrala acestuia permit, sistemul ar trebui să poată adăuga sau elimina dispozitivul din sistem în timp ce acesta rulează, fără a fi necesară repornirea sistemului (''​hotplug''​).
  
-Pentru ca un sistem să suporte plug and play trebuie ca ''​BIOS''​-ul,​ sistemul de operare ​şi dispozitivul să suporte această tehnologie. Dispozitivul trebuie să deţină un ''​ID''​ pe care să îl ofere driver-ului pentru identificare,​ iar sistemul de operare trebuie să poată să identifice aceste modificări în configuraţie pe măsură ce ele apar.+Pentru ca un sistem să suporte plug and play trebuie ca ''​BIOS''​-ul,​ sistemul de operare ​și dispozitivul să suporte această tehnologie. Dispozitivul trebuie să dețină un ''​ID''​ pe care să îl ofere driver-ului pentru identificare,​ iar sistemul de operare trebuie să poată să identifice aceste modificări în configurație pe măsură ce ele apar.
  
-Dispozitive care le suportă plug and play sunt: dispozitivele ''​PCI''​ (plăci de reţea), ''​USB''​ (tastatură,​ mouse, imprimantă),​ etc.+Dispozitive care suportă plug and play sunt: dispozitivele ''​PCI''​ (plăci de rețea), ''​USB''​ (tastatură,​ mouse, imprimantă),​ etc.
  
 =====  Linux Device Model  ===== =====  Linux Device Model  =====
  
-Înainte de versiunea 2.6, kernel-ul nu dispunea de un model unificat prin care să se obţină informaţii despre acesta. Din acest motiv s-a realizat un model pentru dispozitivele din Linux, ''​Linux Device Model''​.+Înainte de versiunea 2.6, kernel-ul nu dispunea de un model unificat prin care să se obțină informații despre acesta. Din acest motiv s-a realizat un model pentru dispozitivele din Linux, ''​Linux Device Model''​.
  
-Scopul principal al acestui model este de a menţine structuri de date interne care să reflecte starea ​şi structura sistemului. Astfel de infomaţii includ ce dispozitive există în sistem, în ce stare se află din punct de vedere al managementului consumului (power management),​ la ce magistrală sunt ataşate, ce drivere au asociate, alături de structura magistralelor,​ dispozitivelor,​ driverelor din sistem.+Scopul principal al acestui model este de a menține structuri de date interne care să reflecte starea ​și structura sistemului. Astfel de infomații includ ce dispozitive există în sistem, în ce stare se află din punct de vedere al managementului consumului (power management),​ la ce magistrală sunt atașate, ce drivere au asociate, alături de structura magistralelor,​ dispozitivelor,​ driverelor din sistem.
  
-Pentru a menţine aceste informaţii, kernel-ul foloseşte următoarele entităţi:+Pentru a menține aceste informații, kernel-ul folosește următoarele entități:
  
-  * **dispozitiv** - un dispozitiv fizic care este ataşat unei magistrale +  * **dispozitiv** - un dispozitiv fizic care este atașat unei magistrale 
-  * **driver** – o entitate software care poate fi asociată unui dispozitiv și execută operaţii cu acesta +  * **driver** – o entitate software care poate fi asociată unui dispozitiv și execută operații cu acesta 
-  * **magistrală (bus)** – un dispozitiv la care se pot ataşa alte dispozitive +  * **magistrală (bus)** – un dispozitiv la care se pot atașa alte dispozitive 
-  * **clasă** – un tip de dispozitive care au o comportare similară; există o clasă pentru discuri, partiţii, porturi seriale, etc. +  * **clasă** – un tip de dispozitive care au o comportare similară; există o clasă pentru discuri, partiții, porturi seriale, etc. 
-  * **subsistem** – o vedere asupra structurii sistemului; subsistemele din kernel includ dispozitive (devices - o vedere ierarhică asupra tuturor dispozitivelor din sistem), magistrale (bus - o vedere a dispozitivelor în funcţie de cum sunt ataşate la magistrale),​ clase, etc.+  * **subsistem** – o vedere asupra structurii sistemului; subsistemele din kernel includ dispozitive (devices - o vedere ierarhică asupra tuturor dispozitivelor din sistem), magistrale (bus - o vedere a dispozitivelor în funcție de cum sunt atașate la magistrale),​ clase, etc.
  
-==== Sysfs ====+==== sysfs ====
  
-Kernel-ul oferă o reprezentare a modelului său în userspace prin intermediul sistemului virtual de fişiere sysfs. Acesta este de obicei montat în directorul ''/​sys'' ​şi conţine următoarele subdirectoare:​+Kernel-ul oferă o reprezentare a modelului său în userspace prin intermediul sistemului virtual de fișiere sysfs. Acesta este de obicei montat în directorul ''/​sys'' ​și conține următoarele subdirectoare:​
  
-  * **block** - toate dispozitivele de tip bloc disponibile în sistem (discuri, partiţii)+  * **block** - toate dispozitivele de tip bloc disponibile în sistem (discuri, partiții)
   * **bus** - tipuri de magistrale la care se conectează dispozitivele fizice (pci, ide, usb)   * **bus** - tipuri de magistrale la care se conectează dispozitivele fizice (pci, ide, usb)
   * **class** - clase de drivere care sunt disponibile în sistem (net, sound, usb)   * **class** - clase de drivere care sunt disponibile în sistem (net, sound, usb)
   * **devices** - structura ierarhica a dispozitivelor conectate în sistem   * **devices** - structura ierarhica a dispozitivelor conectate în sistem
-  * **firmware** - informaţii obţinute de la firmware-ul sistemului (ACPI) +  * **firmware** - informații obținute de la firmware-ul sistemului (ACPI) 
-  * **fs** - informaţii legate de sistemele de fişiere montate +  * **fs** - informații legate de sistemele de fișiere montate 
-  * **kernel** - informaţii legate de starea kernel-ului (utilizatorii logaţi, hotplug)+  * **kernel** - informații legate de starea kernel-ului (utilizatorii logați, hotplug)
   * **module** - lista modulelor încarcate la momentul curent   * **module** - lista modulelor încarcate la momentul curent
-  * **power** - informaţii legate de subsistemul de power management+  * **power** - informații legate de subsistemul de power management
  
-După cum se poate observa, există o corespondenţă între structurile de date din kernel în cadrul modelului descris ​şi subdirectoarele din sistemul virtual de fişiere ''​sysfs''​. Deşi această asemănare poate duce la confundarea celor două concepte, ele sunt diferite. Modelul pentru dispozitive în kernel poate funcţiona şi fără sistemul de fişiere ''​sysfs'',​ dar reciproca nu este adevărată.+După cum se poate observa, există o corespondență între structurile de date din kernel în cadrul modelului descris ​și subdirectoarele din sistemul virtual de fișiere ''​sysfs''​. Deși această asemănare poate duce la confundarea celor două concepte, ele sunt diferite. Modelul pentru dispozitive în kernel poate funcționa și fără sistemul de fișiere ''​sysfs'',​ dar reciproca nu este adevărată.
  
-Informaţia din ''​sysfs''​ se găseşte în fişiere ce conţin câte un atribut. Câteva atribute standard (reprezentate de fişiere sau directoare cu acelaşi nume) sunt următoarele:​+Informația din ''​sysfs''​ se găsește în fișiere ce conțin câte un atribut. Câteva atribute standard (reprezentate de fișiere sau directoare cu același nume) sunt următoarele:​
  
-  * **dev** - identificatorul major şi minor al dispozitivului;​ acesta poate fi folosit pentru a crea automat intrările în directorul ''/​dev''​ +  * **dev** - identificatorul major și minor al dispozitivului;​ acesta poate fi folosit pentru a crea automat intrările în directorul ''/​dev''​ 
-  * **device** - o legătură simbolică spre directorul ce conţine dispozitive;​ acesta poate fi folosit pentru a descoperi dispozitivele hardware care oferă un anumit serviciu (spre exemplu dispozitivul PCI al plăcii de reţea eth0) +  * **device** - o legătură simbolică spre directorul ce conține dispozitive;​ acesta poate fi folosit pentru a descoperi dispozitivele hardware care oferă un anumit serviciu (spre exemplu dispozitivul PCI al plăcii de rețea eth0) 
-  * **driver** - o legătură simbolică spre directorul ce conţine drivere (care se află în ''/​sys/​bus/​*/​drivers''​)+  * **driver** - o legătură simbolică spre directorul ce conține drivere (care se află în ''/​sys/​bus/​*/​drivers''​)
  
-Sunt disponibile ​şi alte atribute, în funcţie de magistrala ​şi driverul folosit.+Sunt disponibile ​și alte atribute, în funcție de magistrala ​și driverul folosit.
  
 {{ :​so2:​laboratoare:​laboratoare-plug_and_play-sysfs.png |}} {{ :​so2:​laboratoare:​laboratoare-plug_and_play-sysfs.png |}}
Line 76: Line 76:
 ==== Structuri de bază în dispozitivele Linux ==== ==== Structuri de bază în dispozitivele Linux ====
  
-''​Linux Device Model''​ oferă o serie de structuri care să asigure interacţiunea între un dispozitiv hardware ​şi un device driver. Întreg modelul are la bază structuri [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | struct kobject]]. Cu ajutorul acestei structuri sunt construite ierarhii ​şi sunt implementate următoarele structuri: [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | struct bus_type]], [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | struct device]] ​şi [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L225 | struct device_driver]].+''​Linux Device Model''​ oferă o serie de structuri care să asigure interacțiunea între un dispozitiv hardware ​și un device driver. Întreg modelul are la bază structuri [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | struct kobject]]. Cu ajutorul acestei structuri sunt construite ierarhii ​și sunt implementate următoarele structuri: [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]], [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | struct device_driver]].
  
 {{ :​so2:​laboratoare:​laboratoare-plug_and_play-linux_device_model_structures.png |}} {{ :​so2:​laboratoare:​laboratoare-plug_and_play-linux_device_model_structures.png |}}
Line 82: Line 82:
 === Structura kobject === === Structura kobject ===
  
-O structură [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] nu îndeplineşte o funcţie de una singură. O astfel de structură este de obicei integrată într-o structură mai mare. O structură [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] incorporează de fapt un set de facilităţi care vor fi oferite unui obiect de nivel de abstracţie mai înalt în ierarhia ''​Linux Device Model''​.+O structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] nu îndeplinește o funcție de una singură. O astfel de structură este de obicei integrată într-o structură mai mare. O structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] incorporează de fapt un set de facilități care vor fi oferite unui obiect de nivel de abstracție mai înalt în ierarhia ''​Linux Device Model''​.
  
-Spre exemplu, structura [[http://lxr.free-electrons.com/​source/​include/​linux/​cdev.h?v=3.11#L12 | cdev]] are următoarea definiţie:+Spre exemplu, structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​cdev.h#​L12 | cdev]] are următoarea definiție:
  
 <code c> <code c>
Line 97: Line 97:
 </​code>​ </​code>​
  
-Se observă că această structură include un câmp de tipul [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | struct kobject]].+Se observă că această structură include un câmp de tipul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | struct kobject]].
  
-O structură [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | struct kobject]] este definită astfel:+O structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | struct kobject]] este definită astfel:
  
 <code c> <code c>
Line 120: Line 120:
 </​code>​ </​code>​
  
-După cum se observă, structurile [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] sunt într-o ierarhie: un obiect are un părinte ​şi deţine un membru kset, care cuprinde obiecte de pe acelaşi nivel.+După cum se observă, structurile [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] sunt într-o ierarhie: un obiect are un părinte ​și deține un membru kset, care cuprinde obiecte de pe același nivel.
  
-Lucrul cu structura presupune iniţializarea ei, cu ajutorul funcţiei [[http://lxr.free-electrons.com/​source/​lib/​kobject.c?v=3.11#L268 | kobject_init]]. Tot în procesul de iniţializare este necesară stabilirea numelui structurii [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]], care va apărea în sysfs, cu ajutorul funcţiei [[http://lxr.free-electrons.com/​source/​lib/​kobject.c?v=3.11#L243 | kobject_set_name]].+Lucrul cu structura presupune inițializarea ei, cu ajutorul funcției [[http://elixir.free-electrons.com/linux/v4.9/​source/​lib/​kobject.c#​L313 | kobject_init]]. Tot în procesul de inițializare este necesară stabilirea numelui structurii [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]], care va apărea în sysfs, cu ajutorul funcției [[http://elixir.free-electrons.com/linux/v4.9/​source/​lib/​kobject.c#​L291 | kobject_set_name]].
  
-Orice operaţie asupra unui [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] se realizează prin incrementarea contorului intern al acestuia cu [[http://lxr.free-electrons.com/​source/​lib/​kobject.c?v=3.11#L525 | kobject_get]],​ sau decrementarea în cazul în care nu se mai foloseşte cu [[http://lxr.free-electrons.com/​source/​lib/​kobject.c?v=3.11#L594 | kobject_put]]. Astfel, un obiect de tip [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] nu va fi eliberat decât în momentul în care contorul intern al acestuia ajunge la valoarea 0. Este nevoie de o metodă de notificare a acestui lucru, pentru ca, apoi, să fie eliberate resursele asociate structurii de dispozitiv care includea [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | struct kobject]] (spre exemplu [[http://lxr.free-electrons.com/​source/​include/​linux/​cdev.h?v=3.11#L12 | cdev]]). Metoda se numeşte release ​şi este asociată obiectului prin intermediul câmpului ktype (de tip [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L108 | struct kobj_type]]).+Orice operație asupra unui [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] se realizează prin incrementarea contorului intern al acestuia cu [[http://elixir.free-electrons.com/linux/v4.9/​source/​lib/​kobject.c#​L587 | kobject_get]],​ sau decrementarea în cazul în care nu se mai folosește cu [[http://elixir.free-electrons.com/linux/v4.9/​source/​lib/​kobject.c#​L678 | kobject_put]]. Astfel, un obiect de tip [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] nu va fi eliberat decât în momentul în care contorul intern al acestuia ajunge la valoarea 0. Este nevoie de o metodă de notificare a acestui lucru, pentru ca, apoi, să fie eliberate resursele asociate structurii de dispozitiv care includea [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | struct kobject]] (spre exemplu [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​cdev.h#​L12 | cdev]]). Metoda se numește release ​și este asociată obiectului prin intermediul câmpului ktype (de tip [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L116 | struct kobj_type]]).
  
-Structura [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | struct kobject]] este structura de bază din Linux Device Model. Structurile din nivelurile mai înalte ale modelului sunt [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | struct bus_type]], [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | struct device]] ​şi [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L225 | struct device_driver]].+Structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | struct kobject]] este structura de bază din Linux Device Model. Structurile din nivelurile mai înalte ale modelului sunt [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]], [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | struct device_driver]].
  
 === Magistrale === === Magistrale ===
  
-O magistrală este un canal de comunicaţie între procesor ​şi un dispozitiv de intrare/ieşire. Pentru asigurarea genericităţii modelului, toate dispozitivele de intrare/ieşire sunt conectate la procesor prin intermediul unei astfel de magistrale (chiar dacă aceasta poate fi una virtuală fără un corespondent fizic hardware).+O magistrală este un canal de comunicație între procesor ​și un dispozitiv de intrare/ieșire. Pentru asigurarea genericității modelului, toate dispozitivele de intrare/ieșire sunt conectate la procesor prin intermediul unei astfel de magistrale (chiar dacă aceasta poate fi una virtuală fără un corespondent fizic hardware).
  
-La adăugarea unei magistrale în sistem, aceasta va apărea în sistemul de fişiere ''​sysfs'',​ în ''/​sys/​bus''​. Ca şi la structurile [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobjects]], magistralele pot fi organizate în ierarhii ​şi vor fi reprezentate astfel ​şi în ''​sysfs''​.+La adăugarea unei magistrale în sistem, aceasta va apărea în sistemul de fișiere ''​sysfs'',​ în ''/​sys/​bus''​. Ca și la structurile [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobjects]], magistralele pot fi organizate în ierarhii ​și vor fi reprezentate astfel ​și în ''​sysfs''​.
  
  
-În Linux Device Model, o magistrală este reprezentată de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | struct bus_type]]:+În Linux Device Model, o magistrală este reprezentată de structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]]:
  
 <code c> <code c>
Line 155: Line 155:
 </​code>​ </​code>​
  
-Se observă că unei magistrale îi este asociat un nume, liste de atribute default, o serie de funcţii specifice ​şi datele private ale driverului. Funcţia ''​uevent''​ (fostă ''​hotplug''​),​ este folosită în cazul dispozitivelor ''​hotplug''​.+Se observă că unei magistrale îi este asociat un nume, liste de atribute default, o serie de funcții specifice ​și datele private ale driverului. Funcția ''​uevent''​ (fostă ''​hotplug''​),​ este folosită în cazul dispozitivelor ''​hotplug''​.
  
-Operaţiile cu magistrala sunt operaţii de înregistrare,​ implementarea operaţiilor descrise în structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | struct bus_type]] ​şi operaţii de parcurgere ​şi inspecţie a dispozitivelor conectate la magistrală.+Operațiile cu magistrala sunt operații de înregistrare,​ implementarea operațiilor descrise în structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]] ​și operații de parcurgere ​și inspecție a dispozitivelor conectate la magistrală.
  
-Înregistrarea unei magistrale se realizează folosind [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L908 | bus_register]],​ iar deînregistrarea folosind [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L987 | bus_unregister]]:​+Înregistrarea unei magistrale se realizează folosind [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L879 | bus_register]],​ iar deînregistrarea folosind [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L965 | bus_unregister]]:​
  
 <spoiler onHidden="​Afișați exemplu implementare"​ onVisible="​Ascundeți exemplu implementare"​ > <spoiler onHidden="​Afișați exemplu implementare"​ onVisible="​Ascundeți exemplu implementare"​ >
Line 198: Line 198:
 \\ \\
  
-Funcţiile care vor fi iniţializate uzual în cadrul unei structuri [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | struct bus_type]] sunt ''​match'' ​şi ''​uevent'':​+Funcțiile care vor fi inițializate uzual în cadrul unei structuri [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]] sunt ''​match'' ​și ''​uevent'':​
  
 <code c> <code c>
Line 209: Line 209:
 static int my_match (struct device *dev, struct device_driver *driver) static int my_match (struct device *dev, struct device_driver *driver)
 { {
- return ​!strncmp (dev_name(dev),​ driver->​name,​ strlen (driver->​name));​+ return strncmp (dev_name(dev),​ driver->​name,​ strlen (driver->​name));​
 } }
    
Line 221: Line 221:
 </​code>​ </​code>​
  
-Funcţia ''​match''​ este utilizată în momentul în care se adaugă la magistrală un nou dispozitiv sau un nou driver. Rolul ei este de a realiza comparaţia între identificatorul dispozitivului ​şi cel al driverului. Funcţia ''​uevent''​ este apelată înainte de generarea unui eveniment de tip ''​hotplug''​ în user-space ​şi are drept rol adăugarea de variabile de mediu.+Funcția ''​match''​ este utilizată în momentul în care se adaugă la magistrală un nou dispozitiv sau un nou driver. Rolul ei este de a realiza comparația între identificatorul dispozitivului ​și cel al driverului. Funcția ''​uevent''​ este apelată înainte de generarea unui eveniment de tip ''​hotplug''​ în user-space ​și are drept rol adăugarea de variabile de mediu.
  
-Alte operaţii posibile în cazul unei magistrale sunt parcurgerea driverelor sau dispozitivelor ataşate acesteia. Deşi nu le putem accesa în mod direct (listele cu driverele ​şi dispozitive fiind stocate în datele private ale driverului, câmpul [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L126 | struct subsys_private *p]]), acestea pot fi parcurse cu ajutorul macrodefiniţiilor [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L286 | bus_for_each_dev]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L418 | bus_for_each_drv]].+Alte operații posibile în cazul unei magistrale sunt parcurgerea driverelor sau dispozitivelor atașate acesteia. Deși nu le putem accesa în mod direct (listele cu driverele ​și dispozitive fiind stocate în datele private ale driverului, câmpul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L134 | struct subsys_private *p]]), acestea pot fi parcurse cu ajutorul macrodefinițiilor [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L281 | bus_for_each_dev]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L431 | bus_for_each_drv]].
  
-Interfaţa ''​Linux Device Model''​ permite crearea de atribute pentru obiectele asociate. Aceste atribute vor avea drept corespondent un fişier în subdirectorul magistralei din ''​sysfs''​. Atributele asociate unei magistrale sunt descrise de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L43 | bus_attribute]]:​+Interfața ''​Linux Device Model''​ permite crearea de atribute pentru obiectele asociate. Aceste atribute vor avea drept corespondent un fișier în subdirectorul magistralei din ''​sysfs''​. Atributele asociate unei magistrale sunt descrise de structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L46 | bus_attribute]]:​
  
 <code c> <code c>
Line 237: Line 237:
 </​code>​ </​code>​
  
-De obicei, un atribut se defineşte cu ajutorul macrodefiniţiei [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L49 | BUS_ATTR]]. Pentru adăugarea/ştergerea unui atribut din cadrul structurii de magistrală se folosesc funcţiile [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L127 | bus_create_file]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​bus.c?v=3.11#L139 | bus_remove_file]].+De obicei, un atribut se definește cu ajutorul macrodefiniției [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L52 | BUS_ATTR]]. Pentru adăugarea/ștergerea unui atribut din cadrul structurii de magistrală se folosesc funcțiile [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L129 | bus_create_file]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​bus.c#​L141 | bus_remove_file]].
  
 Un exemplu de definire a unui atribut pentru magistrala ''​my_bus''​ este prezentat în continuare: Un exemplu de definire a unui atribut pentru magistrala ''​my_bus''​ este prezentat în continuare:
Line 287: Line 287:
 \\ \\
  
-Magistrala este reprezentată atât de un obiect [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | bus_type]], cât şi de un obiect [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | device]], aşa cum vom vedea în continuare (magistrala este şi ea un dispozitiv).+Magistrala este reprezentată atât de un obiect [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | bus_type]], cât și de un obiect [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | device]], așa cum vom vedea în continuare (magistrala este și ea un dispozitiv).
  
 === Dispozitive === === Dispozitive ===
  
-Orice dispozitiv din sistem are asociată o structură [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | struct device]]. Dispozitivele sunt descoperite prin diferite metode de kernel (hotplug, de către device drivere, la iniţializarea sistemului) ​şi sunt înregistrate în sistem. Toate dispozitivele prezente în kernel au câte o intrare în ''/​sys/​devices''​.+Orice dispozitiv din sistem are asociată o structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]]. Dispozitivele sunt descoperite prin diferite metode de kernel (hotplug, de către device drivere, la inițializarea sistemului) ​și sunt înregistrate în sistem. Toate dispozitivele prezente în kernel au câte o intrare în ''/​sys/​devices''​.
  
-La cel mai jos nivel, un dispozitiv în ''​Linux Device Model''​ este reprezentat de o structură [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | struct device]]:+La cel mai jos nivel, un dispozitiv în ''​Linux Device Model''​ este reprezentat de o structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]]:
  
 <code c> <code c>
Line 314: Line 314:
 </​code>​ </​code>​
  
-Printre câmpurile structurii se numără dispozitivul părinte care este de obicei un controller, obiectul [[http://lxr.free-electrons.com/​source/​include/​linux/​kobject.h?v=3.11#L60 | kobject]] asociat, magistrala pe care se găseşte, driverul care se ocupă de dispozitiv ​şi o funcţie apelată în momentul în care contorul dispozitivului ajunge la 0.+Printre câmpurile structurii se numără dispozitivul părinte care este de obicei un controller, obiectul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​kobject.h#​L63 | kobject]] asociat, magistrala pe care se găsește, driverul care se ocupă de dispozitiv ​și o funcție apelată în momentul în care contorul dispozitivului ajunge la 0.
  
-Ca de obicei, avem funcţii de înregistrare/​deînregistrare [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c?v=3.11#L1209 | device_register]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c?v=3.11#L1302 | device_unregister]].+Ca de obicei, avem funcții de înregistrare/​deînregistrare [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1185 | device_register]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1305 | device_unregister]].
  
-Pentru lucrul cu atributele avem structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L499 | struct device_attribute]],​ macrodefiniţia [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L525 | DEVICE_ATTR]] pentru definire ​şi funcţiile [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c?v=3.11#L612 | device_create_file]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c?v=3.11#L635 | device_remove_file]] pentru adăugarea atributului la dispozitiv.+Pentru lucrul cu atributele avem structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L549 | struct device_attribute]],​ macrodefiniția [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L575 | DEVICE_ATTR]] pentru definire ​și funcțiile [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L582 | device_create_file]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L606 | device_remove_file]] pentru adăugarea atributului la dispozitiv.
  
-Un lucru important de notat este faptul că, de obicei, nu se lucrează direct cu o structură de tip [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L689 | struct device]], ci cu o structură care o conţine pe aceasta, de forma:+Un lucru important de notat este faptul că, de obicei, nu se lucrează direct cu o structură de tip [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]], ci cu o structură care o conține pe aceasta, de forma:
  
 <code c> <code c>
Line 333: Line 333:
 </​code>​ </​code>​
  
-De obicei, un modul va exporta funcţii de înregistrare/​deînregistrare ale unui astfel de dispozitiv, după modelul prezentat mai jos:+De obicei, un modul va exporta funcții de înregistrare/​deînregistrare ale unui astfel de dispozitiv, după modelul prezentat mai jos:
  
 <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" > <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" >
Line 389: Line 389:
 \\ \\
  
-După cum se poate observa, funcţiile ''​my_register_device'' ​şi ''​my_unregister_device''​ de adăugare, respectiv scoatere a unui device de pe o magistrală sunt definite în fişierul în care este definită magistrala. Nu se iniţializează obiecte de tip dispozitiv; acestea se vor inţializa în momentul în care vor fi descoperite în sistem (prin hotplug sau înregistrare directă din driver) ​şi se va apela funcţia ''​my_register_device''​ pentru adăugarea la magistrală.+După cum se poate observa, funcțiile ''​my_register_device'' ​și ''​my_unregister_device''​ de adăugare, respectiv scoatere a unui device de pe o magistrală sunt definite în fișierul în care este definită magistrala. Nu se inițializează obiecte de tip dispozitiv; acestea se vor ințializa în momentul în care vor fi descoperite în sistem (prin hotplug sau înregistrare directă din driver) ​și se va apela funcția ''​my_register_device''​ pentru adăugarea la magistrală.
  
-Pentru utilizare (în implementarea driver-ului),​ trebuie declarată o structură de tipul celei exportate, iniţializată ​şi înregistrată cu metoda exportata de magistrală:​+Pentru utilizare (în implementarea driver-ului),​ trebuie declarată o structură de tipul celei exportate, inițializată ​și înregistrată cu metoda exportata de magistrală:​
  
 <spoiler onHidden="​Afișați exemplu înregistrare device"​ onVisible="​Ascundeți exemplu înregistrare device"​ > <spoiler onHidden="​Afișați exemplu înregistrare device"​ onVisible="​Ascundeți exemplu înregistrare device"​ >
Line 427: Line 427:
 === Drivere == === Drivere ==
  
-''​Linux Device Model''​ este folosit pentru a permite asocierea foarte uşoară între dispozitivele sistemului ​şi drivere. Driverele pot exporta informaţii independente de dispozitivul fizic din spate.+''​Linux Device Model''​ este folosit pentru a permite asocierea foarte ușoară între dispozitivele sistemului ​și drivere. Driverele pot exporta informații independente de dispozitivul fizic din spate.
  
-În ''​sysfs''​ informaţiile despre drivere nu au asociate un singur subdirector;​ ele se pot găsi în structura de directoare, în diferite locuri: în ''/​sys/​module''​ se găseşte modulul încărcat, în ''​devices''​ se poate găsi driverul asociat fiecărui device, în ''​classes''​ driverele care aparţin unei clase, în ''/​sys/​bus''​ driverele asociate fiecărei magistrale.+În ''​sysfs''​ informațiile despre drivere nu au asociate un singur subdirector;​ ele se pot găsi în structura de directoare, în diferite locuri: în ''/​sys/​module''​ se găsește modulul încărcat, în ''​devices''​ se poate găsi driverul asociat fiecărui device, în ''​classes''​ driverele care aparțin unei clase, în ''/​sys/​bus''​ driverele asociate fiecărei magistrale.
  
-Un device driver este identificat prin structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L194 | struct device_driver]]:​+Un device driver este identificat prin structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | struct device_driver]]:​
  
 <code c> <code c>
Line 453: Line 453:
 </​code>​ </​code>​
  
-Printre câmpurile structurii regăsim numele driver-ului (apare în ''​sysfs''​),​ magistrala cu care driverul lucrează ​şi funcţii apelate în diverse momente din funcţionarea unui dispozitiv.+Printre câmpurile structurii regăsim numele driver-ului (apare în ''​sysfs''​),​ magistrala cu care driverul lucrează ​și funcții apelate în diverse momente din funcționarea unui dispozitiv.
  
-Ca şi până acum, avem funcţiile de înregistrare/​deînregistrare [[http://lxr.free-electrons.com/​source/​drivers/​base/​driver.c?v=3.11#L157 | driver_register]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​driver.c?v=3.11#L199 | driver_unregister]].+Ca și până acum, avem funcțiile de înregistrare/​deînregistrare [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​driver.c#​L140 | driver_register]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​driver.c#​L182 | driver_unregister]].
  
-Pentru lucrul cu atributele avem structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L264 | struct driver_attribute]],​ macrodefiniţia [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L271 | DRIVER_ATTR]] pentru definire ​şi funcţiile [[http://lxr.free-electrons.com/​source/​drivers/​base/​driver.c?v=3.11#L101 | driver_create_file]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​driver.c?v=3.11#L118 | driver_remove_file]] pentru adăugarea atributului la dispozitiv.+Pentru lucrul cu atributele avem structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L301 | struct driver_attribute]],​ macrodefiniția [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L308 | DRIVER_ATTR]] pentru definire ​și funcțiile [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​driver.c#​L97 | driver_create_file]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​driver.c#​L115 | driver_remove_file]] pentru adăugarea atributului la dispozitiv.
  
-Ca şi în cazul dispozitivelor,​ structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L194 | struct device_driver]] este, de obicei, incorporată în cadrul unei alte structuri specifice unei anumite magistrale (''​PCI'',​ ''​USB'',​ etc.):+Ca și în cazul dispozitivelor,​ structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | struct device_driver]] este, de obicei, incorporată în cadrul unei alte structuri specifice unei anumite magistrale (''​PCI'',​ ''​USB'',​ etc.):
  
 <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" > <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" >
Line 500: Line 500:
 \\ \\
  
-Se observă că se exportă operaţiile de înregistrare/​deînregistrare de driver pentru folosire în cadrul altor module.+Se observă că se exportă operațiile de înregistrare/​deînregistrare de driver pentru folosire în cadrul altor module.
  
-Ca şi în cazul dispozitivelor, ​şi operaţiile cu drivere sunt definite la iniţializarea magistralei, ​şi sunt exportate pentru a putea fi folosite de drivere. În momentul în care se implementează un driver ce lucrează cu dispozitive ataşate la această magistrală,​ acesta va apela funcţiile ''​my_register_driver'' ​şi ''​my_unregister_driver''​ pentru a se asocia cu aceasta.+Ca și în cazul dispozitivelor, ​și operațiile cu drivere sunt definite la inițializarea magistralei, ​și sunt exportate pentru a putea fi folosite de drivere. În momentul în care se implementează un driver ce lucrează cu dispozitive atașate la această magistrală,​ acesta va apela funcțiile ''​my_register_driver'' ​și ''​my_unregister_driver''​ pentru a se asocia cu aceasta.
  
-Pentru utilizare (în implementarea driver-ului),​ trebuie declarată o structură de tipul celei exportate, iniţializată ​şi înregistrată cu metoda exportata de magistrală:​+Pentru utilizare (în implementarea driver-ului),​ trebuie declarată o structură de tipul celei exportate, inițializată ​și înregistrată cu metoda exportata de magistrală:​
  
 <code c> <code c>
Line 533: Line 533:
 === Clase === === Clase ===
  
-O clasă este o vedere de nivel înalt asupra ''​Linux Device Model'',​ care abstractizează detaliile de implementare. Spre exemplu, există drivere pentru discurile ''​SCSI'' ​şi drivere pentru discurile ''​ATA'',​ dar toate aparţin clasei discuri. Clasele asigură o grupare a dispozitivelor bazată pe funcţionalitate, nu pe modul în care sunt conectate sau cum funcţionează. Clasele au corespondent în ''/​sys/​classes''​.+O clasă este o vedere de nivel înalt asupra ''​Linux Device Model'',​ care abstractizează detaliile de implementare. Spre exemplu, există drivere pentru discurile ''​SCSI'' ​și drivere pentru discurile ''​ATA'',​ dar toate aparțin clasei discuri. Clasele asigură o grupare a dispozitivelor bazată pe funcționalitate, nu pe modul în care sunt conectate sau cum funcționează. Clasele au corespondent în ''/​sys/​classes''​.
  
-Există doua structuri principale care descriu clasele: [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L319 | struct class]] ​şi [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L722 | struct device]]. Structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L319 | class]] descrie o clasa generică, în timp ce structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L722 | struct device]] descrie o clasă asociată unui dispozitiv. Există funcţii pentru iniţializare/​deiniţializare ​şi adăugare de atribute pentru fiecare dintre acestea, descrise în ''​include/​linux/​device.h''​.+Există doua structuri principale care descriu clasele: [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L388 | struct class]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]]. Structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L388 | class]] descrie o clasa generică, în timp ce structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]] descrie o clasă asociată unui dispozitiv. Există funcții pentru inițializare/​deinițializare ​și adăugare de atribute pentru fiecare dintre acestea, descrise în ''​include/​linux/​device.h''​.
  
-Avantajul folosirii claselor este că programul udev din userspace, despre care vom discuta în continuare, permite crearea automată a dispozitivelor în directorul ''/​dev''​ pe baza informaţiilor clasei.+Avantajul folosirii claselor este că programul udev din userspace, despre care vom discuta în continuare, permite crearea automată a dispozitivelor în directorul ''/​dev''​ pe baza informațiilor clasei.
  
-Din acest motiv, vom prezenta în continuare un set restrâns de funcţii care lucrează cu clasele pentru a simplifica folosirea mecanismului de plug and play.+Din acest motiv, vom prezenta în continuare un set restrâns de funcții care lucrează cu clasele pentru a simplifica folosirea mecanismului de plug and play.
  
-O clasă generică este descrisă de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L319 | struct class]]:+O clasă generică este descrisă de structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L388 | struct class]]:
  
 <code c> <code c>
Line 564: Line 564:
 </​code>​ </​code>​
  
-Pentru iniţializare/​deiniţializare există funcţiile [[http://​lxr.free-electrons.com/​source/​include/​linux/​device.h#​L389 | class_register]] ​şi [[http://​lxr.free-electrons.com/​source/​drivers/​base/​class.c#​L211 | class_unregister]]:​+Pentru inițializare/​deinițializare există funcțiile [[http://​lxr.free-electrons.com/​source/​include/​linux/​device.h#​L389 | class_register]] ​și [[http://​lxr.free-electrons.com/​source/​drivers/​base/​class.c#​L211 | class_unregister]]:​
  
 <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" > <spoiler onHidden="​Afișați cod" onVisible="​Ascundeți cod" >
Line 597: Line 597:
 \\ \\
  
-O clasă asociată unui dispozitiv este descrisă de structura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L722 | device]]. Pentru iniţializare/​deiniţializare există funcţiile [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c#​L1689 | device_create]] ​şi [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c#​L1754 device destroy]]. Funcţia [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c#​L1689 | device_create]] iniţializează stuctura [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L722 | device]], îi asociază structura generică [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L319 | class]] ​şi dispozitivul ​primite ​ca parametru; în plus, va crea un atribut al clasei, ''​dev'',​ care conţine minorul ​şi majorul dispozitivului (''​minor:​major''​). Astfel, utilitarul ''​udev''​ din usermode poate citi datele necesare din acest fişier atribut pentru a crea un nod în directorul ''/​dev''​ apelând ''​makenod''​.+O clasă asociată unui dispozitiv este descrisă de structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | device]]. Pentru inițializare/​deinițializare există funcțiile [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1774 | device_create]] ​și [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1862 device_destroy]]. Funcția [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1774 | device_create]] inițializează stuctura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | device]], îi asociază structura generică [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L388 | class]] ​și dispozitivul ​primit ​ca parametru; în plus, va crea un atribut al clasei, ''​dev'',​ care conține minorul ​și majorul dispozitivului (''​minor:​major''​). Astfel, utilitarul ''​udev''​ din usermode poate citi datele necesare din acest fișier atribut pentru a crea un nod în directorul ''/​dev''​ apelând ''​makenod''​.
  
-Un exemplu de iniţializare:+Un exemplu de inițializare:
  
 <code c> <code c>
Line 615: Line 615:
 </​code>​ </​code>​
  
-În momentul în care un nou dispozitiv va fi descoperit, i se va asocia o clasă ​şi un nod în directorul ''/​dev''​. Pentru exemplul de mai sus, se va genera un nod ''/​dev/​myclass0''​.+În momentul în care un nou dispozitiv va fi descoperit, i se va asocia o clasă ​și un nod în directorul ''/​dev''​. Pentru exemplul de mai sus, se va genera un nod ''/​dev/​myclass0''​.
  
 ===== Hotplug ===== ===== Hotplug =====
Line 621: Line 621:
 ''​Hotplug''​ descrie mecanismul de adăugare sau eliminare a unui dispozitiv din sistem în timp ce acesta rulează, fără a fi necesară repornirea sistemului. ''​Hotplug''​ descrie mecanismul de adăugare sau eliminare a unui dispozitiv din sistem în timp ce acesta rulează, fără a fi necesară repornirea sistemului.
  
-Un eveniment ''​hotplug''​ este o notificare din partea kernel-ului către user-space atunci când se modifică ceva în configuraţia sistemului. Aceste evenimente sunt generate la crearea sau eliminarea unui obiect kobject din kernel. Întrucât aceste obiecte stau la baza ''​Linux Device Model'',​ fiind incluse în toate structurile ([[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L61 | struct bus_type]], [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h#​L722 | struct device]], [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L194 | struct device_driver]],​ [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L319 | struct class]], etc.), se va genera un eveniment ''​hotplug''​ la crearea sau eliminarea oricăreia dintre aceste structuri (''​uevent''​). +Un eveniment ''​hotplug''​ este o notificare din partea kernel-ului către user-space atunci când se modifică ceva în configurația sistemului. Aceste evenimente sunt generate la crearea sau eliminarea unui obiect kobject din kernel. Întrucât aceste obiecte stau la baza ''​Linux Device Model'',​ fiind incluse în toate structurile ([[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | struct bus_type]], [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L782 | struct device]], [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | struct device_driver]],​ [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L388 | struct class]], etc.), se va genera un eveniment ''​hotplug''​ la crearea sau eliminarea oricăreia dintre aceste structuri (''​uevent''​). 
-În momentul în care un dispozitiv este descoperit în sistem, se generează un eveniment. În funcţie de punctul în care se află în ''​Linux Device Model'',​ se vor apela funcţiile corespunzătoare apariţiei unui eveniment (de obicei, este cazul funcţiei ''​uevent''​ a magistralei sau clasei). Driverul are posibilitatea,​ prin intermediul acestor funcţii, să seteze variabile de sistem pentru user-space. Evenimentul generat ajunge în user-space apoi. Aici există utilitarul ''​udev'',​ care capturează aceste evenimente. În directorul ''/​etc/​udev/''​ există fişierele de configurare pentru acest utilitar. Se pot specifica diferite reguli pentru a captura numai anumite evenimente ​şi a executa anumite acţiuni, în funcţie de variabilele de sistem setate din kernel sau în funcţiile ''​uevent''​.+În momentul în care un dispozitiv este descoperit în sistem, se generează un eveniment. În funcție de punctul în care se află în ''​Linux Device Model'',​ se vor apela funcțiile corespunzătoare apariției unui eveniment (de obicei, este cazul funcției ''​uevent''​ a magistralei sau clasei). Driverul are posibilitatea,​ prin intermediul acestor funcții, să seteze variabile de sistem pentru user-space. Evenimentul generat ajunge în user-space apoi. Aici există utilitarul ''​udev'',​ care capturează aceste evenimente. În directorul ''/​etc/​udev/''​ există fișierele de configurare pentru acest utilitar. Se pot specifica diferite reguli pentru a captura numai anumite evenimente ​și a executa anumite acțiuni, în funcție de variabilele de sistem setate din kernel sau în funcțiile ''​uevent''​.
  
-O consecinţă importantă este că în acest mod se poate realiza mecanismul ''​plug and play'';​ cu ajutorul lui ''​udev''​ si a claselor, descrise anterior, se pot crea automat intrările în directorul ''/​dev''​ pentru dispozitive,​ iar cu ajutorul ''​udev''​ se pot încărca automat driverele necesare pentru un dispozitiv. În acest fel, întreg procesul este automatizat.+O consecință importantă este că în acest mod se poate realiza mecanismul ''​plug and play'';​ cu ajutorul lui ''​udev''​ si a claselor, descrise anterior, se pot crea automat intrările în directorul ''/​dev''​ pentru dispozitive,​ iar cu ajutorul ''​udev''​ se pot încărca automat driverele necesare pentru un dispozitiv. În acest fel, întreg procesul este automatizat.
  
-Regulile pentru ''​udev''​ sunt localizate în ''/​etc/​udev/​rules.d''​. Orice fişier de aici care se termină cu .conf va fi parsat la apariţia unui eveniment. Pentru mai multe detalii despre cum se scriu regulile în aceste fişiere consultaţi [[http://​www.reactivated.net/​writing_udev_rules.html | Writing udev rules]]. Pentru testare, există utilitarele ''​udevmonitor'',​ ''​udevinfo'' ​şi ''​udevtest''​.+Regulile pentru ''​udev''​ sunt localizate în ''/​etc/​udev/​rules.d''​. Orice fișier de aici care se termină cu .conf va fi parsat la apariția unui eveniment. Pentru mai multe detalii despre cum se scriu regulile în aceste fișiere consultați [[http://​www.reactivated.net/​writing_udev_rules.html | Writing udev rules]]. Pentru testare, există utilitarele ''​udevmonitor'',​ ''​udevinfo'' ​și ''​udevtest''​.
  
-Pentru un scurt exemplu, sa consideram situaţia în care dorim sa încarcăm automat un driver pentru un dispozitiv în momentul apariţiei unui eveniment. Putem crea un nou fişier ''/​etc/​udev/​rules.d/​myrules.rules'',​ în care vom avea următoarea linie:+Pentru un scurt exemplu, sa consideram situația în care dorim sa încarcăm automat un driver pentru un dispozitiv în momentul apariției unui eveniment. Putem crea un nou fișier ''/​etc/​udev/​rules.d/​myrules.rules'',​ în care vom avea următoarea linie:
  
 <code bash> <code bash>
Line 634: Line 634:
 </​code>​ </​code>​
  
-Astfel, se vor alege dintre evenimentele generate doar cele care aparţin subsistemului ''​pnp''​ (sunt conectate la magistrala PNP) şi au un atribut id cu valoarea ''​PNP0400''​. În momentul în care se va găsi această regulă, se va executa comanda ce inserează driverul corespunzător în kernel.+Astfel, se vor alege dintre evenimentele generate doar cele care aparțin subsistemului ''​pnp''​ (sunt conectate la magistrala PNP) și au un atribut id cu valoarea ''​PNP0400''​. În momentul în care se va găsi această regulă, se va executa comanda ce inserează driverul corespunzător în kernel.
  
 ===== Plug and Play ===== ===== Plug and Play =====
Line 640: Line 640:
 După cum s-a specificat mai sus, în ''​Linux Device Model''​ toate dispozitivele sunt conectate printr-o magistrală,​ chiar dacă are corespondent fizic hardware sau este virtuală. După cum s-a specificat mai sus, în ''​Linux Device Model''​ toate dispozitivele sunt conectate printr-o magistrală,​ chiar dacă are corespondent fizic hardware sau este virtuală.
  
-În kernel, există deja implementate majoritatea magistralelor prin definirea unei structuri [[http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L102 | bus_type]] ​şi a funcţiilor de înregistrare/​deînregistrare a driverelor ​şi dispozitivelor asociate. Pentru implementarea unui driver trebuie determinată magistrala la care se ataşează dispozitivele suportate ​şi trebuie folosite funcţiile şi structurile acesteia. Principalele magistrale sunt [[http://​lxr.free-electrons.com/​source/​drivers/​pci/​pci-driver.c?​v=3.11 | PCI]], [[http://​lxr.free-electrons.com/​source/​drivers/​usb/​core/​driver.c?​v=3.11 | USB]], [[http://​lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?​v=3.11 | PNP]], [[http://​lxr.free-electrons.com/​source/​drivers/​ide/​ide.c?​v=3.11 | IDE]], [[http://​lxr.free-electrons.com/​source/​drivers/​scsi/​scsi_sysfs.c?​v=3.11 | SCSI]], [[http://​lxr.free-electrons.com/​source/​drivers/​base/​platform.c?​v=3.11 | platform]], [[http://​lxr.free-electrons.com/​source/​drivers/​acpi/​scan.c?​v=3.11 | ACPI]], etc.+În kernel, există deja implementate majoritatea magistralelor prin definirea unei structuri [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L109 | bus_type]] ​și a funcțiilor de înregistrare/​deînregistrare a driverelor ​și dispozitivelor asociate. Pentru implementarea unui driver trebuie determinată magistrala la care se atașează dispozitivele suportate ​și trebuie folosite funcțiile și structurile acesteia. Principalele magistrale sunt [[http://​lxr.free-electrons.com/​source/​drivers/​pci/​pci-driver.c?​v=4.| PCI]], [[http://​lxr.free-electrons.com/​source/​drivers/​usb/​core/​driver.c?​v=4.| USB]], [[http://​lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?​v=4.| PNP]], [[http://​lxr.free-electrons.com/​source/​drivers/​ide/​ide.c?​v=4.| IDE]], [[http://​lxr.free-electrons.com/​source/​drivers/​scsi/​scsi_sysfs.c?​v=4.| SCSI]], [[http://​lxr.free-electrons.com/​source/​drivers/​base/​platform.c?​v=4.| platform]], [[http://​lxr.free-electrons.com/​source/​drivers/​acpi/​scan.c?​v=4.| ACPI]], etc.
  
 ==== Magistrala PNP ==== ==== Magistrala PNP ====
  
-Mecanismul plug and play oferă un mijloc de detectarea ​şi setare a resurselor pentru drivere legacy sau care nu pot fi configurate în alt mod. Toate driverele plug and play, protocoalele,​ serviciile au la bază nivelul ''​Plug and Play''​. Acesta este responsabil cu schimbul de informaţie între drivere ​şi protocoale. Următoarele protocoale sunt disponibile:​+Mecanismul plug and play oferă un mijloc de detectarea ​și setare a resurselor pentru drivere legacy sau care nu pot fi configurate în alt mod. Toate driverele plug and play, protocoalele,​ serviciile au la bază nivelul ''​Plug and Play''​. Acesta este responsabil cu schimbul de informație între drivere ​și protocoale. Următoarele protocoale sunt disponibile:​
  
-  * **PNPBIOS** - folosite pentru sisteme cum ar fi porturile seriale ​şi paralele+  * **PNPBIOS** - folosite pentru sisteme cum ar fi porturile seriale ​și paralele
   * **ISAPNP** - oferă suport pentru magistrala ISA   * **ISAPNP** - oferă suport pentru magistrala ISA
-  * **ACPI** - care oferă, printre altele, informaţii despre dispozitivele la nivel de sistem+  * **ACPI** - care oferă, printre altele, informații despre dispozitivele la nivel de sistem
  
-În kernel există o magistrala ''​pnp_bus'',​ care este folosită pentru conectare de multe drivere. Implementarea ​şi modul de lucru cu această magistrală respectă modelul ''​Linux Device Model'' ​şi este foarte asemănatoare cu ce s-a prezentat până acum.+În kernel există o magistrala ''​pnp_bus'',​ care este folosită pentru conectare de multe drivere. Implementarea ​și modul de lucru cu această magistrală respectă modelul ''​Linux Device Model'' ​și este foarte asemănatoare cu ce s-a prezentat până acum.
  
-Principalele funcţii şi structuri exportate de această magistrală, ​şi care pot fi folosite de către drivere sunt:+Principalele funcții și structuri exportate de această magistrală, ​și care pot fi folosite de către drivere sunt:
  
-  * [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]],​ tipul de driver asociat magistralei +  * [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]],​ tipul de driver asociat magistralei 
-  * [[http://lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?v=3.11#L224 | pnp_register_driver]],​ pentru a înregistra un driver pnp în sistem +  * [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​pnp/​driver.c#​L266 | pnp_register_driver]],​ pentru a înregistra un driver pnp în sistem 
-  * [[http://lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?v=3.11#L232 | pnp_unregister_driver]],​ pentru a deînregistra un driver pnp din sistem+  * [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​pnp/​driver.c#​L274 | pnp_unregister_driver]],​ pentru a deînregistra un driver pnp din sistem
  
-După cum am observat în secţiunile anterioare, magistrala are o funcţie ''​match''​ cu ajutorul căreia asociaza dispozitive cu driverele corespunzătoare. Spre exemplu, în cazul descoperirii unui dispozitiv, se va căuta driver-ul care îndeplineşte condiţia dată de această funcţie relativă la dispozitiv. De obicei, această condiţie reprezintă o comparaţie de id-uri ale driverului ​şi dispozitivului. Un mecanism răspândit este folosirea unei tabele statice în fiecare driver, ce conţine informaţii despre dispozitivele suportate de driver ​şi vor fi folosite de magistrală la comparaţie. Spre exemplu, pentru un driver de port paralel vom avea tabela ''​parport_pc_pnp_tbl'':​+După cum am observat în secțiunile anterioare, magistrala are o funcție ''​match''​ cu ajutorul căreia asociaza dispozitive cu driverele corespunzătoare. Spre exemplu, în cazul descoperirii unui dispozitiv, se va căuta driver-ul care îndeplinește condiția dată de această funcție relativă la dispozitiv. De obicei, această condiție reprezintă o comparație de id-uri ale driverului ​și dispozitivului. Un mecanism răspândit este folosirea unei tabele statice în fiecare driver, ce conține informații despre dispozitivele suportate de driver ​și vor fi folosite de magistrală la comparație. Spre exemplu, pentru un driver de port paralel vom avea tabela ''​parport_pc_pnp_tbl'':​
  
 <code c> <code c>
Line 673: Line 673:
 </​code>​ </​code>​
  
-Se declară ​şi iniţializează o structură [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]],​ cum ar fi ''​parport_pc_pnp_driver'':​+Se declară ​și inițializează o structură [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]],​ cum ar fi ''​parport_pc_pnp_driver'':​
  
 <code c> <code c>
Line 690: Line 690:
 </​code>​ </​code>​
  
-După cum se poate observa, structura are ca parametri un pointer către tabela declarată mai sus două funcţii care se apelează la detectarea unui dispozitiv, respectiv la eliminarea lui din sistem. La fel ca toate structurile prezentate, driver-ul trebuie înregistrat în sistem:+După cum se poate observa, structura are ca parametri un pointer către tabela declarată mai sus două funcții care se apelează la detectarea unui dispozitiv, respectiv la eliminarea lui din sistem. La fel ca toate structurile prezentate, driver-ul trebuie înregistrat în sistem:
  
 <code c> <code c>
Line 708: Line 708:
  
 </​code>​ </​code>​
-==== Operaţii PNP ====+==== Operații PNP ====
  
-Până acum am discutat despre modelul ''​Linux Device Model'' ​şi API-ul folosit. Pentru a implementa un driver plug and play, trebuie respectat modelul ''​Linux Device Model''​.+Până acum am discutat despre modelul ''​Linux Device Model'' ​și API-ul folosit. Pentru a implementa un driver plug and play, trebuie respectat modelul ''​Linux Device Model''​.
  
-De cele mai multe ori, adăugarea unei magistrale în kernel nu este necesară (bus), întrucât deja sunt implementate majoritatea magistralelor (''​PCI'',​ ''​USB'',​ etc.). Astfel, mai întâi trebuie identificată magistrala la care se ataşează dispozitivul. În exemplele de mai jos, vom considera că această magistrală este magistrala ''​PNP''​. Astfel, se vor folosi structurile ​şi funcţiile prezentate mai sus.+De cele mai multe ori, adăugarea unei magistrale în kernel nu este necesară (bus), întrucât deja sunt implementate majoritatea magistralelor (''​PCI'',​ ''​USB'',​ etc.). Astfel, mai întâi trebuie identificată magistrala la care se atașează dispozitivul. În exemplele de mai jos, vom considera că această magistrală este magistrala ''​PNP''​. Astfel, se vor folosi structurile ​și funcțiile prezentate mai sus.
  
 {{ :​so2:​laboratoare:​laboratoare-plug_and_play-linux_device_model_operations.png |}} {{ :​so2:​laboratoare:​laboratoare-plug_and_play-linux_device_model_operations.png |}}
Line 718: Line 718:
 === Adăugare driver === === Adăugare driver ===
  
-Pe lângă operaţiile uzuale, un driver trebuie să respecte modelul ''​Linux Device Model''​. Astfel, se va înregistra în sistem folosind funcţiile puse la dispoziţie de magistrală în acest scop. De obicei, magistrala pune la dispoziţie o structură particulară de driver, ce conţine o structură [[ http://lxr.free-electrons.com/​source/​include/​linux/​device.h?v=3.11#L225 | device_driver]],​ pe care driverul trebuie să o iniţializeze ​şi să o înregistreze cu o funcţie ''​*_register_driver''​. Spre exemplu, pentru magistrala ''​PNP'',​ driverul trebuie să declare ​şi să iniţializeze o structură de tipul [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]],​ pe care să o înregistreze cu [[http://lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?v=3.11#L224 | pnp_register_driver]]:​+Pe lângă operațiile uzuale, un driver trebuie să respecte modelul ''​Linux Device Model''​. Astfel, se va înregistra în sistem folosind funcțiile puse la dispoziție de magistrală în acest scop. De obicei, magistrala pune la dispoziție o structură particulară de driver, ce conține o structură [[ http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​device.h#​L264 | device_driver]],​ pe care driverul trebuie să o inițializeze ​și să o înregistreze cu o funcție ''​*_register_driver''​. Spre exemplu, pentru magistrala ''​PNP'',​ driverul trebuie să declare ​și să inițializeze o structură de tipul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]],​ pe care să o înregistreze cu [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​pnp/​driver.c#​L266 | pnp_register_driver]]:​
  
 <code c> <code c>
Line 736: Line 736:
 </​code>​ </​code>​
  
-Spre deosebire de driverele legacy, driverele plug and play nu înregistrează dispozitivele la iniţializare, în funcţia ''​my_init''​ (''​register_device''​). +Spre deosebire de driverele legacy, driverele plug and play nu înregistrează dispozitivele la inițializare, în funcția ''​my_init''​ (''​register_device''​). 
-După cum s-a descris mai sus, fiecare magistrală are o funcţie ''​match''​ care se apelează la detectarea unui dispozitv pentru a determina driverul asociat acestuia. Prin urmare, trebuie să existe o modalitate ca fiecare driver să exporte informaţii despre ce dispozitive suportă, pentru a putea trece de această comparaţie şi pentru a fi apelate funcţiile sale. În exemplele prezentate în laborator, se face o simplă comparaţie între numele dispozitivului ​şi numele driver-ului. Cele mai multe drivere folosesc o tabelă cu informaţii despre dispozitiv, pentru care au un pointer în structura driver-ului. Spre exemplu, un driver asociat cu o magistrală ''​PNP'',​ declară o tabelă de tipul [[http://lxr.free-electrons.com/​source/​include/​linux/​mod_devicetable.h?v=3.11#L197 | pnp_device_id]], ​şi iniţializează câmpul ''​id_table''​ din structura [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]] cu un pointer către aceasta:+După cum s-a descris mai sus, fiecare magistrală are o funcție ''​match''​ care se apelează la detectarea unui dispozitv pentru a determina driverul asociat acestuia. Prin urmare, trebuie să existe o modalitate ca fiecare driver să exporte informații despre ce dispozitive suportă, pentru a putea trece de această comparație și pentru a fi apelate funcțiile sale. În exemplele prezentate în laborator, se face o simplă comparație între numele dispozitivului ​și numele driver-ului. Cele mai multe drivere folosesc o tabelă cu informații despre dispozitiv, pentru care au un pointer în structura driver-ului. Spre exemplu, un driver asociat cu o magistrală ''​PNP'',​ declară o tabelă de tipul [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​mod_devicetable.h#​L199 | pnp_device_id]], ​și inițializează câmpul ''​id_table''​ din structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]] cu un pointer către aceasta:
  
 <code c> <code c>
Line 759: Line 759:
 </​code>​ </​code>​
  
-În exemplul de mai sus driver-ul suportă operaţii pentru portul paralel. Aceaste informaţii sunt folosite de magistrală,​ în funcţia ''​match_device''​. La adăugarea unui driver, se va asocia driverul magistralei ​şi se vor crea intrări în ''​sysfs''​ bazate pe numele driver-ului. Apoi se va apela funcţia ''​match''​ a magistralei pentru toate dispozitivele asociate, pentru a asocia driver-ul cu orice dispozitiv conectat pe care îl suportă.+În exemplul de mai sus driver-ul suportă operații pentru portul paralel. Aceaste informații sunt folosite de magistrală,​ în funcția ''​match_device''​. La adăugarea unui driver, se va asocia driverul magistralei ​și se vor crea intrări în ''​sysfs''​ bazate pe numele driver-ului. Apoi se va apela funcția ''​match''​ a magistralei pentru toate dispozitivele asociate, pentru a asocia driver-ul cu orice dispozitiv conectat pe care îl suportă.
  
 === Eliminare driver === === Eliminare driver ===
  
-Pentru a elimina un driver din kernel, pe lângă operaţiile necesare unui driver legacy, trebuie deînregistrată structura device_driver. În cazul unui driver pentru un dispozitiv asociat magistralei ''​PNP'',​ trebuie deînregistrată structura [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]] cu ajutorul funcţiei [[http://lxr.free-electrons.com/​source/​drivers/​pnp/​driver.c?v=3.11#L232 | pnp_unregister_driver]]:​+Pentru a elimina un driver din kernel, pe lângă operațiile necesare unui driver legacy, trebuie deînregistrată structura device_driver. În cazul unui driver pentru un dispozitiv asociat magistralei ''​PNP'',​ trebuie deînregistrată structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]] cu ajutorul funcției [[http://elixir.free-electrons.com/linux/v4.9/​source/​drivers/​pnp/​driver.c#​L274 | pnp_unregister_driver]]:​
  
 <code c> <code c>
Line 776: Line 776:
 </​code>​ </​code>​
  
-Spre deosebire de driverele legacy, driverele plug and play nu deînregistrează dispozitivele la deînregistrarea driver-ului,​ în funcţia ''​my_exit''​ (unregister_device). La eliminarea unui driver, se vor elimina toate referinţele către el pentru toate dispozitivele pe care le suportă ​şi se vor şterge intrările din ''​sysfs''​.+Spre deosebire de driverele legacy, driverele plug and play nu deînregistrează dispozitivele la deînregistrarea driver-ului,​ în funcția ''​my_exit''​ (unregister_device). La eliminarea unui driver, se vor elimina toate referințele către el pentru toate dispozitivele pe care le suportă ​și se vor șterge intrările din ''​sysfs''​.
  
 === Adăugare dispozitiv === === Adăugare dispozitiv ===
  
-Dupa cum am văzut mai sus, driverele plug and play nu înregistrează dispozitivele la iniţializare. Această operaţie se va realiza în funcţia ''​probe'',​ care se va apela la detectarea unui dispozitiv. În cazul unui driver pentru un dispozitiv ataşat la magistrala ''​PNP'',​ adăugarea se va realiza în funcţia ''​probe''​ din structura [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]]:​+Dupa cum am văzut mai sus, driverele plug and play nu înregistrează dispozitivele la inițializare. Această operație se va realiza în funcția ''​probe'',​ care se va apela la detectarea unui dispozitiv. În cazul unui driver pentru un dispozitiv atașat la magistrala ''​PNP'',​ adăugarea se va realiza în funcția ''​probe''​ din structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]]:​
  
 <code c> <code c>
Line 808: Line 808:
 </​code>​ </​code>​
  
-La detectarea unui dispozitiv în kernel (în procesul de boot sau la adăugarea dispozitivului prin ''​hotplug''​),​ se transmite o întrerupere în sistem care ajunge la magistrală. Dispozitivul este înregistrat cu ajutorul funcţiei [[http://lxr.free-electrons.com/​source/​drivers/​base/​core.c?v=3.11#L1209 | device_register]] ​şi este ataşat magistralei (şi se va genera un apel în userspace, care poate fi detectat de ''​udev''​). Apoi se va parcurge lista de drivere a magistralei ​şi se va apela funcţia ''​match''​ pentru fiecare dintre ele. Funcţia ''​match''​ încearcă să asocieze un driver cu un dispozitiv. După ce a fost determinat driverul asociat dispozitivului,​ se va apela funcţia ''​probe''​ a driver-ului. Dacă funcţia se termină cu succes, dispozitivul este adăugat în lista de dispozitive a driver-ului ​şi se creează intrările corespunzătoare în ''​sysfs''​ bazate pe numele dispozitivului.+La detectarea unui dispozitiv în kernel (în procesul de boot sau la adăugarea dispozitivului prin ''​hotplug''​),​ se transmite o întrerupere în sistem care ajunge la magistrală. Dispozitivul este înregistrat cu ajutorul funcției [[https://elixir.bootlin.com/linux/v4.9/​source/​drivers/​base/​core.c#​L1185 | device_register]] ​și este atașat magistralei (și se va genera un apel în userspace, care poate fi detectat de ''​udev''​). Apoi se va parcurge lista de drivere a magistralei ​și se va apela funcția ''​match''​ pentru fiecare dintre ele. Funcția ''​match''​ încearcă să asocieze un driver cu un dispozitiv. După ce a fost determinat driverul asociat dispozitivului,​ se va apela funcția ''​probe''​ a driver-ului. Dacă funcția se termină cu succes, dispozitivul este adăugat în lista de dispozitive a driver-ului ​și se creează intrările corespunzătoare în ''​sysfs''​ bazate pe numele dispozitivului.
  
 === Eliminare dispozitiv === === Eliminare dispozitiv ===
  
-Dupa cum am văzut mai sus, driverele plug and play nu deînregistrează dispozitivele la deînregistrarea driver-ului. Această operaţie se va realiza în funcţia ''​remove'',​ care se va apela la detectarea eliminării unui dispozitiv din kernel. În cazul unui driver pentru un dispozitiv ataşat la magistrala ''​PNP'',​ adăugarea se va realiza în funcţia ''​remove''​ din structura [[http://lxr.free-electrons.com/​source/​include/​linux/​pnp.h?v=3.11#L370 | pnp_driver]]:​+Dupa cum am văzut mai sus, driverele plug and play nu deînregistrează dispozitivele la deînregistrarea driver-ului. Această operație se va realiza în funcția ''​remove'',​ care se va apela la detectarea eliminării unui dispozitiv din kernel. În cazul unui driver pentru un dispozitiv atașat la magistrala ''​PNP'',​ adăugarea se va realiza în funcția ''​remove''​ din structura [[http://elixir.free-electrons.com/linux/v4.9/​source/​include/​linux/​pnp.h#​L380 | pnp_driver]]:​
  
 <code c> <code c>
Line 827: Line 827:
 </​code>​ </​code>​
  
-După cum se poate observa, la detectarea eliminării unui dispozitiv din sistem, se va apela funcţia remove a driver-ului,​ se va genera un apel în user-space, ce poate fi detectat de ''​udev'' ​şi se vor elimina intrările din ''​sysfs''​.+După cum se poate observa, la detectarea eliminării unui dispozitiv din sistem, se va apela funcția remove a driver-ului,​ se va genera un apel în user-space, ce poate fi detectat de ''​udev'' ​și se vor elimina intrările din ''​sysfs''​. 
 ===== Resurse utile ===== ===== Resurse utile =====
  
so2/laboratoare/lab12.1400051645.txt.gz · Last modified: 2014/05/14 10:14 by constantin.serban1512
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