58, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta


Rozdział 58.
Tworzenie sterowników urządzeń


Tim Parker

W tym rozdziale:

Sterownik urządzenia stanowi interfejs pomiędzy systemem operacyjnym a urządzeniem dołączonym do systemu. Typowy sterownik składa się z pewnej liczby funkcji potrafiących obsługiwać operacje wejścia / wyjścia zlecane przez system. Takie rozwiązanie pozwala na ujednolicenie interfejsu pomiędzy jądrem systemu i urządzeniami.

Nie możemy niestety omówić wszystkich aspektów tworzenia sterowników urządzeń w jednym rozdziale. Na ten temat napisano kilka całkiem pokaźnych książek. Ponieważ sterowniki urządzeń nie są raczej tworzone przez zwykłych użytkowników, a przez utalentowanych programistów, informacje przedstawione poniżej mają jedynie charakter przedstawienia zagadnienia.

Fragmenty kodu prezentowane w tym rozdziale pochodzą z zestawu przykładowych sterowników napisanych w języku C. Sterowniki te są przenośne i choć zostały zaprojektowane dla systemu UNIX, będą działać poprawnie również w Linuxie. Jeśli zdecydujesz się na tworzenie własnych sterowników, podane tu przykłady powinieneś traktować tylko jako wskazówki. Jeżeli zamierzasz zająć się tym zagadnieniem na poważnie, powinieneś zaopatrzyć się w jedną ze specjalistycznych książek poświęconych mu w całości.

0x01 graphic

Tworzenie sterowników urządzeń jest teoretycznie całkiem proste. Mimo tego przy próbie napisana pierwszego sterownika będziesz zaskoczony liczbą problemów, z którymi się zetkniesz. Wiele osób uważa tworzenie sterowników za swego rodzaju sztukę, ale tak naprawdę wymaga to jedynie odrobiny praktyki i doświadczenia. Napisanie dobrego sterownika daje ogromną satysfakcję.

Sterowniki urządzeń

System Linux używa sterownika dla każdego urządzenia podłączonego do systemu. Najbardziej podstawowe sterowniki są częścią jądra systemu i są ładowane podczas jego uruchamiania. Dzięki sterownikom urządzenia mogą być traktowane przez system tak samo jak pliki - można je adresować, przekierowywać do nich dane czy używać podczas wykorzystywania mechanizmu potoków, zupełnie tak, jak w przypadku zwykłych plików.

Każde urządzenie podłączone do systemu linuxowego jest opisane w pliku programu sterownika, a niektóre parametry są również zapisane w pliku urządzenia, przechowywanym zwykle w katalogu /dev. Jeśli do systemu zostanie dodane nowe urządzenie, należy zainstalować lub też napisać własnoręcznie odpowiedni sterownik. Każdemu urządzeniu musi również odpowiadać plik w katalogu /dev. Jeśli warunki te nie zostaną spełnione, urządzenie nie będzie mogło zostać wykorzystane w systemie linuxowym.

Do każdego pliku urządzenia przypisany jest numer urządzenia, pozwalający systemowi operacyjnemu jednoznacznie je zaadresować. W systemie Linux numer urządzenia składa się z dwóch części: numeru głównego, określającego ogólny typ urządzenia, na podstawie którego wybierany jest odpowiedni sterownik, oraz numeru pobocznego pozwalającego wyszczególnić każde z urządzeń obsługiwanych przez jeden sterownik. Dla przykładu, kilka dysków twardych w systemie może posiadać taki sam numer główny urządzenia (ponieważ są obsługiwane przez ten sam sterownik), ale każdy z nich musi posiadać inny numer poboczny, jednoznacznie go identyfikujący.

