Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porRicardo Blanco Fuentes Modificado hace 8 años
1
Programación de controladores para Linux Julio Bianco Edgardo Hames Faculta de Matemática, Astronomía Y Física Universidad Nacional de Córdoba
2
Lo que vamos a ver... Introducción Utilidades Compilación del kernel La construcción de módulos Interfaz de programación Espacio de usuario vs. Espacio de Núcleo Sincronización de procesos Entrada y salida síncrona
3
Introducción Linus Torvalds + Grupo de gente en Internet Con todas las características de un SO moderno Multitarea Memoria virtual Bibliotecas compartidas Carga en demanda Correcta administración de memoria Soporte para red IPV4 e IPV6 Independencia del hardware
4
Introducción Dispositivo Controlador
5
Introducción Controlador Imprimi! Hace lo tuyo! Mapea las llamadas a las operacionesespecíficas del Hardware Llamadas al sistema
6
Introducción Nucleo Controlador Enlazados en tiempo de ejecución
7
Utilidades depmode: crea dependencia intermodular basado en símbolos -a busca módulos en directorios especificados en /etc/modules.conf -e muestra los símbolos no resueltos de cada módulo -n escribe el archivo de dependencias en stdout. modinfo: muestra información sobre un módulo -a muestra el autor del módulo -d muestra la descripción del módulo -l muestra la licencia del módulo -p muestra los parámetros del módulo -n muestra el path completo del archivo que corresponde al módulo
8
Utilidades lsmod: Muestra la lista de módulos cargados (cat /proc/modules) insmod: Instala un módulo en el núcleo en ejecución -f carga el módulo aunque pertenezca a otra versión del kernel -p prueba si el módulo puede ser cargado rmmod: Desinstala un módulo del núcleo en ejecución modprobe: Instala o desinstala un módulo del kernel en ejecución -r descarga un módulo y todos los que lo refernecian dmesg: Permite examinar los mensajes del kernel
9
Compilación del kernel 1. Descomprimir el archivo con el código fuente # tar -xjf linux-2.6.20.tar.bz2 2.Moverse al directorio donde se descomprimió el archivo # cd linux-2.6.20 3.Configurar el núcleo # make config (Modo interactivo) # make menuconfig (Menú modo texto) # make xconfig (Menú modo gráfico) 4.Generar las dependencias, compila la imagen del kernel, los módulos #make
10
Compilación del kernel 5. Instalar los módulos en la carpeta /lib/modules/ #make modules_install 6. Copiar el kernel a /boot #cp arch/i386/boot/bzImage /boot 7. Configurar el cargador de arranque. Depende del arrancador usado 8. Realizar el equipo y rezar para que todo ande
11
La construcción de módulos La programación será para el kernel de linux versión 2.6 Se requiere tener fuentes de un núcleo configurado y construido en el sistema Un módulo agrega funcionalidad al sistema, la cual puede corresponder al controlador de un dispositivo o no.
12
Module_exit Señala el punto de salida de módulos del núcleo Module_init Señala el punto de entrada de módulos del núcleo Primer módulo Función de inicialización static int (void) punto de entrada de modulos del núcleo Función de finalización static void (void) punto de salida de modulos del núcleo
13
Dispositivos físicos y lógicos [usuario@localhost]$ ls -l /dev/hda /dev/urandom brw------- 1 root root 3, 0 2007-09-26 08:45 /dev/hda crw-r--r-- 1 root root 1, 9 2007-09-26 08:45 /dev/urandom Tipo de dispositivo Major number Minor number 1 charMemory devices 1 = /dev/memPhysical memory access 3 = /dev/nullNull device 4 = /dev/portI/O port access 5 = /dev/zeroNull byte source 9 = /dev/urandomFaster, less secure random number gen. 3 blockFirst MFM, RLL and IDE hard disk/CD-ROM interface 0 = /dev/hdaMaster: whole disk (or CD-ROM) 64 = /dev/hdbSlave: whole disk (or CD-ROM) For partitions, add to the whole disk device number: 0 = /dev/hd?Whole disk 1 = /dev/hd?1First partition 2 = /dev/hd?2Second partition Parte de la lista de dispositivos: /usr/src/linux/ Documentation/ devices.txt
14
Creación de un dispositivo [usuario@localhost]$ mknod -m 0666 /dev/nombre c M m -m Modo de acceso c/b Tipo de dispositivo M Major number m Minor number
15
Interfaz de programación int register chrdev(unsigned int major, const char *name, struct file operations *fops) int unregister chrdev(unsigned int major, const char *name) int open(struct inode *ip, struct file *fp) int release(struct inode *ip, struct file *fp) ssize t read(struct file *fp, char *buf, size t length, loff t *offset) ssize t write(struct file *fp, const char *buf, size t length, loff t *offset) Registro de un dispositivo de caracteres Desregistro de un dispositivo de caracteres Apertura de un dispositivo (no obligatoria) Se invoca cada vez que se libera el dispositivo, no necesariamente con cada close (no obligatoria) Lectura de datos del dispositivo.CUIDADO: buf es un puntero a memoria en espacio usuario Envío de datos al dispositivo.CUIDADO: buf es un puntero a memoria en espacio usuario
16
Nulo: main.c #include #define DEBUG #include "debug.h" #include "nuloops.h" MODULE_AUTHOR("Edgardo Hames - Julio Bianco"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Controlador para dispositivo alternativo /dev/nulo"); static const int MAJOR = 253; static const char *NAME = "nulo-0.3";
17
Nulo: main.c int nulo_init(void) { int error = 0; error = register_chrdev(MAJOR, NAME, &nulo_fops); if (error == 0) { dprintk("%s : Carga completada satisfactoriamente.\n", NAME); } else { dprintk("%s: No se pudo registrar el dispositivo '%s' con" " major: %d.\n", NAME, NAME, MAJOR); error = -1; } return error; } void nulo_exit(void) { int error = 0; error = unregister_chrdev(MAJOR, NAME); if (error == 0) { dprintk("%s: Descarga completada satisfactoriamente.\n", NAME); } else { dprintk("%s: No se pudo desregistrar el dispositivo '%s' con" " major: %d\n", NAME, NAME, MAJOR); } module_init(nulo_init); module_exit(nulo_exit);
18
Nulo: nuloops.h #ifndef NULOOPS_H #define NULOOPS_H extern struct file_operations nulo_fops; #endif /* NULOOPS_H */
19
Nulo: nuloops.c #include #define DEBUG #include "debug.h" #include "nuloops.h" static int nulo_open(struct inode *ip, struct file *fp) { return 0; } static ssize_t nulo_read(struct file *fp, char *buf, size_t count, loff_t *offset) { dprintk("nulo: read %zd.\n", count); return 0; }
20
Nulo: nuloops.c static ssize_t nulo_write(struct file *fp, const char *buf, size_t count, loff_t *offset) { /* * Siempre se puede escribir en /dev/nulo y nunca nos quedaremos sin espacio. */ dprintk("nulo: write %zd.\n", count); return count; } static int nulo_release(struct inode *ip, struct file *fp) { return 0; } /* * La estructura que contiene punteros a cada una de las operaciones que se * pueden realizar sobre /dev/nulo. Esta es la única variable que exporta el * módulo. Así, podremos cambiar hasta los nombres de las funciones que * implementan cada operación y se preservará la abstracción. */ struct file_operations nulo_fops = {.owner=THIS_MODULE,.open=nulo_open,.read=nulo_read,.write=nulo_write,.release=nulo_release };
21
Kernel space vs. user space Las direcciones de memoria del n´cleo est´n protegidas del alcance de los programas en espacio usuario. Por lo tanto, para leer y escribir datos desde estos programas es necesario usar un par de macros que hacen esta tarea posible. unsigned long copy from user(void *to, const void *from, unsigned long count) Esta función se comporta como memcpy y copia memoria de espacio usuario (from) a espacio núcleo (to) count bytes. unsigned long copy to user(void *to, const void *from, unsigned long count) Esta función se comporta como memcpy y copia memoria de espacio núcleo (from) a espacio usuario (to) count bytes.
22
Sincronización de procesos void sema init(struct semaphore *sem, int val) Inicializa el semáforo sem con el valor val. int down interruptible(struct semaphore *sem) Realiza la operación P sobre el semáforo sem y permite que éste reciba señales en el transcurso de la llamada. if (down_interruptible(&s)) { return -ERESTARTSYS; } void up(struct semaphore *sem) Realiza la operación V sobre el semáforo sem.
23
Entrada y salida síncrona Cuando un proceso deba esperar que ocurra un evento, lo ponemos a dormir, suspendiendo su ejecución y liberando el procesador. Cuando el evento ocurre, el kernel despertará al proceso para continuar. Hay varias formas de suspender procesos y todas usan colas de espera. Declaradas estaticamente : wait_queue_head_t cola; init_waitqueue_head(&cola); Declaradas dinámicamente: DECLARE_WAIT_QUEUE_HEAD(cola);
24
Como dormir procesos sleep on(wait queue head t *queue) Pone a dormir el proceso en forma ininterrumpible. Por lo tanto, el proceso no podrá recibir señales y puede quedar bloqueado si el evento que espera nunca ocurre. interruptible sleep on(wait queue head t *queue) Pone a dormir el proceso y permite que reciba señales. wait event(wait queue head t queue, boolean condicion) Hace que espere por el cumplimiento de una condición booleana int wait event interruptible(wait queue head t queue, boolean condicion) El argumento queue es la cola donde dormirá el proceso hasta que se cumpla condicion.
25
Como despertar procesos wake up(wait queue head t *queue) Despierta a todos los procesos que duermen en la cola queue. Causa una inmediata replanificación del CPU y por lo tanto un nuevo proceso puede ejecutarse antes de que retorne. wake up interruptible(wait queue head t *queue) Despierta a todos los procesos que duermen en la cola queue y que están en estado interrumpible. Causa una inmediata replanificación del CPU y por lo tanto un nuevo proceso puede ejecutarse antes de que retorne. wake up interruptible sync(wait queue head t *queue) Despierta a todos los procesos que duermen en la cola queue y que están en estado interrumpible. Si un proceso espera por una condición en un ciclo, no será despertado. Modifica el estado de los procesos suspendidos, pero no replanifica elCPU.
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.