Po wielu perypetiach związanych z uruchomieniem „środowiska” do kompilacji modułu jądra, udało mi się uruchomić „Witaj świecie!”. Teraz przyszedł czas na coś bardziej ambitnego. Urządzenie znakowe produkujące jedynki, działające tak samo jak /dev/zero. Czasami takie urządzenie się przydaje. Znacznie rzadziej, ale jak jest potrzebne, to jest problem. Moduł nie niesie ze sobą nic odkrywczego. Typowe urządzenie znakowe. Moduł został wydany w dwóch wersjach:
Moduł implementuje 4 funkcje, które powinno zawierać urządzenie znakowe. Jest to rozsądne minimum. Urządzenie znakowe widziane jest w systemie jako plik zatem::
- open – funkcja obsługująca otwarcie pliku,
- read – funkcja obsługująca odczyt pliku,
- write – funkcja obsługująca zapis do pliku,
- release – funkcja obsługująca zamknięcie pliku.
Dla urządzenia „plującego” jedynkami sens ma jedynie funkcja read. Funkcje open, write i release nie mają żadnego praktycznego znaczenia, ale wypadałoby, żeby zwróciły coś, co nam jest wygodne. W większości wypadków będzie to „0”, czyli sukces. Pozwoliłem sobie w przypadku funkcji write zwrócić błąd EIO. Wychodzę z założenia, że urządzenie typu /dev/zero czy /dev/random to urządzenie jednokierunkowe, więc chęć zapisu do nich jest bezcelowa, gdyż nie pełni żadnej funkcji.
Większość przykładów „Witaj świecie!” dla urządzeń znakowych funkcja init i exit jest prosta i ogranicza się jedynie do zarejestrowania i wyrejestrowania urządzenia. Niestety taka prosta funkcja nie utworzy nam pliku w gałęzi /dev/ (trzeba z poziomu juzerlandu stworzyć „noda” poleceniem mknod). Żeby urządzenie pojawiło się samo w /dev/ po załadowaniu modułów, trzeba trochę rozszerzyć funkcję init:
- alokujemy sobie „miejsce” na urządzenie lub urządzenia (tutaj polecam zasięgnąć wiedzę na temat numerów określanych jako major i minor),
- tworzymy klasę dla urządzenia (pojawi się odpowiedni wpis w /sys/class/),
- tworzymy urządzenie i inicjujemy jego funkcje (podpięcie naszych funkcji, patrz struktura fileoperations),
- dodajemy urządzenie
Wydajność przyspieszonego modułu jest podobna do /dev/zero. Wyniki prostego testu dla /dev/ones:
pi@raspberrypi ~/raspberry_pi/modules/dev_ones $ dd if=/dev/ones bs=100M count=1 | hexdump 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 1+0 records in 1+0 records out 104857600 bytes (105 MB) copied, 6.21713 s, 16.9 MB/s
Wyniki dla /dev/zero:
pi@raspberrypi ~/raspberry_pi/modules/dev_ones $ dd if=/dev/zero bs=100M count=1 | hexdump 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 1+0 records in 1+0 records out 104857600 bytes (105 MB) copied, 6.04321 s, 17.4 MB/s
Zatem nieźle. Wersja pierwsza była mniej wydajna, w powyższym teście była o 2MB/s wolniejsza. Podejrzewam, że nawet przyspieszona wersja nie jest tak wydajna jak /dev/zero – gdyby to do przetestować dogłębnie, ale taka wydajność jak najbardziej wystarcza do praktycznej pracy z modułem.