GNU/Linux >> Tutoriales Linux >  >> Linux

Controlador de dispositivo IOCTL Linux

El ioctl La función es útil para implementar un controlador de dispositivo para establecer la configuración en el dispositivo. p.ej. una impresora que tiene opciones de configuración para verificar y establecer la familia de fuentes, el tamaño de fuente, etc. ioctl podría usarse para obtener la fuente actual, así como para establecer la fuente en una nueva. Una aplicación de usuario usa 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. fd es el descriptor de archivo, el devuelto por open;
  2. request es el código de solicitud. por ejemplo, GETFONT obtendrá la fuente actual de la impresora, SETFONT establecerá la fuente en la impresora;
  3. el tercer argumento es void * . Dependiendo del segundo argumento, el tercero puede o no estar presente, p. si el segundo argumento es SETFONT , el tercer argumento puede ser el nombre de la fuente como "Arial";

int request no 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 en el dispositivo se debe jugar. La aplicación envía el código de solicitud usando ioctl y luego usa 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 SETFONT para configurar 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 similares a funciones predefinidas.

1._IO(MAGIC, SEQ_NO) ambos son de 8 bits, de 0 a 255, p. digamos que queremos pausar la impresora. Esto no requiere una transferencia de datos. Entonces generaríamos el código de solicitud como se muestra a continuación

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

y ahora usa 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, y TYPE da el tipo del siguiente argumento, recuerda el tercer argumento de ioctl es void * . W en __IOW indica 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,

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

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

¡Avísame si esto te ayuda!


Un ioctl , que significa "control de entrada-salida" es una especie 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. Entonces, un controlador puede definir un ioctl que permite que una aplicación de espacio de usuario le envíe órdenes. Sin embargo, los ioctls no son muy flexibles y tienden a abarrotarse un poco (docenas de "números mágicos" que simplemente funcionan... o no), y también pueden ser inseguros, ya que pasa un búfer al núcleo:un mal manejo puede romper cosas fácilmente.

Una alternativa es el sysfs interfaz, donde configura un archivo bajo /sys/ y lea/escriba eso 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 intensivo es netlink, que es un método IPC (comunicación entre procesos) para comunicarse con su controlador a través de una interfaz de socket BSD. Esto es utilizado, por ejemplo, por los controladores WiFi. Luego te comunicas con él desde el espacio de usuario usando el libnl o libnl3 bibliotecas.


Linux
  1. Linux:¿Cómo encontrar el controlador de dispositivo utilizado para un dispositivo?

  2. Linux:¿Sysfs y Devtmpfs?

  3. Linux:¿cómo sabe el kernel de Linux los números mayores y menores de los dispositivos?

  4. ¿Controlador Huawei Linux en Ubuntu 13.04?

  5. Cómo crear un dispositivo de bloque virtual (dispositivo de bucle/sistema de archivos) en Linux

Cómo instalar un controlador de dispositivo en Linux

Todo es archivo en Linux – Parte 1

Linux:¿cómo encontrar el controlador (módulo) asociado con un dispositivo en Linux?

¿Por qué se necesita el método de sondeo en los controladores de dispositivos de Linux además de init?

¿Cuál es la diferencia entre un controlador de plataforma Linux y un controlador de dispositivo normal?

¿Cómo montar un dispositivo en Linux?