Istnieją dwa podstawowe typy sterowników urządzeń: blokowe i znakowe. Każde urządzenie w systemie UNIX-owym używa jednego lub obu tych typów sterowników. Najczęściej spotykane są sterowniki blokowe. Pozwalają one na przesyłanie do i z urządzenia danych buforowanych przez jądro systemu (kopiowanych w odpowiednie miejsce w pamięci operacyjnej). Pierwotnie sterowniki takie były wykorzystywane tylko dla dysków twardych, ale szybko znalazły zastosowanie również do obsługi innych urządzeń pamięci masowej, takich jak napędy taśmowe, magnetooptyczne, a nawet modemy synchroniczne i niektóre szybkie drukarki.

Urządzenia pracujące w trybie znakowym różnią się od blokowych pod dwoma zasadniczymi względami. Po pierwsze, wyniki operacji wejścia / wyjścia mogą być przekazywane bezpośrednio do przestrzeni adresowej procesu, z pominięciem buforowania przez jądro systemu. Po drugie, żądania operacji wejścia / wyjścia zwykle przekazywane są bezpośrednio do urządzenia. Przykładami urządzeń znakowych są terminale i drukarki, podobnie jak modemy asynchroniczne i niektóre modele napędów taśmowych.

Urządzenia blokowe opierają swe działanie na funkcji „strategii”, pozwalającej na odczytanie i zapisanie do urządzenia bloku danych. Dla urządzeń znakowych dostępny jest szereg specjalnych funkcji pozwalających na bezpośrednią komunikację, nazywanych ioctl(). Urządzenia blokowe czasem również działają jako znakowe, właśnie po to, by możliwe było użycie funkcji ioctl(). Dobrym przykładem jest napęd taśmowy, który może współpracować zarówno ze sterownikiem znakowym, jak i blokowym, zależnie od typu zapisywanych danych.

Niezależnie od typu, sterownik urządzenia podejmuje szereg podstawowych kroków za każdym razem, gdy ma nawiązać komunikację z urządzeniem. Najpierw sprawdza on, czy urządzenie jest gotowe i dostępne. Jeśli tak, jest ono „otwierane”, co umożliwia procesowi dostęp do niego. Następnie zwykle wywoływane są funkcje read i write, służące odpowiednio do odczytu i zapisywania danych do urządzenia, po czym urządzenie jest „zamykane”, dzięki czemu inne procesy mogą mieć do niego dostęp.

Przerwania

Przerwania to sygnały przesyłane przez urządzenia do systemu operacyjnego, powiadamiające go o konieczności obsługi danego urządzenia. Przerwania są generowane przy wszystkich operacjach wejścia / wyjścia. System przerwań wykorzystywany w Linuxie jest podobny do DOS-owego, więc jeśli jesteś obeznany z przerwaniami DOS-owymi, znasz już większą część teorii.

Po odebraniu sygnału przerwania system operacyjny wstrzymuje wszystkie wykonywane procesy i obsługuje przerwanie. W większości przypadków przerwania są obsługiwane przez sterownik urządzenia. Przerwania nie powinny w żaden sposób zaburzać działania innych procesów, za wyjątkiem co najwyżej chwilowego ich wstrzymania.

Pewien problem stwarza fakt, że wywołanie przerwania nie powinno prowadzić do zawieszenia działania jądra systemu ani procesu obsługi urządzenia, za wyjątkiem ściśle określonych sytuacji. Przerwania, które nie są prawidłowo obsługiwane lub sprawdzane, mogą prowadzić do zawieszenia sterownika urządzenia, który obsługiwał komunikację z nim.

Obsługa przerwań jest zwykle wstrzymywana tylko na czas wykonywania operacji o istotnym znaczeniu. Obszary kodu sterownika, które nie powinny być przerywane, nazywane są sekcjami krytycznymi lub niewstrzymywalnymi. Zwykle zawieszenie obsługi przerwań na czas realizacji sekcji krytycznych realizowane jest przez podniesienie priorytetu procesora do poziomu równego lub wyższego od priorytetu przerwań. Po zakończeniu wykonywania takiej sekcji priorytet procesora jest obniżany do poprzedniej wartości.

