GNU/Linux >> Linux Esercitazione >  >> Linux

Driver di dispositivo Linux IOCTL

Il ioctl La funzione è utile per implementare un driver di dispositivo per impostare la configurazione sul dispositivo. per esempio. una stampante che ha opzioni di configurazione per controllare e impostare la famiglia di caratteri, la dimensione del carattere ecc. ioctl potrebbe essere utilizzato per ottenere il carattere corrente e impostare il carattere su uno nuovo. Un'applicazione utente utilizza ioctl per inviare un codice a una stampante dicendole di restituire il font 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 esempio GETFONT otterrà il font corrente dalla stampante, SETFONT imposterà il font sulla stampante;
  3. il terzo argomento è void * . A seconda del secondo argomento, il terzo può o non può essere presente, ad es. se il secondo argomento è SETFONT , il terzo argomento può essere il nome del font come "Arial";

int request non è solo una macro. È necessaria 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 riprodotto. L'applicazione invia il codice di richiesta utilizzando ioctl e 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 della richiesta è SETFONT per impostare 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 è 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 es. diciamo che vogliamo mettere in pausa la stampante. Ciò non richiede un trasferimento di dati. Quindi genereremmo il codice di richiesta come di seguito

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

e ora usa ioctl come

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) MAGIC e SEQ_NO sono gli stessi di sopra e TYPE fornisce il tipo dell'argomento successivo, ricorda il terzo argomento di ioctl è void * . Vincita in __IOW indica che il flusso di dati va dall'applicazione utente al modulo driver. Ad esempio, supponiamo di voler impostare il font della stampante su "Arial" .
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

ulteriormente,

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

Ora font è un puntatore, il che significa che è un indirizzo meglio rappresentato come unsigned long , da qui la terza parte di _IOW menziona il tipo in quanto tale. Inoltre, questo indirizzo del carattere viene passato alla corrispondente chiamata di sistema implementata nel modulo del driver del dispositivo come unsigned long e dobbiamo convertirlo nel tipo corretto prima di usarlo. 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à rispettivamente dallo spazio del kernel allo spazio utente e in entrambe le direzioni.

Per favore fatemi sapere se questo aiuta!


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

Un'alternativa è il sysfs interface, dove imposti un file sotto /sys/ e leggerlo/scriverlo per ottenere informazioni da e per il conducente. Un esempio di come impostarlo:

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 in /sys/ , ad esempio, /sys/block/myblk/version per un driver a blocchi.

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


Linux
  1. Linux – Intende montare un dispositivo in Linux?

  2. Linux – Sysfs e Devtmpfs?

  3. Linux:in che modo il kernel Linux conosce i numeri maggiori e minori del dispositivo?

  4. Driver per Huawei Linux su Ubuntu 13.04?

  5. Come creare un dispositivo a blocchi virtuali (dispositivo di loop/filesystem) in Linux

Tutto è file in Linux – Parte 1

Perché il metodo probe è necessario nei driver di dispositivo Linux oltre a init?

Uscita Linux lsblk

Come montare un dispositivo in Linux?

Come trovare il driver (modulo) associato a un dispositivo su Linux?

Comprensione dei driver di dispositivo Linux della webcam