Laborator 12: Exerciții

Pregătirea laboratorului

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:

  • pregătirea scheletului de laborator
  • compilarea modulelor de Kernel
  • copierea modulelor pe mașina virtuală
  • pornirea mașinii virtuale și testarea modulelor

Pregătirea scheletului de laborator

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

Numele laboratorului curent este device_model.

Similar, putem genera și scheletul pentru un singur exercițiu, atribuind valoarea <lab_name>/<task_name> variabilei LABS.

Scheletul este generat în directorul tools/labs/skels.

Compilarea modulelor

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
...

Copierea modulelor pe mașina virtuală

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ă.

Testarea modulelor

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

Pentru dezvoltarea laboratorului, este recomandat să folosim trei terminale sau, mai bine, trei tab-uri de terminal. Pentru a deschide un nou tab de terminal folosim combinația de taste Ctrl+Shift+t. Cele trei tab-uri de terminal îndeplinesc următoarele roluri:

  1. În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului.
  2. În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ~/so2/linux/tools/labs.
  3. În al treilea tab de terminal accesăm directorul ~/so2/linux/ cu sursele nucleului unde putem folosi Vim și cscope pentru parcurgerea codului sursă.
    student@eg106-pc:~$ netcat -lup 6666

Exerciții

Înainte de începerea rezolvării laboratorului, rulați comanda git pull --rebase in directorul ~/so2/linux, pentru a obține ultima versiune a scheletului de laborator.

[0.5p] Intro

Bonus - 1 punct: Vă invităm să evaluați activitatea echipei de SO2 și să precizați punctele tari și punctele slabe și sugestiile voastre de îmbunătățire a materiei. Feedback-ul vostru este foarte important pentru noi să creștem calitatea materiei în anii următori și să îmbunătățim materiile pe care le veți face în continuare. Găsiți formularul de feedback în partea dreaptă a paginii principale de SO2 de pe cs.curs.pub.ro într-un frame numit “FEEDBACK”

Vă mulțumim! Găsiți definițiile următoarelor simboluri în nucleul Linux:

  • funcțiile dev_name, dev_set_name.
  • funcțiile pnp_device_probe, pnp_bus_match, pnp_register_driver și variabila pnp_bus_type.

Completare formular de feedback

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!

1. [2p] Implementare bus

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.

Aruncați o privire pe implementarea funcției 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.

2. [2p] Adăugare atribute pentru tip și versiune

Adăugați două atribute read-only: type și version. Urmăriți comentariile marcate cu TODO 2.

Va trebui să adăugați cele două atribute type și version în structura bus_dev_attrs pe modelul:

&dev_attr_<insert-attribute-type-here>.attr,

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

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);

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.

Va trebui să adăugați atributele del și add în structura bex_bus_attr pe modelul:

&bus_attr_<insert-attribute-name-here>.attr,

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.

Un exemplu de funcție de tipul store este:

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);

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.

Folosiți echo pentru a scrie în atributele magistralei:

$ echo "name type 1" > /sys/bus/bex/add
$ echo "name" > /sys/bus/bex/del

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?

Observați faptul că funcția de match pentru magistrală nu este implementată în bex.c.

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_misc.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.

Folosiți misc_register() and misc_deregister().

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.

Indicatorii major și minor sunt vizibili în atributul dev al dispozitivului de tip misc.

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
  • un nou device cu tipul test este creat
  • un nou device cu tipul misc și versiunea 2 este creat
  • un nou device cu tipul misc și versiunea 1 este creat
  • toate de mai sus sunt eliminate
so2/laboratoare/lab12/exercitii.txt · Last modified: 2018/05/16 13:38 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0