Pilote de périphérique Linux IOCTL [fermé]


126

Quelqu'un peut-il m'expliquer,

  1. C'est quoi IOCTL?
  2. A quoi cela sert?
  3. Comment puis-je l'utiliser?
  4. Pourquoi ne puis-je pas définir une nouvelle fonction qui fait le même travail que IOCTL?

Réponses:


99

An ioctl, qui signifie «contrôle d'entrée-sortie», est une sorte d'appel système spécifique à l'appareil. Il n'y a que quelques appels système sous Linux (300-400), qui ne sont pas suffisants pour exprimer toutes les fonctions uniques que les périphériques peuvent avoir. Ainsi, un pilote peut définir un ioctl qui permet à une application de l'espace utilisateur de lui envoyer des commandes. Cependant, les ioctls ne sont pas très flexibles et ont tendance à être un peu encombrés (des dizaines de "nombres magiques" qui fonctionnent juste ... ou pas), et peuvent également être peu sûrs, car vous passez un tampon dans le noyau - une mauvaise manipulation peut casser les choses facilement.

Une alternative est l' sysfsinterface, où vous configurez un fichier sous /sys/et que vous lisez / écrivez pour obtenir des informations depuis et vers le pilote. Un exemple de la façon de configurer cela:

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

Et pendant la configuration du pilote:

device_create_file(dev, &dev_attr_version);

Vous auriez alors un fichier pour votre périphérique /sys/, par exemple /sys/block/myblk/versionpour un pilote de bloc.

Une autre méthode pour une utilisation plus intensive est netlink, qui est une méthode IPC (communication inter-processus) pour parler à votre pilote via une interface de socket BSD. Ceci est utilisé, par exemple, par les pilotes WiFi. Vous communiquez ensuite avec lui depuis l'espace utilisateur à l'aide des bibliothèques libnlou libnl3.


3
Cette réponse «répond» partiellement à la question.
Vishal Sahu

163

La ioctlfonction est utile pour implémenter un pilote de périphérique pour définir la configuration sur le périphérique. par exemple, une imprimante qui a des options de configuration pour vérifier et définir la famille de polices, la taille de la police, etc. ioctlpourrait être utilisée pour obtenir la police actuelle ainsi que pour définir la police sur une nouvelle police. Une application utilisateur utilise ioctlpour envoyer un code à une imprimante lui indiquant de renvoyer la police actuelle ou de définir la police sur une nouvelle police.

int ioctl(int fd, int request, ...)
  1. fdest le descripteur de fichier, celui renvoyé par open;
  2. requestest le code de demande. par exemple GETFONTobtiendra la police actuelle de l'imprimante, SETFONTdéfinira la police sur l'imprimante;
  3. le troisième argument est void *. Selon le deuxième argument, le troisième peut être présent ou non, par exemple, si le deuxième argument est SETFONT, le troisième argument peut être le nom de la police tel que "Arial";

int requestn'est pas qu'une macro. Une application utilisateur est requise pour générer un code de demande et le module de pilote de périphérique pour déterminer avec quelle configuration sur le périphérique doit être joué. L'application envoie le code de demande en utilisant ioctl, puis utilise le code de demande dans le module de pilote de périphérique pour déterminer l'action à effectuer.

Un code de demande comprend 4 parties principales

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

Si le code de demande est SETFONTde définir la police sur une imprimante, la direction du transfert de données sera de l'application utilisateur au module de pilote de périphérique (l'application utilisateur envoie le nom "Arial"de la police à l'imprimante). Si le code de demande est GETFONT, la direction va de l'imprimante vers l'application utilisateur.

Afin de générer un code de requête, Linux fournit des macros de type fonction prédéfinies.

1. les _IO(MAGIC, SEQ_NO)deux sont 8 bits, de 0 à 255, par exemple, disons que nous voulons mettre l'imprimante en pause. Cela ne nécessite pas de transfert de données. Nous générerions donc le code de demande comme ci-dessous

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

et maintenant utiliser ioctlcomme

ret_val = ioctl(fd, PAUSE_PRIN);

L'appel système correspondant dans le module de pilote recevra le code et mettra l'imprimante en pause.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGICet SEQ_NOsont les mêmes que ci-dessus, et TYPEdonne le type de l'argument suivant, rappelez-vous le troisième argument de ioctlest void *. W in __IOWindique que le flux de données va de l'application utilisateur au module pilote. Par exemple, supposons que nous voulions définir la police de l'imprimante sur "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

plus loin,

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

Maintenant fontest un pointeur, ce qui signifie que c'est une adresse mieux représentée comme unsigned long, d'où la troisième partie du _IOWtype de mentions en tant que tel. En outre, cette adresse de police est transmise à l'appel système correspondant implémenté dans le module de pilote de périphérique unsigned long et nous devons le convertir au type approprié avant de l'utiliser. L'espace noyau peut accéder à l'espace utilisateur et donc cela fonctionne. les deux autres macros fonctionnelles sont __IOR(MAGIC, SEQ_NO, TYPE)et __IORW(MAGIC, SEQ_NO, TYPE)où le flux de données sera de l'espace noyau à l'espace utilisateur et dans les deux sens respectivement.

Faites-moi savoir si cela vous aide!


Je me demande si les fonctions __IOW, __IOR et __IORW ci-dessus sont correctes (je veux dire le double soulignement dans certains cas, dans certains cas non. Je n'ai jamais utilisé le double soulignement) ... Merci pour une explication claire!
jcoppens

Très bien expliqué .. Merci! Pouvez-vous s'il vous plaît donner un petit extrait de code du côté pilote qui utilise cet ioctl?
Aadishri


Très bien expliqué. Je vous remercie. Je pense que c'est _IOWR pas _IORW
Mohamed Samy

Répondez comme un article de blog.
Fredrick Gauss
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.