Priorytet przerwań można modyfikować za pomocą funkcji spl5(), spl6(), spl7() i splx(). Wywołanie jednej z trzech pierwszych funkcji powoduje zablokowanie obsługi przerwań. Funkcja spl5() wyłącza obsługę przerwań generowanych przez dyski, drukarki i klawiaturę, funkcja spl6() wyłącza zegar systemowy, natomiast spl7() wyłącza obsługę wszystkich przerwań, w tym pochodzących od urządzeń szeregowych. Funkcje te zwracają kod oznaczający wartość poziomu przerwań, do którego można wrócić za pomocą funkcji splx().

Przed wejściem do sekcji krytycznej kodu należy więc wykonać polecenie

pierw_poz = spl5();

które spowoduje zawieszenie obsługi przerwań aż do momentu wywołania funkcji

splx():
splx(pierw_poz);

Poniższy przykład przedstawia wielokrotne zmiany poziomu obsługiwanych przerwań w sterowniku urządzenia.

int poz_a, poz_b;
poz_a = spl5();
/* kod, ktory nie powinien byc */
/* przerywany przez dyski */
poz_b = spl7();
/* instrukcje, ktore nie mogą */
/* byc w ogole przerywane */
splx(poz_b);
/* kod koncowy, ktory nie moze */
/* byc przerwany przez dyski */
splx(poz_a);

Ta dość dziwaczna na pierwszy rzut oka żonglerka poziomami przerwań jest niezbędna, aby uniknąć wstrzymania obsługi sterownika urządzenia i jądra systemu, co może prowadzić do nieprawidłowej pracy systemu. Mechanizmy zabezpieczające powinny być uruchamiane na tak krótko, jak tylko jest to możliwe.

Zwykle nie należy używać funkcji spl6() i spl7(). W niektórych przypadkach wywołanie funkcji spl6() może spowodować opóźnienie zegara systemowego, natomiast wywołanie funkcji spl7() może spowodować utratę danych przesyłanych przez urządzenia szeregowe, chyba że blokada jest aktywna przez bardzo krótki okres czasu. Mimo wszystko jednak w większości przypadków przed wejściem do sekcji krytycznej wystarcza wywołanie funkcji spl5().

Struktura sterownika urządzenia dla systemu Linux

Kod źródłowy sterownika urządzenia pod względem struktury nie odbiega od kodu zwykłych programów. W systemie Linux sterowniki w zasadzie tworzone są w języku C, choć czasem korzysta się również z asemblera i języka C++.

Pliki nagłówkowe

Typowy sterownik urządzenia zawiera plik nagłówkowy, w którym znajdują się dyrektywy włączające do kodu deklaracje funkcji systemowych, adresów rejestrów urządzeń, definicje zawartości oraz definicje zmiennych globalnych używanych przez sterownik. W większości sterowników wykorzystuje się następujący zestaw plików nagłówkowych:

param.h parametry jądra systemu;

dir.h parametry katalogów;

user.h definicje użytkownika

tty.h definicje terminali i bufora clist

buf.h informacje o buforowaniu

Plik tty.h jest wykorzystywany w sterownikach pracujących w trybie znakowym, natomiast plik buf.h - w trybie blokowym.

Adresy rejestrów urządzenia, definiowane w jednym z plików nagłówkowych, są zależne od samego urządzenia. Dla urządzeń znakowych odpowiadają one zwykle adresom portów, takich jak port wejścia / wyjścia czy zawierający bity stanu u kontrolne. Polecenia zmieniające stan urządzenia są zdefiniowane jako kody urządzenia.

Oto przykład inicjalizacji rejestrów urządzenia dla sterownika terminalu standardowego (UART):

