Driver di dispositivo IOCTL Linux [chiuso]


126

Qualcuno può spiegarmi,

  1. Che cosa è IOCTL?
  2. A cosa serve?
  3. Come posso usarlo?
  4. Perché non riesco a definire una nuova funzione che funzioni esattamente come IOCTL?

Risposte:


99

Un ioctl, che significa "controllo input-output" è un tipo di chiamata di sistema specifica del dispositivo. Ci sono solo alcune chiamate di sistema in Linux (300-400), che non sono sufficienti per esprimere tutte le funzioni uniche che i dispositivi potrebbero avere. Quindi un driver può definire un ioctl che consente a un'applicazione di spazio utente di inviargli ordini. Tuttavia, gli ioctl non sono molto flessibili e tendono ad essere un po 'ingombranti (dozzine di "numeri magici" che funzionano solo ... o no) e possono anche essere insicuri, quando si passa un buffer nel kernel - una cattiva gestione può rompersi le cose facilmente.

Un'alternativa è l' sysfsinterfaccia, in cui è possibile impostare un file in /sys/e leggere / scrivere che per ottenere informazioni da e per il driver. Un esempio di come configurarlo:

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

E durante l'installazione del driver:

device_create_file(dev, &dev_attr_version);

Avresti quindi un file per il tuo dispositivo /sys/, ad esempio /sys/block/myblk/versionper un driver di blocco.

Un altro metodo per un uso più pesante è netlink, che è un metodo IPC (comunicazione tra processi) per comunicare con il driver tramite un'interfaccia socket BSD. Questo viene utilizzato, ad esempio, dai driver WiFi. Quindi comunichi con esso dallo spazio utente usando le librerie libnlo libnl3.


3
Questa risposta "risponde" parzialmente alla domanda.
Vishal Sahu,

163

La ioctlfunzione è utile per implementare un driver di dispositivo per impostare la configurazione sul dispositivo. ad es. una stampante che ha opzioni di configurazione per controllare e impostare la famiglia di caratteri, la dimensione del carattere ecc. ioctlpotrebbe essere utilizzata per ottenere il carattere corrente e impostarne uno nuovo. Un'applicazione utente utilizza ioctlper inviare un codice a una stampante che gli dice di restituire il carattere corrente o di impostarne uno nuovo.

int ioctl(int fd, int request, ...)
  1. fdè il descrittore di file, quello restituito da open;
  2. requestè il codice di richiesta. ad es. GETFONTotterrà il carattere corrente dalla stampante, SETFONTimposterà il carattere sulla stampante;
  3. il terzo argomento è void *. A seconda del secondo argomento, il terzo può essere o meno presente, ad esempio se il secondo argomento è SETFONT, il terzo argomento può essere il nome del carattere come "Arial";

int requestnon è solo una macro. È richiesta un'applicazione utente per generare un codice di richiesta e il modulo del driver del dispositivo per determinare con quale configurazione sul dispositivo deve essere giocato. L'applicazione invia il codice di richiesta utilizzando ioctle quindi utilizza il codice di richiesta nel modulo del driver del dispositivo per determinare quale azione eseguire.

Un codice di richiesta ha 4 parti principali

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

Se il codice di richiesta deve SETFONTimpostare il carattere su una stampante, la direzione per il trasferimento dei dati sarà dall'applicazione utente al modulo del driver del dispositivo (l'applicazione utente invia il nome del carattere "Arial"alla stampante). Se il codice di richiesta è GETFONT, la direzione va dalla stampante all'applicazione utente.

Per generare un codice di richiesta, Linux fornisce alcune macro simili a funzioni predefinite.

1. _IO(MAGIC, SEQ_NO)entrambi sono 8 bit, da 0 a 255, ad esempio diciamo che vogliamo mettere in pausa la stampante. Ciò non richiede un trasferimento di dati. Quindi generiamo il codice di richiesta come di seguito

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

e ora usa ioctlcome

ret_val = ioctl(fd, PAUSE_PRIN);

La chiamata di sistema corrispondente nel modulo driver riceverà il codice e metterà in pausa la stampante.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGICe SEQ_NOsono gli stessi di cui sopra, e TYPEfornisce il tipo di argomento successivo, ricordando il terzo argomento di ioctlis void *. W in __IOWindica che il flusso di dati va dall'applicazione utente al modulo driver. Ad esempio, supponiamo di voler impostare il carattere della stampante su "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

ulteriore,

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

Ora fontè un puntatore, il che significa che è un indirizzo meglio rappresentato come unsigned long, quindi la terza parte del _IOWtipo di menzioni come tale. Inoltre, questo indirizzo di carattere viene passato alla chiamata di sistema corrispondente implementata nel modulo del driver di dispositivo poiché unsigned long è necessario eseguirne il cast al tipo corretto prima di utilizzarlo. Lo spazio del kernel può accedere allo spazio utente e quindi funziona. altre due macro simili a funzioni sono __IOR(MAGIC, SEQ_NO, TYPE)e __IORW(MAGIC, SEQ_NO, TYPE)dove il flusso di dati sarà dallo spazio del kernel allo spazio dell'utente e in entrambi i modi, rispettivamente.

Per favore fatemi sapere se questo aiuta!


Mi chiedo se le funzioni __IOW, __IOR e __IORW sopra siano corrette (intendo il doppio carattere di sottolineatura in alcuni casi, in alcuni casi no. Non ho mai usato il doppio carattere di sottolineatura) ... Grazie per una spiegazione chiara!
jcoppens,

Molto ben spiegato .. Grazie! Potete per favore fornire un piccolo frammento di codice del lato driver che utilizza questo ioctl?
Aadishri,


Molto ben spiegato. Grazie. Penso che sia _IOWR non _IORW
Mohamed Samy

Rispondi come un post sul blog.
Fredrick Gauss,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.