This shows you the differences between two versions of the page.
so2:laboratoare:lab12 [2016/05/18 15:28] razvan.deaconescu [Structuri de bază în dispozitivele Linux] |
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 ===== | ||
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 === | ||
Line 132: | Line 132: | ||
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 157: | Line 157: | ||
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 223: | Line 223: | ||
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 431: | Line 431: | ||
Î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 455: | Line 455: | ||
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 535: | Line 535: | ||
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 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?v=3.13#L1662 | 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 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''. | + | 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 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''. | ||
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 ==== | ||
Line 654: | Line 654: | ||
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'': | ||
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 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 763: | Line 763: | ||
=== 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 780: | Line 780: | ||
=== 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> |