/* definicja rejestrow */
#define RRDATA 0x01 /* odbior */
#define RTDATA 0x02 /* nadawanie */
#define RSTATUS 0x03 /* stan */
#define RCONTRL 0x04 /* bity kontrolne */
...itd.
/* definicja rejestrow stanu */
#define SRRDY 0x01 /* dane odebrane */
#define STRDY 0x02 /* nadajnik gotowy */
#define SPERR 0x03 /* blad parzystosci */
#define SCTS 0x04 /* gotowy do wyslania inf. o stanie */
...itd.

Funkcje, które musi udostępniać sterownik, zależą od natury samego urządzenia. Wszystkie sterowniki muszą posiadać funkcje open() i close(), pozwalające na realizację operacji wejścia / wyjścia.

Otwieranie urządzenia

Podprogram open() musi sprawdzać, czy wybrane urządzenie jest prawidłowe, czy proces wywołujący może uzyskać do niego dostęp (czy ma prawo dostępu i czy urządzenie jest gotowe) oraz inicjalizować urządzenie. Podprogram open() jest wywoływany za każdym razem, gdy jakiś proces korzysta z urządzenia.

Poniżej prezentujemy procedurę open() obsługującą ogólne urządzenie terminalu o nazwie td.

tdopen (device, flag)
int device, flag;
{
/* definicje zmiennych lokalnych oraz szczegoly */
/* zostaly pominiete */

/* sprawdz numer urzadzenia /
if (UNMODEM (device) >= NTDEVS)
{
seterror(ENXIO);
return;
}

/* sprawdz, czy urzadzenie jest uzywane */
/* jeśli tak, to wymus zwolnienie jesli */
/* uzytkownikiem jest root (suser) */
tp = &td_tty[UNMODEM(device)];
adres = td_address[UNMODEM(device)];
if ( ( tp->t_lflag & XCLUDE ) && !suser() )
{
seterror(EBBUSY);
return;
{

/* Jesli urzadzenie nie jest otwarte, zainicjalizuj je */
/* wywolujac funkcje ttinit() */
if ( (tp->t_state & (ISOPEN|WOPEN)) == 0 )
{
ttinit(tp);
/* inicjalizacja znacznikow i wywolanie tdparam() */
/* aby ustalic parametry linii */
tdparam (device);
}

/* Jesli uzywany jest modem, sprawdz stan nosnej */
/* Jesli polaczenie bezposrednie, ustal */
/* wartosc znacznika wykrywania nosnej */
/* ustal priorytet przerwan aby zapobiec nadpisania */
/* czekaj na sygnal wykrycia nosnej */
/* na potrzeby tego przykladu */
/* implementacja zostala pominieta */

Zamykanie urządzenia

Podprogram close() używany jest tylko po zakończeniu komunikacji z urządzeniem. Powoduje on wyłączenie obsługi przerwań pochodzących od urządzenia oraz przesłanie odpowiednich informacji kończących jego pracę. Wszystkie wewnętrzne odniesienia do urządzenia są usuwane. Podprogram close() w większości przypadków nie jest wymagany, ponieważ urządzenia są traktowane jako dostępne przez cały czas. Wyjątek stanowią dyski wymienne i urządzenia wymagające wyłączności na używanie. Również niektóre modemy wymagają, aby w procedurze close() umieścić kod pozwalający na zwolnienie linii telefonicznej.

Również tu posłużymy się przykładem pochodzącym ze sterownika obsługującego terminal.

tdclose (device)
{
register struct tty *tp;
tp = &td_tty[UNMODEM(device)];
(*linesw[tp->t_line].l_close) (tp);
if (tp->t_cflag & HUPCL)
tdmodem(device, TURNOFF);
/* usun znacznik wylacznosci */
ip->t_lflag &= ~XCLUDE;
}

Funkcje strategii

Funkcje strategii (używane tylko przez sterowniki urządzeń blokowych) są wywoływane z parametrem prowadzącym do nagłówka bufora, do którego jądro systemu składa dane. Nagłówek bufora zawiera informacje dotyczące odczytu czy zapisu danych, wraz z adresem miejsca pamięci, w którym znajdują się dane do wysłania lub mają znaleźć się odbierane dane. Rozmiar bufora jest zwykle ustalany podczas instalacji i waha się pomiędzy 512 i 1024 bajtami. Rozmiar ten definiowany jest w pliku param.h jako wartość zmiennej BSIZE. Rozmiar bloku danych używanego przez urządzenie może być mniejszy od rozmiaru bufora - w takim przypadku sterownik wykona kilka operacji odczytu czy zapisu pod rząd.

Funkcja strategii zostanie przedstawiona na przykładzie prostego sterownika dysku twardego. Nie zamieszczamy samego kodu źródłowego, a jedynie szkieletowe informacje o działaniu funkcji.

int hdstrategy (bp)
register struct buf *bp;
{
/* inicjalizuj dysk i numery partycji */
/* ustal wartosci zmiennych lokalnych */

/* sprawdz, czy dysk i partycja sa prawidlowe */
/* ustal numer cylindra docelowego */
/* wylacz przerwania */
/* wstaw zadanie do kolejki */
/* sprawdz kontroler, jesli nie jest aktywny, uruchom go */
/* przywroc poprzedni poziom przerwan */
}

Funkcje write()

Urządzenia pracujące w trybie znakowym używają funkcji write(), która sprawdza, czy jej argumenty są poprawne, a następnie kopiuje dane z obszaru pamięci procesu do bufora sterownika urządzenia. Po skopiowaniu wszystkich danych lub zapełnieniu bufora uruchamiane są procedury wejścia / wyjścia aż do opróżnienia bufora, po czym proces się powtarza. Dane z pamięci procesu są odczytywane za pomocą prostej funkcji (cpass) zwracającej -1 w przypadku, gdy osiągnięty zostanie koniec obszaru pamięci. Zapisywanie danych do pamięci procesu odbywa się za pośrednictwem funkcji komplementarnej (passc). Oto przykładowa funkcja write() obsługująca urządzenie terminalu:

tdwrite (device)
{
register struct tty *tp;
tp = &td_tty[UNMODEM(device)];
(*linesw[tp->t_line].l_write) (tp);
}

Większe ilości danych są obsługiwane przez proces o nazwie copyio, który pobiera argumenty określające adres danych źródłowych i miejsca, do którego mają one zostać skopiowane, oraz liczbę bajtów i znacznik stanu.

Funkcje read()

Funkcja read() dla urządzenia znakowego przesyła dane z urządzenia do pamięci procesu. Jest to operacja analogiczna do działania procedury write(). Kod źródłowy tej procedury dla urządzenia terminalu ma następującą postać:

tdread (device)
{
register struct tty *tp;
tp = &td_tty[UNMODEM(device)];
(*linesw[tp->t_line].l_read) (tp);
}

Jeśli funkcje read() i write() mają skopiować kilka bajtów, używany jest niewielki bufor, o nazwie clist. Używa on szeregu powiązanych list, które z kolei do usuwania i wstawiania znaków do bufora używają funkcji getc i putc. Nagłówek bufora clist zawiera również informację o liczbie przechowywanych znaków.

Podprogramy start i ioctl

Podprogram start używany jest zarówno przez urządzenia blokowe, jak i znakowe. Pobiera on dane z kolejki urządzenia i kieruje je kolejno do urządzenia. Urządzenia blokowe do kolejkowania danych używają funkcji strategii, natomiast urządzenia znakowe - prostego bufora clist. Podprogram start w czasie przesyłania danych do urządzenia automatycznie obsługuje znaczniki mówiące o tym, że urządzenie jest zajęte. Po zakończeniu procesu urządzenie wywołuje podprogram intr, który inicjalizuje je ponownie, przygotowując do obsługi następnego procesu.

Podprogram ioctl(), używany w sterownikach urządzeń znakowych, pozwala przesłać do sterownika specjalne instrukcje, umożliwiające na przykład zmianę metody komunikacji pomiędzy sterownikiem a systemem operacyjnym czy wykonanie operacji ściśle zależnych od urządzenia (jak przewinięcie taśmy czy alokacja pamięci).

Funkcję ioctl() zilustrujemy przykładem pochodzącym ze sterownika terminal. W tym przypadku do ustalenia parametrów urządzenia wywoływana jest inna funkcja. Nie przedstawiamy jej kodu źródłowego, tylko ogólny zarys pozwalający zorientować się w zasadach działania.

tdioctl (device, cmd, arg, mode)
int device;
int cmd;
int mode;
faddr_t arg;
{
if (ttiocom(&td_tty[UNMODEM(device)], cmd, arg, mode))
tdparam (device);
}

tdparam(device)
{
/* inicjalizacja zmiennych */
/* pobierz adres i znaczniki linii, do ktorej */
/* odnosi się polecenie */
adr = td_addr[UNMODEM(device)];
cflag = td_tty[UNMODEM(device)].t_cflag;

/* sprawdz predkosc; jeśli zero to zwolnij linie */
/* zmien predkosc */
/* ustal zarzadzanie linia */
/* obsluz przerwania */
}

Używanie nowego sterownika

Proces dodawania do systemu nowego sterownika urządzenia składa się z kilku etapów. Najpierw identyfikowany jest podprogram obsługi przerwania, a następnie punkty wejścia do programu sterownika (na przykład adres procedury open) są dodawane do tabeli punktów wejścia sterownika. Cały sterownik jest kompilowany i dołączany do jądra systemu, a następnie umieszczany w katalogu /dev (w rozdziale 57. „Jądro systemu” znajdziesz dodatkowe informacje dotyczące dodawania sterowników do jądra systemu). Na koniec system musi zostać zrestartowany, po czym można przetestować działanie nowego sterownika. Oczywiście wprowadzenie modyfikacji do kodu sterownika wymaga powtórzenia całego procesu, więc usuwanie błędów może być dość męczące i prawdziwą sztuką jest osiągnięcie jak najmniejszej liczby restartów.

0x01 graphic

Przy tworzeniu sterowników urządzeń nie należy używać funkcji sleep() i seterror() oraz operacji zmiennoprzecinkowych we fragmentach, podczas wykonywania których zawieszona jest obsługa przerwań.

Czas, na jaki wstrzymywane są przerwania, powinien być jak najkrótszy; należy również uważać, by nie uszkodzić danych przechowywanych w buforze. Bardzo ważne jest także wykorzystanie jak najmniejszej liczby komórek stosu.

Można ułatwić sobie proces usuwania błędów ze sterowników urządzeń, umieszczając w kodzie źródłowym wywołania funkcji printf czy getchar w odniesieniu do innego urządzenia, na przykład konsoli. Takie rozwiązanie pozwala na pozostawienie śladu wykonania sterownika. Jeśli testujesz sterownik jako root, możesz również wykorzystać debuger adb, pozwalający na obserwację pamięci używanej przez jądro systemu w czasie pracy sterownika. Ostrożne korzystanie z tego programu pozwala na bezpośrednie śledzenie zmian wartości zmiennych czy zawartości komórek pamięci; bądź jednak uważny, ponieważ nieprawidłowe użycie debugera adb może prowadzić do załamania się systemu.

Jednym z najczęstszych problemów występujących przy tworzeniu sterowników (prócz oczywiście błędów w kodzie źródłowym) jest „gubienie” przerwania lub uśpienie urządzenia podczas jego obsługi. Takie sytuacje powodują, że urządzenie się zawiesza. W większości przypadków do sterowników urządzeń dołącza się procedurę ograniczającą czas, przez jaki należy oczekiwać na odpowiedź urządzenia, dzięki czemu unika się zawieszania urządzenia. Jeśli spodziewane przerwanie nie zostanie zgłoszone w określonym czasie, urządzenie jest sprawdzane bezpośrednio, aby upewnić się, że przerwanie nie zostało „zgubione”. Jeśli okaże się, że przerwanie zostało zgubione, może ono zostać zasymulowane przez sterownik. Używanie funkcji spl() w czasie testowania zwykle ułatwia wyizolowanie tego typu problemów.

Sterowniki urządzeń blokowych najczęściej tworzone są w oparciu o przerwania. Jednak coraz więcej programistów używa ostatnio techniki zwanej odpytywaniem, nadającej się do obsługi urządzeń znakowych. Technika ta polega na regularnym sprawdzaniu stanu urządzenia. Sterownik nie czeka więc na zgłoszenie przerwania, co pociąga za sobą nieco większe zużycie czasu procesora. Odpytywanie nie jest właściwym rozwiązaniem dla większości urządzeń, takich jak pamięci masowe, ale w przypadku urządzeń znakowych może przynieść pewne korzyści. Urządzenia szeregowe są zwykle obsługiwane za pomocą odpytywania, co pozwala na zmniejszenie liczby wywołań przerwań.

Terminal połączony z systemem linią o prędkości transmisji 19200 bodów generuje około 1920 przerwań na sekundę, co powoduje wielokrotną obsługę samego przerwania i wchodzenie oraz wychodzenie z funkcji jego obsługi. Jeśli zamiast przerwań zastosowany zostanie mechanizm odpytywania, przedział czasowy pomiędzy kolejnymi zgłoszeniami konieczności obsługi przez procesor może być znacznie zwiększony, na przykład przez zastosowanie niewielkiego bufora przechowującego dane wysyłane do lub odbierane z urządzenia. Urządzenia czasu rzeczywistego również nadają się do obsługi za pomocą mechanizmów odpytywania, ponieważ zmniejsza to znacznie liczbę wywoływanych przerwań. Jeśli chcesz używać tego mechanizmu w swoich sterownikach urządzeń, powinieneś zaopatrzyć się w jedną z książek poświęconych w całości sterownikom, ponieważ jest to temat dość złożony.

Podsumowanie

Większość użytkowników systemu Linux nigdy nie będzie tworzyć własnych sterowników urządzeń, ponieważ przeważnie sterowniki takie są już dostępne. Jednak jeśli posiadasz zupełnie nowe urządzenie lub też sterownik, którego używasz, zawiera jakiś błąd, możesz pokusić się o stworzenie własnego sterownika. Nie jest to zadanie bardzo trudne (pod warunkiem, że znasz dobrze język C), ale zwykle dużo kłopotów sprawia usuwanie powstałych usterek. Programista tworzący sterownik musi cały czas uważać, by nie wpływał on na działanie innych procesów lub urządzeń. Napisanie poprawnie działającego sterownika jest jednak powodem do dumy.

Rozdział 26. „Programowanie w języku C”, omawia zagadnienia związane z językiem C dla systemu Linux, którego można użyć do tworzenia sterowników.

Język Perl, bardzo poręczny i doskonale nadający się do tworzenia krótkich i zaskakująco wydajnych programów, omówiony jest w rozdziale 28. „Perl”.

Inne języki programowania dostępne dla systemu Linux przedstawione są w skrócie w rozdziale 30. „Inne kompilatory”.

854 Część VIII Programowanie dla zaawansowanych

854 E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\58.DOC

E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\58.DOC 855

Rozdzia³ 58. Tworzenie sterowników urządzeń 855



Wyszukiwarka

Podobne podstrony:
43, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
34, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
26, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
08, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
10, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
57, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
29, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
46, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
60, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
36, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
49, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
62, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
D, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
55, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
28, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
61, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
42, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
03, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
31, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta

więcej podobnych podstron