This is an old revision of the document!
Pentru rezolvarea laboratorului, vom lucra în același director din care pornim mașina virtuală (~/so2/linux/tools/labs
).
Pașii de rezolvare sunt următorii:
Scheletul de laborator este generat din sursele din directorul tools/labs/templates
. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda:
tools/labs $ make skels
Pentru a genera scheletul pentru un singur laborator, vom folosi variabila de mediu LABS
:
tools/labs $ make clean tools/labs $ LABS=<lab name> make skels
device_model
.
Similar, putem genera și scheletul pentru un singur exercițiu, atribuind valoarea <lab_name>/<task_name>
variabilei LABS
.
tools/labs/skels
.
Comanda make build
compilează toate modulele din directorul skels
.
student@eg106:~/so2/linux/tools/labs$ make build echo "# autogenerated, do not edit " > skels/Kbuild echo "ccflags-y += -Wno-unused-function -Wno-unused-label -Wno-unused-variable " >> skels/Kbuild for i in ./device_model; do echo "obj-m += $i/" >> skels/Kbuild; done ...
Putem copia modulele generate pe mașina virtuală folosind target-ul copy
al comenzii make, atunci când mașina virtuală este oprită.
student@eg106:~/so2/linux/tools/labs$ make copy student@eg106:~/so2/linux/tools/labs$ make boot
Alternativ, putem copia fișierele prin scp
, pentru e evita repornirea mașinii virtuale. Pentru detalii despre folosirea interacțiunea prin rețea cu mașina virtuală citiți Interacțiunea cu mașina virtuală.
Modulele generate sunt copiate pe mașina virtuală în directorul /home/root/skels/<lab_name>
.
root@qemux86:~/skels/device_model# ls bex.ko bex_misc.ko
După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU (sau în minicom
) pentru a încărca și descărca modulul de kernel:
root@qemux86:~# insmod skels/<lab_name>/<task_name>/<module_name>.ko root@qemux86:~# rmmod skels/<lab_name>/<task_name>/<module_name>.ko
Ctrl+Shift+t
. Cele trei tab-uri de terminal îndeplinesc următoarele roluri:
~/so2/linux/tools/labs
.~/so2/linux/
cu sursele nucleului unde putem folosi Vim și cscope pentru parcurgerea codului sursă.student@eg106-pc:~$ netcat -lup 6666
git pull --rebase
in directorul ~/so2/linux
, pentru a obține ultima versiune a scheletului de laborator.
Vă mulțumim! Găsiți definițiile următoarelor simboluri în nucleul Linux:
dev_name
, dev_set_name
.pnp_device_probe
, pnp_bus_match
, pnp_register_driver
și variabila pnp_bus_type
.Apreciem opinia voastră legată de activitățile cursului de SO2. Ne ajută să îmbunătățim cursul și să facem materia cât mai accesibilă și interesantă. Pentru această vă rugăm să completați formularul de feedback de pe cs.curs.pub.ro (trebuie să fiți autentificați și înrolați în cadrul cursului). Vă mulțumim!
Analizați conținutul fișierului bex.c
, care conține implementarea unui driver de magistrală. Urmăriți comentariile marcate cu TODO 1
pentru a implementa părțile ce lipsesc: înregistrați driverul de magistrală și adăugați un nou device, numit root
, cu tipul none
și versiunea 1
.
bex_add_dev()
.
Compilați, copiați modulul pe mașina virtuală, încărcați-l în kernel și verificați faptul că dispozitivul de tip magistrală este vizibil în /sys/bus
. De asemenea, verificați că dispozitivul este vizibil în /sys/bus/bex/devices.
.
Eliminați modulul și observați că intrările din sysfs
sunt eliminate.
Adăugați două atribute read-only: type
și version
. Urmăriți comentariile marcate cu TODO 2
.
type
și version în structura
bus_dev_attrs pe modelul:
<code>
&dev_attr_<insert-attribute-type-here>.attr,
</code>
</note>
Observați că cele două atribute noi sunt vizibile în
/sys/bus/bex/devices/root. Verificați conținutul acestor atribute.
O implementare pentru funcția de afișare de type este
<code c>
static ssize_t
type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bex_device *bex_dev = to_bex_device(dev);
return sprintf(buf, ”%s\n”, bex_dev→type);
}
DEVICE_ATTR_RO(type);
</code>
==== 3. [2p] Adăugare atribute del și add ====
Adăugați două atribute write-only, numite
del și
add.
del așteaptă un nume de device pentru a îl elimina, iar
add așteaptă numele, tipul și versiunea pentru a crea un device noi. Urmăriți comentariile marcate cu
TODO 3.
<note tip>
Va trebui să adăugați atributele
del și
add în structura
bex_bus_attr pe modelul:
<code>
&bus_attr_<insert-attribute-name-here>.attr,
</code>
</note>
<note tip>
Folosiți
sscanf pentru a parsa inputul de la
sysfs și
bex_del_dev() and
bex_add_dev() pentru a șterge și crea un device nou.
</note>
Un exemplu de funcție de tipul
store este:
<code c>
static ssize_t
add_store(struct bus_type *bt, const char *buf, size_t count)
{
char type[32], name[32];
int version;
int ret;
ret = sscanf(buf, ”%31s %31s %d”, name, type, &version);
if (ret != 3)
return -EINVAL;
return bex_add_dev(name, type, version) ? : count;
}
BUS_ATTR(add, S_IWUSR, NULL, add_store);
</code>
Creați un device nou și verificați dacă este vizibil în
/sys/bus/bex/devices. Eliminați-l și verificați că a dispărut din
sysfs.
<note tip>
Folosiți
echo pentru a scrie în atributele magistralei:
<code>
$ echo “name type 1” > /sys/bus/bex/add
$ echo “name” > /sys/bus/bex/del
</code>
</note>
==== 4. [2p] Înregistrarea driver-ului bex misc ====
Modificați fișierul
bex-misc.c pentru a înregistra driver-ul la magistrala
bex.
Inserați modulul bex_misc.ko și creați un nou device de tip
bex din
sysfs, cu numele Test, tipul misc și versiunea 2. Urmăriți comentariile marcate cu
TODO 4.
Verificați dacă noul driver este vizibil în
/sys/bus/bex/drivers.
De ce nu este apelată funcția
probe?
<note tip>
Observați faptul că funcția de
match pentru magistrală nu este implementată în
bex.c.
</note>
Implementați funcția pentru match în fișierul
bex.c. Urmăriți comentariile marcate cu
TODO 5.
Încercați din nou adăugarea unui dispozitiv de tip
bex și observați că de data aceasta funcția de
probe este apelată.
==== 5. [1.5p] Înregistrarea unui device bex misc în funcția probe ====
Modificați
bex.c astfel încât operația
probe să eșueze dacă
version > 1. Înregistrați device-ul misc în funcția
bex_misc_probe și deînregistrați-l în
bex_misc_remove. Urmăriți comentariile marcate cu
TODO 6.
<note tip>
Folosiți
misc_register() and
misc_deregister().
</note>
Creați un device nou cu numele test, tipul misc și versiunea 2 și verificați că operația
probe eșuează.
Creați un nou device cu numele test, tipul misc și versiunea 1 și verificați că operația se termină cu succes.
Verificați conținutul fișierului
/sys/bus/bex/devices/test și observați că există o nouă intrare. Identificați majorul și minorul pentru device-ul
misc, creați un device node de tip caracter pentru acest dispozitiv (
Hint: mknod) și încercați operații de citire și scriere pe fișierul creat, pentru a accesa buffer-ul dispozitivului.
<note tip>
Indicatorii
major și
minor sunt vizibili în atributul
dev al dispozitivului de tip
misc.
</note>
==== 6. [1p] Monitorizarea notificărilor uevent ====
Folosiți comanda
udevadm și observați ce se întâmplă când:
* modulele
bex.ko and
bex_misc.ko'' sunt inserate