Quelqu'un peut-il m'expliquer,
- C'est quoi
IOCTL
? - A quoi cela sert?
- Comment puis-je l'utiliser?
- Pourquoi ne puis-je pas définir une nouvelle fonction qui fait le même travail que
IOCTL
?
la source
Quelqu'un peut-il m'expliquer,
IOCTL
?IOCTL
?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' sysfs
interface, 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/version
pour 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 libnl
ou libnl3
.
La
ioctl
fonction 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.ioctl
pourrait être utilisée pour obtenir la police actuelle ainsi que pour définir la police sur une nouvelle police. Une application utilisateur utiliseioctl
pour envoyer un code à une imprimante lui indiquant de renvoyer la police actuelle ou de définir la police sur une nouvelle police.fd
est le descripteur de fichier, celui renvoyé paropen
;request
est le code de demande. par exempleGETFONT
obtiendra la police actuelle de l'imprimante,SETFONT
définira la police sur l'imprimante;void *
. Selon le deuxième argument, le troisième peut être présent ou non, par exemple, si le deuxième argument estSETFONT
, le troisième argument peut être le nom de la police tel que"Arial"
;int request
n'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 utilisantioctl
, 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
Si le code de demande est
SETFONT
de 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 estGETFONT
, 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-dessouset maintenant utiliser
ioctl
commeL'appel système correspondant dans le module de pilote recevra le code et mettra l'imprimante en pause.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
etSEQ_NO
sont les mêmes que ci-dessus, etTYPE
donne le type de l'argument suivant, rappelez-vous le troisième argument deioctl
estvoid *
. W in__IOW
indique 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"
.plus loin,
Maintenant
font
est un pointeur, ce qui signifie que c'est une adresse mieux représentée commeunsigned long
, d'où la troisième partie du_IOW
type 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ériqueunsigned 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!
la source