Controlador de dispositivo IOCTL Linux [cerrado]


126

¿Alguien puede explicarme?

  1. ¿Qué es IOCTL?
  2. ¿Para qué se usa esto?
  3. ¿Como puedo usar lo?
  4. ¿Por qué no puedo definir una nueva función que funcione igual que IOCTL?

Respuestas:


99

Un ioctl, que significa "control de entrada-salida" es un tipo de llamada de sistema específica del dispositivo. Solo hay unas pocas llamadas al sistema en Linux (300-400), que no son suficientes para expresar todas las funciones únicas que pueden tener los dispositivos. Por lo tanto, un controlador puede definir un ioctl que permite que una aplicación de espacio de usuario le envíe pedidos. Sin embargo, los ioctls no son muy flexibles y tienden a estar un poco desordenados (docenas de "números mágicos" que simplemente funcionan ... o no), y también pueden ser inseguros, al pasar un búfer al núcleo: un mal manejo puede romperse cosas fácilmente

Una alternativa es la sysfsinterfaz, donde configura un archivo /sys/y lo lee / escribe para obtener información desde y hacia el controlador. Un ejemplo de cómo configurar esto:

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);

Y durante la configuración del controlador:

device_create_file(dev, &dev_attr_version);

Entonces tendría un archivo para su dispositivo /sys/, por ejemplo, /sys/block/myblk/versionpara un controlador de bloque.

Otro método para un uso más pesado es netlink, que es un método IPC (comunicación entre procesos) para hablar con su controlador a través de una interfaz de socket BSD. Esto es utilizado, por ejemplo, por los controladores WiFi. Luego se comunica con él desde el espacio de usuario utilizando las bibliotecas libnlo libnl3.


3
Esta respuesta 'contesta' la pregunta parcialmente.
Vishal Sahu

163

La ioctlfunción es útil para implementar un controlador de dispositivo para establecer la configuración en el dispositivo. por ejemplo, una impresora que tiene opciones de configuración para verificar y establecer la familia de fuentes, el tamaño de fuente, etc., ioctlpodría usarse para obtener la fuente actual, así como establecer la fuente en una nueva. Una aplicación de usuario utiliza ioctlpara enviar un código a una impresora diciéndole que devuelva la fuente actual o que establezca la fuente en una nueva.

int ioctl(int fd, int request, ...)
  1. fdes el descriptor de archivo, el que devuelve open;
  2. requestEs el código de solicitud. por ejemplo GETFONT, obtendrá la fuente actual de la impresora, SETFONTestablecerá la fuente en la impresora;
  3. El tercer argumento es void *. Dependiendo del segundo argumento, el tercero puede o no estar presente, por ejemplo, si el segundo argumento es SETFONT, el tercer argumento puede ser el nombre de la fuente como "Arial";

int requestNo es solo una macro. Se requiere una aplicación de usuario para generar un código de solicitud y el módulo del controlador del dispositivo para determinar con qué configuración se debe jugar en el dispositivo. La aplicación envía el código de solicitud utilizando ioctly luego utiliza el código de solicitud en el módulo del controlador del dispositivo para determinar qué acción realizar.

Un código de solicitud tiene 4 partes 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 el código de solicitud es SETFONTestablecer la fuente en una impresora, la dirección para la transferencia de datos será desde la aplicación del usuario al módulo del controlador del dispositivo (la aplicación del usuario envía el nombre de la fuente "Arial"a la impresora). Si el código de solicitud es GETFONT, la dirección es de la impresora a la aplicación del usuario.

Para generar un código de solicitud, Linux proporciona algunas macros predefinidas similares a funciones.

1. _IO(MAGIC, SEQ_NO)ambos son de 8 bits, de 0 a 255, por ejemplo, digamos que queremos pausar la impresora. Esto no requiere una transferencia de datos. Entonces generaríamos el código de solicitud de la siguiente manera

#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

y ahora usar ioctlcomo

ret_val = ioctl(fd, PAUSE_PRIN);

La llamada del sistema correspondiente en el módulo del controlador recibirá el código y pausará la impresora.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGICy SEQ_NOson los mismos que los anteriores, y TYPEda el tipo del siguiente argumento, recuerde el tercer argumento de ioctlis void *. W in __IOWindica que el flujo de datos es de la aplicación del usuario al módulo del controlador. Como ejemplo, supongamos que queremos establecer la fuente de la impresora en "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

más lejos,

char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font); 

Ahora fontes un puntero, lo que significa que es una dirección mejor representada como unsigned long, por lo tanto, la tercera parte del _IOWtipo de menciones como tal. Además, esta dirección de fuente se pasa a la llamada del sistema correspondiente implementada en el módulo del controlador del dispositivo unsigned long y debemos convertirla al tipo adecuado antes de usarla. El espacio del kernel puede acceder al espacio del usuario y, por lo tanto, esto funciona. otras dos macros de tipo funcional son __IOR(MAGIC, SEQ_NO, TYPE)y __IORW(MAGIC, SEQ_NO, TYPE)donde el flujo de datos será del espacio del núcleo al espacio del usuario y en ambos sentidos, respectivamente.

¡Avísame si esto te ayuda!


Me pregunto si las funciones anteriores __IOW, __IOR y __IORW son correctas (me refiero al doble guión bajo en algunos casos, en algunos casos no. Nunca he usado el guión bajo doble) ... ¡Gracias por una explicación clara!
jcoppens

Muy bien explicado .. Gracias! ¿Puede dar un pequeño fragmento de código del lado del controlador que utiliza este ioctl?
Aadishri


Muy bien explicado. Gracias. Creo que es _IOWR no _IORW
Mohamed Samy

Responda como una publicación de blog.
Fredrick Gauss el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.