Linux block device driver

  

block device es un concepto de yuxtaposición con dispositivos de caracteres. La estructura de estos dos tipos de dispositivos es muy diferente en Linux. En general, los controladores de dispositivos de bloques son mucho más complicados que los controladores de dispositivos de caracteres. Las operaciones de E /S muestran grandes diferencias, y el búfer, la programación de E /S, las colas de solicitud, etc. son conceptos relacionados con los controladores de dispositivos de bloque. Este capítulo le mostrará cómo programar controladores de dispositivo de bloqueo de Linux. La sección 13.1 analiza las características de las operaciones de E /S del dispositivo de bloque y compara las diferencias en las operaciones de E /S entre los dispositivos de caracteres y los dispositivos de bloque. La sección 13.2 describe la estructura del controlador de dispositivo de bloque de Linux en su conjunto y analiza las principales estructuras de datos, funciones y relaciones. Las secciones 13.3 a 13.5 ilustran la carga y descarga, la apertura y la liberación del módulo del controlador del dispositivo de bloque y las funciones ioctl (), respectivamente. La sección 13.6 es muy importante. Describe el concepto y el uso de las colas de solicitud de las que dependen las operaciones de E /S del dispositivo de bloque. Las secciones 13.2 y 13.3 a 13.6 son la relación entre el conjunto y la parte, mientras que las secciones 13.2 a 13.6 y 13.7 son relaciones progresivas iterativas. Sobre la base de los contenidos explicados en las Secciones 13.1 a 13.6, la Sección 13.7 resume el proceso de lectura y escritura del dispositivo Linux. La sección 13.7 da un ejemplo concreto de un controlador de dispositivo de bloque, el controlador RAMDISK. 13.1 Características de operación de E /S de los dispositivos de bloque La diferencia entre los dispositivos de caracteres y las operaciones de E /S del dispositivo de bloque es que un dispositivo de bloque puede aceptar la entrada y la salida de retorno solo en unidades de bloque, mientras que los dispositivos de caracteres están en bytes. La mayoría de los dispositivos son dispositivos de caracteres porque no requieren almacenamiento en búfer y no funcionan a un tamaño de bloque fijo. Los 2 bloques tienen buffers correspondientes para las solicitudes de E /S, por lo que pueden elegir el orden de respuesta. Los dispositivos de caracteres no necesitan ser almacenados en búfer, leer y escribir directamente. El orden de ajuste de lectura y escritura es excelente para los dispositivos de almacenamiento porque es más rápido para leer y escribir sectores consecutivos que los sectores separados. Los dispositivos de 3 caracteres solo se pueden leer y escribir de forma secuencial, y los dispositivos de bloque se pueden acceder de forma aleatoria. Si bien los dispositivos de bloque son accesibles al azar, para dispositivos mecánicos como los discos, la organización secuencial del acceso a los dispositivos de bloqueo puede mejorar el rendimiento. Como se muestra en la Figura 13.1, las solicitudes de los discos 1, 10, 3, 2 se ajustan a las solicitudes de 1, 2, 3, 10 para mejorar el rendimiento de lectura y escritura. Tenga en cuenta que para los dispositivos de bloque, como las tarjetas SD y RAMDISK, no hay ninguna razón mecánica y no es necesario realizar dichos ajustes. Figura 13.1 Ajuste del orden de las operaciones de E /S del dispositivo de bloque 13.2 Estructura de controlador de dispositivo de bloque de Linux 13.2.1 Estructura block_device_operations En el controlador de dispositivo de bloque, hay una estructura block_device_operations similar a la estructura file_operations en el controlador de dispositivo de caracteres, que es un bloque. Una colección de operaciones del dispositivo, como se define en el Listado 13.1. Listado 13.1 block_device_operations structure 1 struct block_device_operations2 {3 int (* open) (struct inode *, struct file *); //Open 4 int (* release) (struct inode *, struct file *); //release 5 int (* ioctl) (struct inode *, struct file *, unsigned, unsigned long); //ioctl6 long (* unlocked_ioctl) (struct file, unsigned, unsigned long); 7 long (* compat_ioctl) (struct file *, unsigned , sin signo largo); 8 int (* direct_access) (struct block_device *, sector_t, unsigned long *); 9 int (* media_changed) (struct gendisk *); //¿Se cambió el medio? 10 int (* revalidate_disk) (struct gendisk *); //Hacer que el medio sea válido 11 int (* getgeo) (struct block_device *, struct hd_geometry *); //completar la información de la unidad 12 struct module * owner; //módulo propietario 13 }; El siguiente análisis de sus funciones miembro principales:? Abrir y liberar int (* abrir) (struct inode * inode, struct file * filp); int (* release) (struct inode * inode, struct file * filp) Al igual que los controladores de dispositivo de caracteres, se llaman cuando el dispositivo se enciende y se apaga. IO control int (* ioctl) (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg); la función anterior es una implementación de la llamada al sistema ioctl (), el dispositivo de bloque contiene un gran número de solicitudes estándar, estas solicitudes estándar Es manejado por la capa de dispositivo de bloque de Linux, por lo que la mayoría de las funciones ioctl () controladas por dispositivo de bloque son bastante cortas. • El kernel llama al cambio de medio int (* media_changed) (struct gendisk * gd) para verificar si el medio en la unidad ha cambiado, y si es así, devuelve un valor distinto de cero, de lo contrario devuelve 0. Esta función solo está disponible para unidades que admiten medios extraíbles (los dispositivos que no son móviles no necesitan implementar este método) y, por lo general, requieren una variable de marca para indicar si el estado de los medios ha cambiado. • Haga que el medio sea válido int (* revalidate_disk) (struct gendisk * gd); se llama a la función revalidate_disk () para responder a un cambio de medio, lo que le da al conductor la oportunidad de hacer el trabajo necesario para preparar el nuevo medio. Obtenga la información de la unidad int (* getgeo) (struct block_device *, struct hd_geometry *); esta función llena una estructura hd_geometry basada en la geometría de la unidad. La estructura hd_geometry contiene información como cabezas, sectores y cilindros. • El puntero del módulo struct module * owner: un puntero al módulo que posee la estructura, que generalmente se inicializa en THIS_MODULE. 13.2.2 estructura de gendisk En el kernel de Linux, se utiliza una estructura de gendisk (disco general) para representar un dispositivo de disco (o partición) separado. La definición de esta estructura se muestra en el Listado 13.2. Listado 13.2 gendisk estructura 1 struct gendisk2 {3 int major; /* número de dispositivo principal * /4 int first_minor; /* primer número de sub-dispositivo * /5 int menores; /* número máximo de sub-dispositivos, si no están divididos , es 1 * /6 char disk_name [32]; /* nombre de dispositivo * /7 struct hd_struct ** parte; /* información de partición en el disco * /8 struct block_device_operations * fops; /* estructura de operación del dispositivo de bloque * /9 struct request_queue * queue; /* request queue * /10 void * private_data; /* datos privados * /11 sector_t capacidad; /* número de sector, 512 bytes para 1 sector * /12 13 banderas int; 14 caracteres Devfs_name [64]; 15 int número; 16 struct device * driverfs_dev; 17 struct kobject kobj; 18 19 struct timer_rand_state * random; 20 int policy; 21 22 atomic_t sync_io; /* RAID * /23 sello largo sin signo; 24 int in_flight; 25 #ifdef CONFIG_SMP26 struct disk_stats * dkstats; 27 # else28 struct disk_stats dkstats; 29 # endif30}; major, first_minor y menores juntos representan los números de dispositivo principal y secundario del disco, y cada partición principal del mismo disco comparte un número de dispositivo principal. El número de dispositivo menor es diferente. Fops es block_device_operations, el conjunto de operaciones de dispositivo de bloque descrito en la sección anterior. Una cola es un puntero que el kernel utiliza para administrar la cola de solicitud de E /S para este dispositivo. Capacidad indica la capacidad del dispositivo, en unidades de 512 bytes. Private_data se puede usar para apuntar a cualquier dato privado en el disco, similar a la información privada de la estructura de archivos del controlador del dispositivo de caracteres.

Copyright © Conocimiento de Windows All Rights Reserved