¿Qué es el desarrollo de controladores para la plataforma Linux?
Antes de aprender, no estaba muy familiarizado con el desarrollo de controladores y me sentía un poco misterioso. No sé cuál es la diferencia entre el desarrollo de controladores y el desarrollo de programas ordinarios; cuál es su marco básico; qué tiene de especial su entorno de desarrollo y cómo compilar y cargar un controlador de dispositivo de caracteres simple antes de escribirlo; Presentemos estos problemas uno por uno.
1. Marco básico del controlador
1. Entonces, ¿qué es exactamente un controlador y para qué sirve?
l Un controlador es una capa de software intermedia entre un dispositivo de hardware y una aplicación.
l Permite que un hardware específico responda a una interfaz de programación interna bien definida mientras se ocultan por completo los detalles de funcionamiento del dispositivo
l El usuario completa la operación correspondiente a través de un conjunto de llamadas estandarizadas que son independientes del dispositivo específico
l La tarea del controlador es asignar estas llamadas al sistema estandarizadas a operaciones específicas de dispositivos específicos en hardware real
l El controlador es parte del kernel y puede usar interrupciones, DMA y otras operaciones
l El controlador transfiere datos entre el modo de usuario y el modo kernel
2. Marco básico del controlador de Linux
3. Los controladores de dispositivos en Linux generalmente se pueden dividir en las siguientes tres categorías
1) Dispositivos de caracteres
a) Todos los dispositivos a los que se puede acceder como flujos de bytes se implementan a través de dispositivos de caracteres
b) Se asignan a nodos en el sistema de archivos, generalmente en el directorio /dev/
c) Generalmente incluyen la implementación de llamadas al sistema como abrir, leer, escribir y cerrar
2) Dispositivo de bloque
d) Generalmente se refiere a un dispositivo de almacenamiento como disco, memoria, Flash, etc. que puede acomodar un sistema de archivos.
e) También se accede a los dispositivos de bloque a través del sistema de archivos. La diferencia con los dispositivos de caracteres es que la forma en que el kernel administra los datos es diferente.
f) Permite que se realicen flujos de bytes. accedido como dispositivos de caracteres, también puede pasar cualquier número de bytes a la vez.
3) Dispositivo de interfaz de red
g) Generalmente se refiere a un dispositivo de hardware, pero a veces puede ser un dispositivo de software (como una interfaz loopback). Están controlados por. El subsistema de red en el kernel. Controlador del sistema, responsable de enviar y recibir paquetes de datos.
h) Su transferencia de datos a menudo no está orientada a flujos, por lo que es difícil asignarlos a un nodo del sistema de archivos.
2. Cómo construir un entorno de desarrollo de controladores
Debido a que el controlador debe compilarse en el kernel, el dispositivo de hardware se ejecutará cuando se inicie o se compile el kernel; un archivo .o. Cuando la aplicación lo necesita, se carga dinámicamente en el espacio del kernel y se ejecuta. Por lo tanto, la compilación de cualquier controlador debe estar vinculada al árbol de fuentes del kernel.
Entonces, el primer paso para construir un entorno es, por supuesto, construir un árbol de fuentes del kernel
1 Cómo construir un árbol de fuentes del kernel
a) Primero verifique si su sistema tiene una fuente. tree.En su/Habrá información del kernel en el directorio lib/modules. Por ejemplo, hay dos versiones en mi sistema actual:
#ls /lib/modules
2.6. .15-rc7 2.6.21- 1.3194.fc7
Ver la ubicación de su código fuente:
## ll /lib/modules/2.6.15-rc7/build
lrwxrwxrwx 1 raíz raíz 27 2008 -04-28 19:19 /lib/modules/2.6.15-rc7/build -gt /root/xkli/linux-2.6.15-rc7
Se descubrió que la compilación es un archivo de enlace. El directorio correspondiente es el directorio del árbol fuente. Pero ahora el directorio de destino no es válido. Así que tienes que volver a descargarlo tú mismo
b) Descarga y compila el árbol fuente
Hay muchos sitios web donde puedes descargarlo, pero el sitio web oficial es:
http://www .kernel.org/pub/linux/kernel/v2.6/
Después de descargar, por supuesto, descomprime y compila
# tar – xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (Configura las opciones del kernel. Si no hay configuración, no puedes compilar en el siguiente paso. No es necesario cambiar nada aquí)
#make
Si no hay errores en la compilación. Así que felicidades.
Su entorno de desarrollo ha sido configurado
3. Comprenda los conocimientos básicos del controlador
1. Número de dispositivo
1) ¿Cuál es el número de dispositivo? Ingresemos al sistema y expliquemos en base al equipo existente:
#ls -l /dev/
crwxrwxrwx 1 root root 1, 3 2009-05-11 16:36 null
crw------- 1 raíz raíz 4, 0 2009-05-11 16:35 systty
crw-rw-rw- 1 raíz tty 5, 0 2009- 05-11 16:36 tty
crw-rw---- 1 root tty 4, 0 2009-05-11 16:35 tty0
Los dos caracteres delante del fecha El número (por ejemplo, la primera columna es 1, 3) representa el número del dispositivo. El primero es el número del dispositivo principal y el segundo es el número del dispositivo esclavo.
2) ¿Qué es? el uso del número de dispositivo?
l Tradicionalmente, el número principal identifica el controlador al que está conectado el dispositivo. Por ejemplo, /dev/null y /dev/zero son administrados por el controlador 1, mientras que la consola virtual y el terminal serie lo son. ambos administrados por el controlador 4
El núcleo utiliza el número l para decidir a qué dispositivo hacer referencia. Difiere según cómo esté escrito el controlador
3) Tipo de estructura del número de dispositivo y. método de aplicación
l En el kernel, el tipo dev_t (definido en) se usa para contener el número de dispositivo. Para el kernel 2.6.0, dev_t es una cantidad de 32 bits, se usan 12 bits como. número mayor y 20 bits se utilizan como número menor.
Puedo obtener el método de numeración mayor o menor de un dev_t:
MAJOR(dev_t dev); /p>
MINOR(dev_t dev); //Minor
l Pero si tiene un número mayor y menor, necesita convertirlo a dev_t, use: MKDEV (int major, int minor);
4) Cómo asignar y liberar en el programa el número de dispositivo
Lo primero que debe hacer al crear un controlador de caracteres es obtener uno o más números de dispositivo para uso Hay dos funciones que pueden lograr esta función:
l Una es que conozca el número de dispositivo de antemano
register_chrdev_region, declarado en:
int. Register_chrdev_region(dev_t first, unsigned int count, char *name);
first es el número de dispositivo inicial que desea asignar. La parte menor de first es siempre 0 y count es el número total de dispositivos consecutivos. Los números que solicitó son el nombre del dispositivo que debe conectarse a este rango de números; aparecerá en /proc/devices y sysfs.
l El segundo es asignar dinámicamente números de dispositivos p>
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char * name);
Con esta función, dev es un parámetro de solo salida que contiene el primer número de su rango de asignación cuando la función se completa exitosamente.
minor debe ser el primer número menor utilizado en la solicitud; generalmente es 0. Los parámetros de recuento y nombre son los mismos que para request_chrdev_region.
5) Liberar el uso de números de dispositivo
No importa cómo asigne el número de dispositivo.
Debe liberarse después de su uso, de la siguiente manera:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2. estructuras de datos importantes
1) operación_archivo
Por ejemplo, la definición general del dispositivo de caracteres scull es la siguiente:
estructura operaciones_archivo scull_fops = {
.owner = ESTE_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
}; llamada La interfaz del controlador del dispositivo
se define en , que es una colección de punteros de función. Cada archivo abierto (representado internamente por una estructura de archivos) está asociado con su propio conjunto de funciones (al incluir un miembro, que. apunta a una estructura file_operations). La mayoría de estas operaciones son responsables de implementar llamadas al sistema, por lo que se denominan abrir, leer, etc.
2) Archivo
La definición se encuentra en include/fs .h
Miembros de la estructura del archivo struct relacionado con el controlador
l mode_t f_mode identifica los permisos de lectura y escritura del archivo
l loff_t f_pos posición actual de lectura y escritura
l indicador de archivo int_f_flag sin firmar, verificado principalmente durante operaciones de bloqueo/no bloqueo
l struct file_operation * f_op puntero de estructura de la operación de archivo
l void * private_data driver Generalmente, apunta a los datos asignados
l struct dentry* La estructura de entrada del directorio correspondiente al archivo f_dentry
Registro del dispositivo de caracteres
1) El kernel es interno. Utilice estructuras de tipo struct cdev para representar dispositivos de caracteres. Antes de que el kernel pueda llamar a las operaciones de su dispositivo, debe escribir para asignar y registrar una o más de estas estructuras. e inicialice una de estas estructuras.
l Si desea obtener una estructura cdev independiente en tiempo de ejecución, puede usarla así:
struct cdev *my_cdev = cdev_alloc();
my_cdev-gt; ops = amp; my_fops;
l Si desea incrustar la estructura cdev en una estructura propia específica del dispositivo, debe inicializar la estructura que tiene; asignado, usando:
void cdev_init(struct cdev *cde
v, struct file_operations *fops);
2) Una vez establecida la estructura cdev, el paso final es informar al kernel sobre ella, llamando a:
int cdev_add(struct cdev * dev, dev_t num , unsigned int count);
Explicación: dev es la estructura cdev, num es el primer número de dispositivo respondido por este dispositivo y count es el número de números de dispositivo que deben asociarse con el dispositivo. Por lo general, el recuento es 1, pero hay varios números de dispositivo correspondientes a un dispositivo específico.
3) Para eliminar un dispositivo de caracteres del sistema, llame a:
void cdev_del(struct). cdev *dev);
4. abrir y soltar