Są tak naprawdę - interfejsy. Zakodowane przez „większą” i „mniejszą” liczbę, zapewniają zaczepienie do jądra.
Występują w dwóch odmianach (cóż, trzech, ale nazwane potoki są na razie poza zakresem tego wyjaśnienia): Urządzenia postaci i Urządzenia bloku.
Urządzenia blokowe są zwykle urządzeniami pamięci masowej, zdolnymi do buforowania danych wyjściowych i przechowywania danych do późniejszego pobrania.
Urządzenia znakowe to takie rzeczy, jak karty audio lub graficzne lub urządzenia wejściowe, takie jak klawiatura i mysz.
W każdym przypadku, gdy jądro ładuje poprawny sterownik (podczas uruchamiania lub za pomocą programów takich jak udev ), skanuje różne magistrale, aby sprawdzić, czy jakieś urządzenia obsługiwane przez ten sterownik są rzeczywiście obecne w systemie. Jeśli tak, konfiguruje urządzenie, które „nasłuchuje” na odpowiednim numerze głównym / podrzędnym.
(Na przykład cyfrowy procesor sygnałowy pierwszej karty dźwiękowej znalezionej przez system otrzymuje parę liczb głównych / podrzędnych wynoszącą 14/3; druga otrzymuje 14,35 itd.)
Udev musi utworzyć wpis o /dev
nazwie dsp
jako urządzenie znakowe oznaczone jako główne 14 drugorzędne 3.
(W wersjach systemu Linux o znacznie starszych lub minimalnej powierzchni /dev/
może nie być ładowane dynamicznie, ale tylko statycznie zawierać wszystkie możliwe pliki urządzeń).
Następnie, gdy program przestrzeni użytkownika próbuje uzyskać dostęp do pliku oznaczonego jako „specjalny plik znakowy” z odpowiednim numerem głównym / dodatkowym (na przykład odtwarzacz audio próbuje wysłać cyfrowy dźwięk /dev/dsp
), jądro wie, że dane te muszą być przekazywane za pośrednictwem kierowcy, do którego dołączony jest numer główny / pomocniczy; prawdopodobnie powiedział, że kierowca wie z kolei, co z tym zrobić.
Każdy plik, urządzenie lub w inny sposób obsługuje 6 podstawowych operacji w VFS:
Ponadto pliki urządzeń obsługują kontrolę we / wy, co pozwala na wykonywanie innych operacji nieobjętych pierwszą 6.
W przypadku znaku specjalnego wyszukiwanie i mów nie są realizowane, ponieważ obsługują interfejs przesyłania strumieniowego . Oznacza to, że czytanie lub pisanie bezpośrednio, tak jak w przypadku przekierowania w powłoce:
źródło
Minimalny możliwy do uruchomienia
file_operations
przykładGdy zobaczysz minimalny przykład, wszystko stanie się oczywiste.
Kluczowe pomysły to:
file_operations
zawiera wywołania zwrotne dla każdego wywołania systemowego związanego z plikiemmknod <path> c <major> <minor>
tworzy urządzenie postaci, które je wykorzystujefile_operations
cat /proc/devices
character_device.ko
moduł jądra:Program testowy użytkownika:
GitHub QEMU + Buildroot w górę z płytą grzewczą, aby go uruchomić:
Bardziej złożone przykłady:
read
,write
,lseek
Z wewnętrznym buforem o stałym rozmiarze i debugfs zamiast urządzenia znaków: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/fops.cpoll
: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/poll.cioctl
: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/poll.canon_inode_getfd
kojarzyfile_operations
deskryptor pliku bez pliku systemu plików: /programming/4508998/what-is-anonymous-inode/44388030#44388030źródło
*off = 1;
i dlaczego jest ustawione1
?read
wywołań do tego samegoopen(
deskryptora pliku. Kierowca może przy tym robić co chce. Zazwyczaj semantyczny ma zawierać liczbę odczytanych bajtów. W tym przykładzie mamy tylko prostszy semantyczny:0
dla pierwszego czytania,1
po pierwszym czytaniu. Spróbuj go uruchomić i debuguj krok printk lub GDB.„Postać na raz” jest mylącą nazwą (podobnie jak idea, że urządzenia postaci niekoniecznie obsługują wyszukiwanie i mówienie). W rzeczywistości urządzenia „blokuj na raz” (tj. Urządzenia ściśle zorientowane na zapis, takie jak napęd taśmowy *) muszą być urządzeniami znakowymi. Podobnie jest z ideą, że urządzenie znakowe musi koniecznie być niewidzialne - sterowniki urządzeń znakowych definiują pełną
file_operations
strukturę, która może dowolnie definiować lseek, czy nie, zależnie od tego, czy urządzenie obsługuje tę operację. Urządzenia postaci, które większość ludzi uważa za przykłady, to null, urandom, urządzenia TTY, karta dźwiękowa, mysz itp. i / dev / kmem są również urządzeniami postaci i wszystkie są widoczne.Jak wspomniałem, sterownik urządzenia znakowego definiuje strukturę operacji file_operation, która ma wskaźniki funkcji dla wszystkich operacji, które ktoś może chcieć wywołać dla pliku - szukaj, czytaj, pisz, ioctl itp. - i każda z nich jest wywoływana raz, gdy odpowiednie wywołanie systemowe jest wykonywany przy otwartym pliku urządzenia. A zatem czytanie i pisanie może w ten sposób robić wszystko, co chce dzięki swoim argumentom - może odmówić przyjęcia zapisu, który jest zbyt duży lub pisać tylko to, co pasuje; może odczytać tylko dane odpowiadające jednemu rekordowi, a nie całej żądanej liczby bajtów.
Czym więc jest urządzenie blokowe? Zasadniczo urządzenia blokowe są dyskami. Żadne inne urządzenie (z wyjątkiem wirtualnych napędów dyskowych, takich jak ramdysk i pętla zwrotna) nie jest urządzeniem blokowym. Są one zintegrowane z systemem żądania we / wy, warstwą systemu plików, systemem bufora / pamięci podręcznej i systemem pamięci wirtualnej w sposób, w jaki nie są używane urządzenia znakowe, nawet gdy uzyskujesz dostęp np. / Dev / sda z procesu użytkownika . Nawet „surowe urządzenia”, o których strona wspomina jako wyjątek, są urządzeniami znakowymi .
* Niektóre systemy UNIX zaimplementowały tak zwany „tryb stałego bloku” - który pozwala grupom jądra i podzielonym żądaniom We / Wy dopasować skonfigurowane granice bloków mniej więcej tak samo, jak w przypadku napędów dyskowych - jako blok urządzenie. Urządzenie znakowe jest potrzebne do „trybu zmiennych bloków”, który zachowuje granice bloków z programu użytkownika, ponieważ pojedyncze wywołanie write (2) zapisuje jeden blok, a pojedyncze wywołanie read (2) zwraca jeden blok. Ponieważ przełączanie trybów jest teraz realizowane jako ioctl, a nie jako osobny plik urządzenia, używane jest urządzenie znakowe. Napędy taśmowe o zmiennych rekordach są w większości „niewidzialne”, ponieważ wyszukiwanie wymaga zliczenia liczby rekordów, a nie liczby bajtów, a natywna operacja wyszukiwania jest zaimplementowana jako ioctl.
źródło
Urządzenia znakowe mogą być tworzone przez moduły jądra (lub samo jądro). Podczas tworzenia urządzenia twórca udostępnia wskaźniki do funkcji, które implementują obsługę standardowych wywołań, takich jak open, read itp. Jądro Linux następnie kojarzy te funkcje z urządzeniem znakowym, na przykład gdy aplikacja w trybie użytkownika wywołuje funkcję read () funkcja w pliku urządzenia znakowego spowoduje wywołanie systemowe, a następnie jądro przekieruje to wywołanie do funkcji odczytu określonej podczas tworzenia sterownika. Jest to poradnik krok po kroku na stworzenie urządzenia znakowego tutaj można stworzyć przykładowy projekt i przejść przez nią za pomocą debuggera, aby zrozumieć, w jaki sposób tworzony jest obiekt urządzenie i kiedy teleskopowe są wywoływane.
źródło