Comment Linux sait quelle fonction ioctl appeler?

Voici l’appel ioctl dans l’espace utilisateur:

 int ioctl(int fd, int cmd, ...); 

Pour autant que je sache, lorsque nous souhaitons effectuer des opérations IO, nous définissons notre propre fonction ioctl avec un ensemble de requêtes (commandes), affectons notre ioctl à une structure file_operations comme celle-ci:

 struct file_operations fops = { .read = device_read, .write = device_write, .ioctl = device_ioctl, // device_ioctl is our function .open = device_open, .release = device_release, }; 

Et la fonction device_ioctl est définie différemment par rapport à l’interface de l’espace utilisateur:

 static long device_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 

Je pense que sur la base du descripteur de fichier, le kernel peut obtenir la structure de fichier appropriée et appelle l’ ioctl du périphérique.

Ceci est juste une supposition parce que je ne peux pas trouver la définition de la fonction générique où le kernel sélectionne la fonction ioctl appropriée en fonction du descripteur de fichier fd transmis à l’interface ioctl générique? Il n’y a que 3 définitions ioctl je peux trouver, mais apparemment ce ne sont que les définitions des périphériques, pas le kernel: ioctl

Regardez dans le code source Linux, fs / ioctl.c ( http://lxr.free-electrons.com/source/fs/ioctl.c )
Là, vous verrez le syscall pour ioctl:

 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 

Cela appelle tour à tour do_vfs_ioctl (), qui appelle vfs_ioctl (), qui appelle ensuite la fonction unlocked_ioctl définie pour ce système de fichiers dans la structure file_operations.
Ce sera votre fonction device_ioctl que vous avez enregistrée.

device_ioctl est un pointeur de fonction. Le kernel prend simplement fd comme index pour un tableau de struct file_operations et appelle le .ioctl de l’élément correspondant. Le kernel n’a jamais besoin de savoir quelle fonction elle-même est quel périphérique auquel elle fait référence.

C’est la base de “Tout est un fichier”, qui est la devise d’Unix.

Lorsque vous appelez ioctl vous passez un descripteur de fichier. Vous avez le descripteur de fichier pour ouvrir un fichier de périphérique comme /dev/tty0 :

 $ ls -l /dev/tty0 crw--w---- 1 root tty 4, 0 Mar 6 10:47 /dev/tty0 $ 

Le nombre 4 est le numéro majeur du périphérique qui est encodé dans le module pilote que le kernel doit utiliser.

Le kernel saura quelle fonction ioctl appeler à cause du descripteur de fichier . Pour pouvoir appeler un ioctl () à partir de l’espace utilisateur, vous devrez ouvrir un fichier pour obtenir le fichier fd , un fichier / dev / [some_device] dont le pilote implémentera la structure file_operations, comme vous l’avez souligné.