IOCTL Linux device driver

Czy ktoś może mi wyjaśnić,

  1. Co to jest IOCTL?
  2. w jakim celu się go stosuje?
  3. Jak mogę go użyć?
  4. Dlaczego nie mogę zdefiniować nowej funkcji, która działa tak samo jak IOCTL?
Author: Abhijeet Kasurde, 2013-04-04

2 answers

AN ioctl, co oznacza "Kontrola wejścia-wyjścia" jest rodzajem wywołania systemowego specyficznego dla urządzenia. Istnieje tylko kilka wywołań systemowych w Linuksie (300-400), które nie są wystarczające, aby wyrazić wszystkie unikalne funkcje, jakie mogą mieć urządzenia. Tak więc sterownik może zdefiniować ioctl, który pozwala aplikacji w przestrzeni użytkownika wysyłać jej zamówienia. Jednak ioctle nie są zbyt elastyczne i mają tendencję do nieco zaśmiecania (dziesiątki "magicznych liczb", które po prostu działają... lub nie), a także może być niebezpieczne, gdy przekazujesz bufor do jądra - złe prowadzenie może łatwo zepsuć rzeczy.

Alternatywą jest interfejs sysfs, w którym ustawiasz plik pod {[4] } i odczytujesz/zapisujesz, aby uzyskać informacje od I do sterownika. Przykład jak to skonfigurować:

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);

I podczas konfiguracji sterownika:

device_create_file(dev, &dev_attr_version);

W /sys/, na przykład, /sys/block/myblk/version dla sterownika blokowego, znajduje się plik dla urządzenia.

Inną metodą jest netlink, czyli metoda IPC (inter-process communication), z którą można rozmawiać sterownik 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.

 68
Author: Inductiveload,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-18 17:52:40

ioctl funkcja jest przydatna, gdy implementuje się Sterownik urządzenia, aby ustawić konfigurację na urządzeniu. np. drukarka ma opcje konfiguracji, aby sprawdzić i ustawić czcionkę, rozmiar czcionki itp. ioctl może być użyty do uzyskania bieżącej czcionki, jak również ustawienia czcionki na inną. W aplikacji użytkownika użyj ioctl, Aby wysłać do drukarki kod z prośbą o zwrócenie bieżącej czcionki lub ustawienie czcionki na nową.

int ioctl(int fd, int request, ...)
  1. fd jest deskryptorem pliku, zwracanym przez otwórz
  2. request jest kodem żądania. np. GETFONT pobierze bieżącą czcionkę z drukarki, SETFONT ustawi czcionkę na drukarce.
  3. trzecim argumentem jest void *. W zależności od drugiego argumentu, trzeci może być obecny lub nie. na przykład, jeśli drugim argumentem jest SETFONT, trzeci argument może dać nazwę czcionki jako ARIAL.

Więc teraz int request nie jest tylko makrem, trzeba wygenerować kod żądania, który będzie używany przez aplikację użytkownika i moduł sterownika urządzenia do określenia, które konfiguracja na urządzeniu musi być odtwarzana. Wysyłamy kod żądania za pomocą ioctl z aplikacji użytkownika, a następnie używamy kodu żądania w module sterownika urządzenia, aby określić, którą akcję wykonać.

Kod zapytania składa się z 4 głównych części

    1. A Magic number - 8 bits
    2. A sequence number - 8 bits
    3. Argument type (typically 14 bits), if any.
    4. Direction of data transfer (2 bits).  

Jeśli kod żądania jest USTAWIONYFONT, aby ustawić czcionkę na drukarce, kierunek transferu danych będzie od aplikacji użytkownika do modułu sterownika urządzenia. Użytkownik wysyła nazwę czcionki Arial do drukarki. Jeśli kod żądania to GETFONT, kierunek jest od drukarki do aplikacja użytkownika.

Aby wygenerować kod żądania, Linux dostarcza pewne predefiniowane funkcje, takie jak makra.

1._IO(MAGIC, SEQ_NO) oba są 8 bitami, od 0 do 255, np. powiedzmy, że chcemy wstrzymać drukarkę. Nie wymaga to transferu adata. Tak więc wygenerowalibyśmy kod żądania jak poniżej

    #define PRIN_MAGIC 'P'
    #define NUM 0
    #define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

Teraz użyjioctl jako

    ret_val = ioctl(fd, PAUSE_PRIN);

Odpowiednie wywołanie systemowe w module sterownika odbierze kod i wstrzyma drukarkę.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGIC i SEQ_NO są takie same jak powyżej, ale trzecia część podaje Typ następnego argumentu, przypomnijmy trzeci argument ioctl to void *. W in __IOW wskazuje, że kierunek danych jest od aplikacji użytkownika do modułu sterownika. Weźmy przykład, Załóżmy, że mówi się drukarce, aby ustawiła czcionkę na Arial.

    #define PRIN_MAGIC 'S'
    #define SEQ_NO 1
    #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)
    

Dalej,

    char *font = "Arial";
    ret_val = ioctl(fd, SETFONT, font); 

Teraz font jest wskaźnikiem, co oznacza, że jest to adres najlepiej reprezentowany jako unsigned long, stąd trzecia część _IOW wymienia Typ jako taki. Również ten adres czcionki jest przekazywany do odpowiednie wywołanie systemowe zaimplementowane w module sterownika urządzenia jako unsigned long i przed użyciem musimy je oddać do odpowiedniego typu. Przestrzeń jądra może mieć dostęp do przestrzeni użytkownika i dlatego to działa. pozostałe dwie funkcje takie jak makra to __IOR(MAGIC, SEQ_NO, TYPE) i __IORW(MAGIC, SEQ_NO, TYPE), gdzie kierunek przepływu danych będzie odpowiednio z przestrzeni jądra do przestrzeni użytkownika i w obie strony.

Proszę dać mi znać, jeśli to pomoże!

 117
Author: anukalp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-09 19:17:58