Linux Drivers 2010
Linux Drivers 2010
Linux Drivers 2010
Introducción
• ¿Qué es un Driver de acceso a dispositivo?
¾ Pieza de software, normalmente perteneciente al sistema,
para el acceso a dispositivos físicos.
Driver de
dispositivo
Driver de Programas de
dispositivo aplicación
Driver de
dispositivo
Introducción
Programas de usuario
Interfaz de llamadas al sistema (API, del sistema operativo)
• Drivers en Linux
¾Cuatro tipos de drivers
De carácter
De bloque
De red
pseudo-dispositivos
– Usb
– SCSI
– Fire-Wire
¾Normalmente implementados como módulos
Drivers en Linux
• Concurrencia
¾Múltiples versiones del código del driver
ejecutándose simultáneamente
Varios procesos acceden simultáneamente al recurso
Varias CPU que ejecutan simultáneamente el mismo driver
• El código debe ser reentrante
¾Correr en más de un contexto al mismo tiempo
¾Diseño de las estructuras de datos con cuidado
para evitar la corrupción
Drivers en Linux
• Módulos
¾Se cargan y descargan de forma dinámica
Para activar un dispositivo basta con cargar el módulo con el
driver (función insmod)
Para descargar el dirver basta con llamar a la función rmmod
¾El Kernel es capaz de descargar de la memoria un
modulo que no este usándose para liberar
recursos activándolo de forma automática cuando
lo precise.
Drivers en Linux
• Módulos
¾ Emplean únicamente funciones del sistema.
¾ Gran número de funciones y variables globales.
Todos los módulos se ejecutan en el mismo espacio del kernel.
Necesidad de ocultar los datos mediante la palabra static.
¾ Llamados desde el espacio del usuario.
Permite que un proceso ejecutado en modo usuario acceda a
recursos de modo supervisor
Tranferencia desde el espacio de usuario al del kernel mediante
llamadas al sistema e interrupciones.
¾ Ejecutados en el espacio del kernel (Modo
supervisor).
¾ Código ejecutado en forma continua. Es necesario
descargar el módulo de forma explicita (rmmod)
Estructura básica de un módulo
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
Programa de usuario
....
fid=fopen(“/dev/short0”,”rw”);
.....
Llamada al sistema
escrito=write(fid,”hola”,4);
Llamada al sistema
Inicializacion Salida
..... .....
Drivers de carácter, Operaciones asociadas al
driver
Posibles funciones (Un driver no tiene por qué implementarlas todas)
1) Posición actual del archivo
int (* lseek) (struct file *, loff_t, int);
2) Leer datos desde el dispositivo
int (* read) (struct file *, char *, size_t, loff_t;
3) Escribir datos en el dispositivo
int (* write) (struct file *, const char *, size_t, loff_t);
4) Apertura del dispositivo
int (* open) (struct inode *, struct file *);
5) Cierre del dispositivo
int (* release) (struct inode *, struct file *);
6) Determinar si el dispositivo es de r, w, rw
int (* select) (struct file *, int, select_table *);
7) Especificar comandos del driver
int (* ioctl) (struct inode *, struct file *, unsigned int, unsigned
long);
8) Peticiones de mapeo de memoria
int (* mmap) (struct file *, struct file *,struct vm_area_struct *);
9) Sincroniza el dispositivo
int (* fsync) (struct inode *, struct dentry *, int);
Drivers de carácter, estructura
file_operations
Identifica las funciones implementadas
Punteros a funcion
struct file_operations nombre_modulo_fops =
{nombre_modulo_lseek,
nombre_modulo_read,
nombre_modulo_write,
NULL, /* readdir */
NULL, /* select */
nombre_modulo_ioctl,
NULL, /* mmap */
nombre_modulo_open,
nombre_modulo_release,
NULL, /* fsync */
NULL, /* fasync */
NULL, /* check media change */
NULL, /* revalidate */
};
Drivers de carácter, estructura
file_operations
Inicialización resumida
Microprocesador
Periféricos Memoria
Intel x86
Espacio Espacio
• 000- 01F: Registros DMA1 (8237) • 1F0- 1F8: Controlador disco duro
• 020- 03F: Registro control INTR 1 • 200- 20F: Adaptador juegos
(8259) • 210- 277: No usado
• 040- 05F: Registro temporizador (8254) • 278- 27F: Puerto paralelo 3
• 060- 06F: Registro control TECLADO • 280- 2F7: No usado
(8042)
• 2F8- 2FF: Puerto serie 2
• 070- 07F: Reloj tiempo real
• 080- 08F: Registro página ADM
• 300- 31F: Placa prototipo USR
• 0A0- 0BF: Registro control INTR 2 • 360- 36F: Reservado
(8259) • 378- 37F: Puerto paralelo 2
• 0C0- 0DF: Registros DMA2 (8237)
• 0F0- 0FF: Registro Coprocesador
matemático
• Liberar la interrución
int free_irq(unsigned int irq,
, void *dev_id);
irq número de la interrupción solicitada
- manejador función encargada de gestión de la interrupción
- dev_id datos privados para entregar al manejador
• disable_irq(int irq);
• disable_irq_nosycn(int irq):
• enable_irq(int irq);
• void prepare_to_wait(wait_queue_head_t
*queue,wait_queue_t *wait,int State)
• Schedule();
• void finish_wait(wait_queue_head_t*
queue,wait_queue_t *wait)
tasklet_hi_schedule(&tlet);
/* tasklet_schedule(&tlet); */
/* tasklet_disable(&tlet) suspende la ejecución hasta se
habilita*/
/* tasklet_enable(&tlet) habilita la que esta suspendida */
Temporización. Workqueues