2013-03-08 18 views
24

Czekam na napisanie sterownika PWM. Wiem, że istnieją dwa sposoby kontrolowania sterownika sprzętowego:Przestrzeń użytkownika a przestrzeń jądra sterownika

  1. Sterownik miejsca użytkownika.
  2. Kernel kierowca przestrzeń

Jeśli w ogóle (nie uważają sprawę sterownika PWM) musimy podjąć decyzję, czy iść do przestrzeni użytkownika lub sterownika przestrzeni jądra. Jakie czynniki musimy wziąć pod uwagę poza tymi?

  1. Sterownik przestrzeni użytkownika może bezpośrednio mmap()/dev/mem pamięci do ich wirtualnej przestrzeni adresowej i nie wymaga przełączania kontekstu.
  2. Sterownik przestrzeni użytkownika nie może zaimplementować obsługi przerwań (muszą odpytać o przerwanie).
  3. Sterownik przestrzeni użytkownika nie może wykonać DMA (ponieważ pamięć DMA może być przydzielona z przestrzeni jądra).
+1

Zabezpieczenia: uprawnienia do plików kontrolki węzła urządzenia, które użytkownicy mogą otwierać/czytać/zapisywać na urządzeniu. Operacje na plikach blokują lub zezwalają na współbieżne operacje. – sawdust

+1

Decyzja może w dużym stopniu zależeć od tego, czym jesteś PWM i jakiego sprzętu. –

Odpowiedz

31

Z tych trzech czynników, które wymieniono, tylko pierwsza jest prawidłowa. Co do reszty - niezupełnie. Kod przestrzeni użytkownika może wykonywać operacje DMA - nie ma z tym problemu. Istnieje wiele firm produkujących urządzenia, które stosują tę technikę w swoich produktach. Możliwe jest również zastosowanie aplikacji przestrzeni użytkownika sterowanej przerwań, nawet gdy wszystkie operacje wejścia/wyjścia są wykonywane przy pełnym obejściu jądra. Oczywiście nie jest to tak proste, jak po prostu wykonanie mmap() na.

Musiałbyś mieć minimalną część sterownika w jądrze - jest to konieczne, aby zapewnić przestrzeni użytkownika minimum potrzebnego z jądra (ponieważ jeśli o tym pomyślisz - to jest również /dev/mem kopia zapasowa przez sterownik urządzenia znaków).

Dla DMA jest to w rzeczywistości zbyt proste - wystarczy, że obsłużysz żądanie mmap i zamapujesz bufor DMA na przestrzeń użytkownika. W przypadku przerwań - jest to nieco trudniejsze, przerwanie musi być obsługiwane przez jądro, bez względu na wszystko, jednak jądro może nie wykonywać żadnej pracy i po prostu obudzić proces, który wywołuje, powiedzmy, epoll_wait(). Innym podejściem jest dostarczenie sygnału do procesu wykonanego przez DOSEMU, ale jest to bardzo powolne i nie jest zalecane.

Jeśli chodzi o faktyczne pytanie, jednym z czynników, które należy wziąć pod uwagę, jest podział zasobów. Dopóki nie musisz udostępniać urządzenia w wielu aplikacjach i nie ma nic, czego nie możesz zrobić w przestrzeni użytkownika - przejdź do przestrzeni użytkownika. Prawdopodobnie zaoszczędzisz mnóstwo czasu podczas cyklu programowania, ponieważ pisanie kodu przestrzeni użytkownika jest niezwykle łatwe. Kiedy jednak dwie lub więcej aplikacji wymaga współdzielenia urządzenia (lub jego zasobów), istnieje duże prawdopodobieństwo, że poświęcisz ogromną ilość czasu na jego wykonanie - wyobraź sobie, że wiele procesów rozwidla się, rozbija, mapuje (ta sama?) Pamięć jednocześnie itd. I ostatecznie, IPC jest zwykle wykonywane przez jądro, więc jeśli aplikacja musiałaby zacząć "rozmawiać" ze sobą, wydajność może znacznie się pogorszyć. Wciąż jest to robione w prawdziwym życiu dla pewnych aplikacji o krytycznym znaczeniu dla wydajności, ale nie chcę wchodzić w szczegóły.

Kolejnym czynnikiem jest infrastruktura jądra. Załóżmy, że chcesz napisać sterownik urządzenia sieciowego. To nie jest problem, aby zrobić to w przestrzeni użytkownika. Jeśli jednak to zrobisz, będziesz musiał napisać pełny stos sieciowy, ponieważ nie będzie możliwe korzystanie z domyślnego systemu Linux, który żyje w jądrze.

Powiedziałbym, idź do przestrzeni użytkownika, jeśli to możliwe, a ilość wysiłku, aby wszystko zadziałało, jest mniejsza niż napisanie sterownika jądra i pamiętając, że pewnego dnia może być konieczne przeniesienie kodu do jądra . W rzeczywistości jest to powszechna praktyka polegająca na kompilowaniu tego samego kodu zarówno dla przestrzeni użytkownika, jak i przestrzeni jądra, w zależności od tego, czy zdefiniowano jakieś makro, ponieważ testowanie w przestrzeni użytkownika jest o wiele przyjemniejsze.

+0

Świetna odpowiedź. Szukałem tych informacji, a twoja odpowiedź była bardzo pomocna.! –

+0

Jednak epoll ma szybki mechanizm, w końcu jest strukturą ankiety, a nie obsługą przerwań. Może to powodować problemy z operacjami o krytycznym czasie. – obayhan

6

Kolejna uwaga: znacznie łatwiej jest debugować sterowniki przestrzeni użytkownika. Możesz użyć gdb, valgrind itp. Heck, nie musisz nawet pisać sterownika w C.

Istnieje trzecia opcja poza tylko przestrzenią użytkownika lub sterownikami jądra jądra: niektóre z nich. W sterowniku jądra możesz robić tylko rzeczy związane z przestrzenią jądra i robić wszystko inne w przestrzeni użytkownika. Nie musisz nawet pisać sterownika przestrzeni jądra, jeśli korzystasz ze środowiska sterowników Linux UIO (zobacz https://www.kernel.org/doc/html/latest/driver-api/uio-howto.html).

Miałem szczęście pisząc sterownik obsługujący DMA prawie całkowicie w przestrzeni użytkownika. UIO zapewnia infrastrukturę, dzięki czemu można po prostu odczytać/wybrać/epoll na pliku, aby poczekać na przerwanie.

Powinieneś zdawać sobie sprawę z implikacji związanych z bezpieczeństwem programowania deskryptorów DMA z przestrzeni użytkownika: o ile nie masz pewnej ochrony w samym urządzeniu lub IOMMU, sterownik przestrzeni użytkownika może spowodować, że urządzenie odczyta lub napisze na dowolny adres w pamięci fizycznej.

Powiązane problemy