ioctl , la enciclopedia libre
ioctl es una llamada de sistema en Unix que permite a una aplicación controlar o comunicarse con un driver de dispositivo, fuera de los usuales read/write de datos. Esta llamada se originó en la versión 7 del AT&T Unix. Su nombre abrevia la frase input/output control.
Descripción
[editar]Una llamada ioctl toma como parámetros:
- un descriptor de archivos abierto
- un número de código de requerimiento
- también un valor entero, posiblemente sin signo (va al driver), o un puntero a datos (también va al driver y vuelve de él)
El kernel generalmente envía un ioctl directamente al driver, el cual puede interpretar el número de requerimiento y datos en cualquier forma requerida. Los escritores del driver documentan cada número de requerimiento del driver para ese driver particular, y los proveen de constantes en el archivo de cabeceras (*.h)
Algunos sistemas tienen convenciones en su codificación, dentro del número de codificación, el tamaño de los datos a ser transferidos desde o hacia el driver del dispositivo, la dirección de la transferencia de datos y la identidad del driver implementando el requerimiento.
Independientemente de que esa convención se cumpla o no, el kernel y el driver colaboran para entregar un código de error uniforme (señalados por la constante simbólica ENOTTY) a una aplicación que haga un requerimiento al driver que no reconozca.
El nemónico ENOTTY (tradicionalmente asociado con el mensaje textual "Not a typerwriter") viene del hecho de que en los sistemas iniciales que incorporaba una llamada ioctl, solo el dispositivo teletipo (tty) planteaba este error. A través del nemónico simbólico es ajustado por los requerimientos de compatibilidad; algunos sistemas modernos muy útilmente prestan un mensaje más general, como: "Inappropriate device control operation", o la localización del mismo.
TCSETS ejemplifica un ioctl en un puerto serial. Las llamadas de lectura y escritura normales en un puerto serial reciben y envían paquetes de datos. Una llamada ioctl(fd, TCSETS, data), independiente de las llamadas normales I/O, controla varias opciones del controlador, como la manipulación de caracteres especiales, o las señales de salida en el puerto (por ejemplo, la señal DTR).
Ejemplo de uso
[editar]Un ejemplo de uso para ioctl es el manejo de los leds del teclado, KDGKLED, KDSKBLED son las macros definidas para poder acceder a los leds que la mayoría de los teclados tienen.
#include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/kd.h> #include <time.h> #include <unistd.h> /*Encabezado para la función sleep() and close() */ int get_state(int fd,int *estado) { if (-1 == ioctl(fd, KDGKBLED, estado)){ /*Si la función ioctl devuelve -1, hubo un error, que será especificado en la función perror(), si es cero significa que finalizo exitosamente*/ perror("ioctl"); close(fd); return -1; } return 0; } void print_caps_lock_state(int estado) { printf("Estado Caps Lock: %s (%d)\n", (estado & K_CAPSLOCK) == K_CAPSLOCK ? "on" : "off", estado); } int apaga(int fd,int *estado) { get_state(fd,estado); if (-1 == ioctl(fd, KDSKBLED, *estado ^ K_CAPSLOCK)){ perror("ioctl set"); close(fd); return -1; } return 0; } int prende(int fd,int *estado) { if (-1 == ioctl(fd, KDSKBLED, K_CAPSLOCK)){ perror("ioctl set"); close(fd); return -1; } get_state(fd,estado); return 0; } int main() { int fd = open("/dev/tty0", O_NOCTTY); if (fd == -1){ perror("open"); return -1; } int estado = 0; prende(fd,&estado); sleep(1); apaga(fd,&estado); sleep(2); prende(fd,&estado); sleep(1); apaga(fd,&estado); close(fd); return 0; }