Linux_IoCtl - Kasimashi/Systemes-embarques GitHub Wiki
L'IoCTL (Input/Output Control) est une interface de programmation qui permet de communiquer avec des périphériques matériels, des pilotes de périphériques ou des systèmes d'exploitation. C'est un mécanisme permettant à une application d'envoyer des commandes ou de contrôler le comportement de matériel ou de pilotes au niveau du noyau. L'IoCTL est utilisé principalement sous des systèmes Unix/Linux et Windows pour des opérations spécifiques sur les périphériques, comme l'accès à des fichiers ou la gestion des entrées-sorties (E/S).
-
Appel à une fonction du noyau : Lorsqu'un programme souhaite interagir avec un périphérique (par exemple un disque dur, un périphérique réseau), il peut appeler une fonction
ioctl()
, qui envoie une commande au noyau pour effectuer une opération spécifique sur le périphérique. -
Identifiant unique : Chaque commande IoCTL possède un identifiant unique appelé code de commande. Ces codes peuvent être définis par les développeurs du noyau ou les pilotes de périphériques pour des actions particulières.
-
Communication bidirectionnelle : L'IoCTL permet non seulement d'envoyer des commandes mais aussi de recevoir des données de retour du périphérique ou du noyau.
En général, l'appel à ioctl()
en C sous Linux se fait de la manière suivante :
int ioctl(int fd, unsigned long request, ...);
- fd : Le descripteur de fichier du périphérique.
- request : Le code de commande (l'opération à effectuer).
- ... : Des arguments optionnels (souvent des pointeurs vers des structures de données ou des tampons pour l'entrée et la sortie).
Voici un exemple simple où l'on ouvre un périphérique et on utilise ioctl() pour effectuer une opération :
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>
#define MY_IOCTL_COMMAND 0x1234
int main() {
int fd = open("/dev/mydevice", O_RDWR);
if (fd == -1) {
perror("Erreur d'ouverture du périphérique");
return 1;
}
int result = ioctl(fd, MY_IOCTL_COMMAND, NULL);
if (result == -1) {
perror("Erreur d'exécution de l'IoCTL");
} else {
printf("Commande IoCTL exécutée avec succès\n");
}
close(fd);
return 0;
}
Sous Windows, DeviceIoControl() est utilisé à la place de ioctl(). Voici un exemple basique :
#include <windows.h>
#include <stdio.h>
#define MY_IOCTL_COMMAND 0x1234
int main() {
HANDLE hDevice = CreateFile("\\\\.\\MyDevice", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Erreur d'ouverture du périphérique\n");
return 1;
}
DWORD bytesReturned;
BOOL result = DeviceIoControl(hDevice, MY_IOCTL_COMMAND, NULL, 0, NULL, 0,
&bytesReturned, NULL);
if (result) {
printf("Commande IoCTL exécutée avec succès\n");
} else {
printf("Erreur d'exécution de l'IoCTL\n");
}
CloseHandle(hDevice);
return 0;
}
Les commandes IoCTL sont définies selon un format standard pour éviter les conflits entre différents types de périphériques. Typiquement, elles suivent ce format :
#define _IO(type, nr) _IOC(_IOC_NONE, type, nr, 0)
#define _IOR(type, nr, size) _IOC(_IOC_READ, type, nr, size)
#define _IOW(type, nr, size) _IOC(_IOC_WRITE, type, nr, size)
#define _IOWR(type, nr, size) _IOC(_IOC_READ|_IOC_WRITE, type, nr, size)
L'IoCTL est un mécanisme puissant et flexible pour interagir avec les périphériques et effectuer des opérations spécifiques à bas niveau. Cependant, son utilisation nécessite une bonne connaissance des périphériques et de leur gestion au niveau du noyau, car des erreurs peuvent entraîner des comportements inattendus ou des plantages système.