This shows you the differences between two versions of the page.
so2:laboratoare:lab12 [2014/05/14 10:18] razvan.deaconescu [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''. | ||
Line 22: | Line 22: | ||
===== 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 ===== | ||
Line 38: | Line 38: | ||
Î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) | ||
Line 57: | Line 57: | ||
* **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 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 502: | Line 502: | ||
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. | ||
Line 541: | Line 541: | ||
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: | ||
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.9 | PCI]], [[http://lxr.free-electrons.com/source/drivers/usb/core/driver.c?v=4.9 | USB]], [[http://lxr.free-electrons.com/source/drivers/pnp/driver.c?v=4.9 | PNP]], [[http://lxr.free-electrons.com/source/drivers/ide/ide.c?v=4.9 | IDE]], [[http://lxr.free-electrons.com/source/drivers/scsi/scsi_sysfs.c?v=4.9 | SCSI]], [[http://lxr.free-electrons.com/source/drivers/base/platform.c?v=4.9 | platform]], [[http://lxr.free-electrons.com/source/drivers/acpi/scan.c?v=4.9 | 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 710: | Line 710: | ||
==== 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 737: | Line 737: | ||
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 ===== |