Katalog /dev zawiera pliki urządzeń (device nodes). Przykładowo:
- /dev/hda1 - plik odpowiedzialny za pierwszą partycję dysku twardego
- /dev/console - plik odpowiedzialny za klawiaturę
- /dev/cdrom - plik odpowiedzialny za napęd CDROM
Za pomocą device nodes aplikacja może porozumiewać się ze sterownikiem urządzenia.
Z kolei w pliku /proc/devices znajduje się lista sterowników urządzeń, które są akutalnie skonfigurowane i działające.
Obecnie jesteśmy na etapie gdzie nasze urządzenie jest widoczne pod odpaleniu sterownika w /proc/devices, jednak nie jest widoczne w katalogu /dev/. Zatem póki co nie możemy wykorzystać sterownika w żadnej aplikacji pisanej z poziomu user-space, ponieważ brakuje elementu pośredniczącego między aplikacją a samym sterownikiem.
Wpisy w /dev/ możemy dodawać ręcznie za pomocą polecenia:
mknod /dev/"nazwa_pliku_urzadzenia" c "numer major" "numer minor"
np. mknod /dev/char_device c 250 0
Plik urządzenia powinien być widoczny i gotowy do użycia. Pamiętajcie, aby użyć takie numery major i minor, które zostały przydzielone wcześniej do urządzenia. Używanie mknod za każdym razem byłoby dość upierdliwe, zajmiemy się więc tym jak wykonać automatyczne tworzenie device node'a dla naszego urządzenia.
Użyjemy do tego:
Dodajemy nagłówek <linux/device.h> oraz makro MODULE_LICENSE("GPL") i tworzymy device node:
struct class *cl;
if ((cl = class_create(THIS_MODULE, "char_driver")) == NULL)
{
unregister_chrdev_region(devNum,1);
return -1;
}
if ((device_create(cl, NULL, devNum, NULL, "my_device")) == NULL)
{
class_destroy(cl);
unregister_chrdev_region(devNum,1);
return -1;
}
Do funkcji unload dodajemy:
device_destroy(cl, devNum);
class_destroy(cl);
Przyszedł czas, aby porozmawiać z naszym sterownikiem. Proponuję wysłać coś do sterownika i zobaczyć co się stanie. Wpisujemy w konsolę:
W momencie gdy przekierowujemy wyjście z konsoli na nasze urządzenie wykonywana jest zdefiniowana przez nas operacja zapisu, czuli funkcja char_write(), na chwilę obecną wypisuje ona jedynie swoją nazwę. Przed i po wywołaniu funkcji char_write() zostały wywołane char_open() - otwarcie urządzenia, oraz char_release - zamknięcie urządzenia. W kolejnej części dopiszemy implementacje funkcji, aby działały zgodnie ze swoim rzeczywistym przeznaczeniem.
Użyjemy do tego:
- struct class - klasa urządzenia
- class_create(THIS_MODULE, "device_class_name") - funkcja tworząca klasę urządzenia
- device_create(struct class *cl, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) - funkcja tworząca wpis w /dev/, gdzie:
- parent - wskaźnik na rodzica urządzenia
- devt - struktura zawięrająca major i minor
- drvdata - dodatkowe dane
- fmt - nazwa pliku urządzenia, która będzie widnieć jako wpis w /dev/
Dodajemy nagłówek <linux/device.h> oraz makro MODULE_LICENSE("GPL") i tworzymy device node:
struct class *cl;
if ((cl = class_create(THIS_MODULE, "char_driver")) == NULL)
{
unregister_chrdev_region(devNum,1);
return -1;
}
if ((device_create(cl, NULL, devNum, NULL, "my_device")) == NULL)
{
class_destroy(cl);
unregister_chrdev_region(devNum,1);
return -1;
}
Do funkcji unload dodajemy:
device_destroy(cl, devNum);
class_destroy(cl);
Przyszedł czas, aby porozmawiać z naszym sterownikiem. Proponuję wysłać coś do sterownika i zobaczyć co się stanie. Wpisujemy w konsolę:
Następnie korzystamy z dmesg i naszym oczom powinno ukazać się:
Brak komentarzy:
Prześlij komentarz