Czy ktoś może mi wyjaśnić,
- Co to jest
IOCTL
? - Do czego jest to używane?
- Jak mogę tego używać?
- Dlaczego nie mogę zdefiniować nowej funkcji, która działa tak samo jak
IOCTL
?
źródło
Czy ktoś może mi wyjaśnić,
IOCTL
?IOCTL
?An ioctl
, co oznacza „sterowanie wejściem / wyjściem”, jest rodzajem wywołania systemowego specyficznego dla urządzenia. W Linuksie (300-400) jest tylko kilka wywołań systemowych, które nie wystarczają do wyrażenia wszystkich unikalnych funkcji, jakie mogą mieć urządzenia. Tak więc kierowca może zdefiniować ioctl, który pozwala aplikacji w przestrzeni użytkownika na wysyłanie zamówień. Jednak ioctl nie są zbyt elastyczne i mają tendencję do trochę zaśmiecania (dziesiątki "magicznych liczb", które po prostu działają ... lub nie), a także mogą być niepewne, gdy przekazujesz bufor do jądra - zła obsługa może się zepsuć rzeczy łatwo.
Alternatywą jest sysfs
interfejs, w którym ustawiasz plik pod /sys/
i odczytujesz / zapisujesz, aby uzyskać informacje od i do sterownika. Przykład, jak to ustawić:
static ssize_t mydrvr_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", DRIVER_RELEASE);
}
static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL);
A podczas konfiguracji sterownika:
device_create_file(dev, &dev_attr_version);
Miałbyś wtedy plik dla swojego urządzenia /sys/
, na przykład /sys/block/myblk/version
dla sterownika blokowego.
Inną metodą do intensywniejszego wykorzystania jest netlink, czyli metoda IPC (komunikacja między procesami) służąca do komunikacji ze sterownikiem przez interfejs gniazda BSD. Jest to używane na przykład przez sterowniki WiFi. Następnie komunikujesz się z nim z przestrzeni użytkownika za pomocą bibliotek libnl
lub libnl3
.
ioctl
Funkcja ta jest przydatna do realizacji sterownika ustawić konfigurację urządzenia. np. drukarka posiadająca opcje konfiguracyjne do sprawdzania i ustawiania rodziny czcionek, rozmiaru czcionki itp.ioctl
może być użyta do pobrania aktualnej czcionki, jak również ustawienia nowej czcionki. Aplikacja użytkownika używaioctl
do wysyłania kodu do drukarki z poleceniem zwrócenia bieżącej czcionki lub ustawienia nowej czcionki.fd
jest deskryptorem pliku, tym zwróconym przezopen
;request
to kod żądania. np.GETFONT
pobierze aktualną czcionkę z drukarki,SETFONT
ustawi czcionkę na drukarce;void *
. W zależności od drugiego argumentu, trzeci może być obecny lub nie, np. Jeśli drugi argument jestSETFONT
, trzecim argumentem może być nazwa czcionki, taka jak"Arial"
;int request
to nie tylko makro. Aplikacja użytkownika jest wymagana do wygenerowania kodu żądania i modułu sterownika urządzenia, aby określić, z jaką konfiguracją urządzenia należy odtwarzać. Aplikacja wysyła kod żądania za pomocą,ioctl
a następnie używa kodu żądania w module sterownika urządzenia, aby określić, jakie działanie ma wykonać.Kod żądania składa się z 4 głównych części
Jeśli kod żądania ma
SETFONT
ustawić czcionkę na drukarce, dane będą przesyłane z aplikacji użytkownika do modułu sterownika urządzenia (aplikacja użytkownika wysyła nazwę czcionki"Arial"
do drukarki). Jeśli kod żądania toGETFONT
, kierunek prowadzi z drukarki do aplikacji użytkownika.Aby wygenerować kod żądania, Linux udostępnia pewne predefiniowane makra podobne do funkcji.
1.
_IO(MAGIC, SEQ_NO)
oba mają 8 bitów, od 0 do 255, np. Powiedzmy, że chcemy wstrzymać drukarkę. Nie wymaga to przesyłania danych. Więc wygenerujemy kod żądania, jak poniżeja teraz użyj
ioctl
jakoOdpowiednie wywołanie systemowe w module sterownika otrzyma kod i wstrzyma drukarkę.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
iSEQ_NO
są takie same jak powyżej iTYPE
podaje typ następnego argumentu, przypomnij sobie trzeci argumentioctl
isvoid *
. W in__IOW
wskazuje, że przepływ danych odbywa się z aplikacji użytkownika do modułu sterownika. Na przykład załóżmy, że chcemy ustawić czcionkę drukarki na"Arial"
.dalej,
Teraz
font
jest wskaźnikiem, co oznacza, że jest to adres najlepiej reprezentowany jakounsigned long
, stąd trzecia część_IOW
typu jako takiego. Ponadto ten adres czcionki jest przekazywany do odpowiedniego wywołania systemowego zaimplementowanego w module sterownika urządzenia jakounsigned long
i przed użyciem musimy go rzutować na odpowiedni typ. Przestrzeń jądra może uzyskać dostęp do przestrzeni użytkownika i dlatego to działa. pozostałe dwa makra podobne do funkcji to__IOR(MAGIC, SEQ_NO, TYPE)
i__IORW(MAGIC, SEQ_NO, TYPE)
gdzie przepływ danych będzie odbywał się odpowiednio z przestrzeni jądra do przestrzeni użytkownika iw obie strony.Proszę daj mi znać, czy to pomogło!
źródło