Arhiva de suport pentru exerciții se găsește aici. Descărcați arhiva și apoi decomprimați-o folosind comanda
unzip cap-12-tasks.zip
Parcurgere sysfs
Linux Device Model / Linux Device Tree
Major și minor, /dev
, /proc/devices
Operații pe dispozitive: structura cdev
, structura file_operations
Subsisteme de I/O: video4linux
, mem
drivers (zero
, null
, full
, random
, urandom
, mem
, kmem
, port
)
Comunicarea și interacțiunea dintre user space și kernel space se poate face prind dispozitive (devices). Acestea sunt vizibile utilizatorului ca intrări în sistemul de fișier (de obicei în /dev
) pe care acesta le poate opera.
În directorul ioctl-print/
avem un modul de kernel care expunde dispozitivul /dev/print
și care, la operații de tip ioctl (Input/Output Control
) afișează un mesaj. Este un modul didactic, vrem să urmărim comportamentul ioctl.
Pentru a putea observa apelul ioctl()
folosim și un modul de test rulabil din user space, care este compilat static în executabilul print_test
.
kernel/
în vreme ce testul de user space se găsește în subdirectorul user/
.
Atât fișierul de test cât și fișierul modul se copiază pe mașina virtuală pentru a putea testa funcționalitatea respectivă: afișarea unui mesaj la apelul ioctl()
.
După ce modulul este inserat, trebuie creat dispozitivul /dev/print
cu ajutorul comenzii
mknod /dev/print c 42 0
Apoi se poate rula executabilul de test cu opțiunea aferentă pentru a invoca funcționalitatea de tip ioctl:
./print_test p
Actualizați modulul anterior și adăugați două noi operații la ioctl
, astfel încât la una dintre ele să aloce o zonă de memorie de 10KB și să rețină pointer-ul rezultat într-o variabilă globală, iar la cealaltă să-l elibereze.
Nu va aloca dacă a fost deja alocată zona de memorie, nu o va elibera dacă a fost deja eliberată.
include/util.h
.
Implementarea noilor operații o veți face în cadrul blocului switch
din funcția print_ioctl()
.
Operațiile de tipul ioctl
sunt operații de comandă/control. Pentru transfer de informație cel mai adesea follosim operații de tipul read
și write
. Pentru început să folosim operația read
.
În directorul read-string/
din arhiva de suport a capitolului se găsește o implementare de modul care întoarce un șir predefinit (anaaremere) la orice operație de citire. Practic, oricând folosim comanda cat
pe dispozitivul afernet (/dev/string
) ne va afișa șirul predefinit.
Compilați modululul și apoi copiați-l pe mașina virtuală QEMU și testați această funcționalitate.
mknod /dev/string c 43 0
Apoi, pentru a testa, folosiți comanda cat
pe dispozitiv, pentru a citi șirul:
cat /dev/string
În modul vor fi, pentru fiecare apel al funcției string_read()
, afișate niște mesaje legat de numărul de octeți care s-au dorit citiți și numărul de octeți care s-a citit. De câte ori a fost apelată funcția string_read()
? Cum explicați mesajele afișate (în fapt ne interesează valorile de retur ale funcției)?
Creați un modul de kernel care expune un dispozitiv /dev/one
care la citire generează o infinnitate de caractere de 1
. Se oprește doar când cere spațiul utilizator să se oprească. Este similar cu /dev/zero
.
Adăugați funcționalitatea de write
modulului din directorul read-string/
astfel încât sa și permită scrierea de mesaje în dispozitiv. După ce un mesaj este scris, același mesaj este citit de operațiile de citire.
echo "mesaj" > <fisier>
unde <fisier>
este numele intrării în care vreți să scrieți, de exemplu /dev/string
.
Actualizați modulul de mai sus astfel încât la citire să nu mai întoarcă șirul scris, ci un șir de cifre care să însemne lungimea șirului scris anterior.