sobota, 31 sierpnia 2013

Programowanie sterowników pod Linux cz.4 - device nodes

Teraz musimy nieco porozmawiać na temat /dev oraz /proc/devices.

 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:
  • 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ę:


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.

Brak komentarzy:

Prześlij komentarz