Quelqu'un peut-il m'expliquer,
- Qu'est-ce que
IOCTL
? - A quoi sert-il ?
- Comment puis-je l'utiliser ?
- Pourquoi je ne peux pas définir une nouvelle fonction qui fait le même travail que
IOCTL
?
Quelqu'un peut-il m'expliquer,
IOCTL
?IOCTL
?Le site ioctl
est utile pour mettre en œuvre un pilote de périphérique afin de définir la configuration du périphérique. Par exemple, une imprimante qui possède des options de configuration pour vérifier et définir la famille de polices, la taille des polices, etc. ioctl
peut être utilisé pour obtenir la police actuelle et pour définir une nouvelle police. Une application utilisateur utilise ioctl
pour envoyer un code à une imprimante lui demandant de renvoyer la police actuelle ou d'en choisir une nouvelle.
int ioctl(int fd, int request, ...)
fd
est un descripteur de fichier, celui retourné par open
;request
est le code de la demande, par exemple GETFONT
récupère la police actuelle de l'imprimante, SETFONT
définira la police de l'imprimante ;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 request
n'est pas seulement une macro. Une application utilisateur est nécessaire pour générer un code de demande et le module du pilote de périphérique pour déterminer avec quelle configuration du périphérique il faut jouer. L'application envoie le code de requête en utilisant ioctl
et utilise ensuite le code de demande dans le module du pilote de périphérique pour déterminer l'action à effectuer.
Un code de demande comporte 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 la demande est SETFONT
pour définir la police de caractères d'une imprimante, le transfert de données s'effectue de l'application utilisateur vers le module du pilote de périphérique (l'application utilisateur envoie le nom de police "Arial"
à l'imprimante). Si le code de demande est GETFONT
La direction est celle de l'imprimante vers l'application de l'utilisateur.
Afin de générer un code de demande, Linux fournit quelques macros prédéfinies de type fonction.
1. _IO(MAGIC, SEQ_NO)
Les deux sont de 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érerons donc le code de demande comme suit
#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM)
et utiliser maintenant ioctl
comme
ret_val = ioctl(fd, PAUSE_PRIN);
L'appel système correspondant dans le module pilote recevra le code et mettra l'imprimante en pause.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
y SEQ_NO
sont les mêmes que ci-dessus, et TYPE
donne le type de l'argument suivant, rappelez-vous le troisième argument de ioctl
es void *
. W dans __IOW
indique que le flux de données va de l'application utilisateur au module pilote. A titre d'exemple, supposons que nous voulions définir la police de l'imprimante sur "Arial"
.
plus loin,
char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font);
Ahora font
est un pointeur, ce qui signifie que c'est une adresse représentée au mieux par unsigned long
d'où la troisième partie de _IOW
mentionne le type en tant que tel. De plus, cette adresse de la police est transmise à l'appel système correspondant mis en œuvre dans le module du pilote de périphérique, comme suit unsigned long
et nous devons le convertir en un type approprié avant de l'utiliser. L'espace du noyau peut accéder à l'espace utilisateur et donc cela fonctionne. Les deux autres macros de type fonction sont __IOR(MAGIC, SEQ_NO, TYPE)
y __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 !
Un site ioctl
La commande d'entrée-sortie est une sorte d'appel système spécifique au périphérique. Il n'y a que quelques appels système dans Linux (300-400), ce qui n'est pas suffisant pour exprimer toutes les fonctions uniques que les périphériques peuvent avoir. Un pilote peut donc définir un ioctl qui permet à une application de l'espace utilisateur de lui envoyer des ordres. Cependant, les ioctl ne sont pas très flexibles et ont tendance à être un peu encombrés (des douzaines de "chiffres magiques" qui fonctionnent... ou pas), et peuvent aussi être peu sûrs, car vous passez un tampon au noyau - une mauvaise manipulation peut facilement casser les choses.
Une alternative est le sysfs
où vous configurez un fichier sous /sys/
et le lire/écrire pour obtenir des informations de et vers le pilote. Voici un exemple de configuration :
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 aurez alors un fichier pour votre appareil dans le dossier /sys/
par exemple, /sys/block/myblk/version
pour un conducteur de bloc.
Une autre méthode pour une utilisation plus lourde est netlink, qui est une méthode IPC (communication inter-processus) pour parler à votre pilote via une interface socket BSD. Cette méthode est utilisée, par exemple, par les pilotes WiFi. Vous communiquez ensuite avec lui depuis l'espace utilisateur en utilisant la commande libnl
o libnl3
bibliothèques.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.