Controlador de dispositivo Linux IOCTL


¿Puede alguien explicarme,

  1. ¿Qué es IOCTL?
  2. ¿para Qué se utiliza?
  3. ¿Cómo puedo usarlo?
  4. ¿Por qué no puedo definir una nueva función que haga el mismo trabajo que IOCTL?
Author: Abhijeet Kasurde, 2013-04-04

2 answers

Un ioctl, que significa "control de entrada-salida" es un tipo de llamada al 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 ioctl 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 puede ser inseguro, ya que pasa un búfer al núcleo - el mal manejo puede romper las cosas fácilmente.

Una alternativa es la interfaz sysfs, donde se configura un archivo bajo /sys/ y se 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 en /sys/, por ejemplo, /sys/block/myblk/version para 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 libnl o libnl3.

 68
Author: Inductiveload,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-18 17:52:40

ioctl la función es útil cuando se está implementando un controlador de dispositivo para establecer la configuración en el dispositivo. por ejemplo, una impresora tiene opciones de configuración para verificar y establecer la fuente, el tamaño de la fuente, etc. ioctl podría usarse para obtener la fuente actual, así como para establecer la fuente en otra. En la aplicación de usuario haga uso de ioctl para 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. {[9] } es el descriptor de fichero, el que devuelve abierto
  2. request es el código de solicitud. por ejemplo, GETFONT obtendrá la fuente actual de la impresora, SETFONT establecerá la fuente en una 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 dar el nombre de la fuente como ARIAL.

Así que ahora la solicitud int no es solo una macro, se requiere generar código de solicitud para ser utilizado por la aplicación de usuario y el módulo de controlador de dispositivo para determinar qué se debe jugar con la configuración del dispositivo. Uno envía un código de solicitud usando ioctl desde la aplicación de usuario y luego usa el código de solicitud en el módulo de controlador de 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 SETFONT para establecer 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. El 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 aplicación de usuario.

Para generar código de solicitud Linux proporciona algunas funciones predefinidas como macros.

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 transferencia de adata. Así que generaríamos código de solicitud como se muestra a continuación

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

Ahora use ioctl como

    ret_val = ioctl(fd, PAUSE_PRIN);

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

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGIC y SEQ_NO son los mismos que los anteriores, pero la tercera parte da el tipo de siguiente argumento, recordar el tercer argumento de ioctl es void *. W en __IOW indica que la dirección de los datos es de la aplicación del usuario al módulo del controlador. Tomemos un ejemplo, Supongamos que uno le está diciendo a la impresora que establezca la fuente en Arial.

    #define PRIN_MAGIC 'S'
    #define SEQ_NO 1
    #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)
    

Además,

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

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

Por favor, hágamelo saber si esto ayuda!

 117
Author: anukalp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-09 19:17:58