Story Transcript
10/12/13
Mecanismos de extensión del núcleo Yolanda Becerra Fontal Juan José Costa Prats Facultat d'Informàtica de Barcelona Universitat Politècnica de Catalunya BarcelonaTech 2013-2014QT
SO2/SOA
Índice • Concepto • Mecanismos – Está5cos – Dinámicos
• Módulos de Linux – Funcionalidad básica – Operaciones disponibles – Ejemplo de uso: Driver de disposi5vo SO2/SOA
1
10/12/13
Qué se en5ende por extender el núcleo? • Añadir nuevas funcionalidades o caracterís5cas a un sistema opera5vo – Cambiar polí5ca planificación – Arreglar un error de seguridad – Añadir soporte para nueva tarjeta de red
• Añadir código (ru5nas) y datos (estructuras y variables) • Básicamente hay 2 mecanismos – Está5cos – Dinámicos SO2/SOA
Mecanismos • Está5cos
– En 5empo de compilación – Necesitamos acceso al código fuente – Añadir el nuevo código y los datos – Y generar nueva imagen del sistema opera5vo
• Dinámicos
– En 5empo de ejecución – En algunos casos sin la necesidad de reiniciar la máquina – Nuevo código y datos encapsulados en algun formato binario que permita su inserción dinámica – No todos los sistemas lo permiten
SO2/SOA
2
10/12/13
Linux modules • Linux permite inserción dinámica de código y datos a traves de los módulos – La alterna5va es recompilar el sistema
• Los módulos 5enen las mismas limitaciones que cualquier otro desarrollo dentro del sistema: – Solo se pueden acceder/modificar los símbolos públicos del kernel (aquellos que han estado exportados explícitament) – No hay acceso a la libreria de C – Herramientas de depuración limitadas (p.ej: chivatos con printk)
• Finalmente obtenemos un fichero binario (kernel object) que podemos insertar / quitar dinámicamente SO2/SOA
Operaciones sobre módulos • Instalar un módulo – # insmod mymodule.ko [param=value][, param=value] *
• Quitar un módulo – # rmmod mymodule.ko
• Instalar un módulo resolviendo dependencias – # modprobe moduloA.ko – # cat /lib/modules/version/modules.dep /path_completo/moduloA.ko: /path_completo/moduloB.ko /path_completo/moduloB.ko: SO2/SOA
3
10/12/13
Operaciones sobre módulos • Listar modulos instalados en el sistema – # lsmod – # cat /proc/modules
• Listar información sobre un modulo – # modinfo module.ko
SO2/SOA
Desarrollo de un módulo de Linux • Programar los ficheros para implementar el módulo – Funciones de inicialización y finalización • Se invocan al instalar/desinstalar un módulo
– Código/datos a incluir en el sistema – Exportar variables/funciones que vayan a ser usadas fuera del módulo • EXPORT_SYMBOL( f ) → “ksyms -‐a” o “cat /proc/kallsyms”
– Puede usar cualquier variable/función exportada por el kernel u otros módulos
• Compilar los ficheros
– Es necesario disponer de los fuentes del sistema – Produce un fichero objeto (.ko = kernel object)
• Insertarlo en el sistema
– Cargar el módulo y sus dependencias – Pasar parametros de inicialización
• Usar el módulo SO2/SOA
4
10/12/13
Desarrollo de un módulo de Linux • Desde el módulo podeis acceder a muchas funciones para la ges5ón de estructuras de datos: – find_task_by_pid – for_each_process – … – Antes de implementar algo, mirad que no exista!
• Desde el módulo accedeis al espacio de direcciones de usuario: unsigned long copy_from_user(void *to, const void *from, unsigned long count); unsigned long copy_to_user(void *to, const void *from, unsigned long count
SO2/SOA
Ejemplo de un módulo #include #include /* * Module ini5aliza5on. */ sta0c int __init Mymodule_init(void) { . . . } /* * Finaliza5on module. */ sta0c void __exit Mymodule_exit(void) { . . . } module_init(Mymodule_init); module_exit(Mymodule_exit);
SO2/SOA
5
10/12/13
Macros varias para módulos • module_param (parameter name and type) – int pid=1; – module_param (pid, int, 0);
• MODULE_PARM_DESC (parameter descrip5on)
– MODULE_PARM_DESC (pid, "Process ID to monitor (default 1)");
• MODULE_AUTHOR (author list) • MODULE_DESCRIPTION • MODULE_LICENSE (GPL, BSD, …)
• Información visible con 'modinfo' SO2/SOA
Contador de referencias • Un módulo puede descargarse, sí y solo sí, ningún proceso lo esta usando – Hay un contador de referencias, para quan5ficar el uso del módulo • Pero la ges5ón la 5ene que hacer el programador del módulo :(
• try_module_get( THIS_MODULE ) – Incrementa contador: Alguien esta usando el módulo.
• module_put( THIS_MODULE ) – Decrementa contador: Alguien ha dejado de usar el módulo
• Hay que programar esta ges5ón en todas las ru5nas públicas SO2/SOA
6
10/12/13
Device Driver • Los módulos son usados |picamente para cargar drivers de disposi5vos
SO2/SOA
Device Driver • El driver es un conjunto de variables y funciones para manejar un disposi5vo (logico o }sico) • U5liza una API estandar – Interna (no visible para el usuario) – Basado en el struct file_opera5ons
• Solo hay que proporcionar las funciones requeridas por el disposi5vo (p.ej: open, read) SO2/SOA
7
10/12/13
Operaciones del disposi5vo Tabla Canales
read(fd)
fd
Tabla Ficheros Abiertos
Caract. dinámicas
Tabla Inodos
Caract. Está5cas (DD)
DRIVER file_opera5ons open read write close
Open(..){ } Read(…){ } Write(…){ }
SO2/SOA
Iden5ficación del disposi5vo • Iden5ficados por un major y un minor – Simples números
• dev_t MKDEV (major, minor)
– Históricamente, el major iden5ficaba la clase de disposi5vo (p.ej: una impresora) y el minor diferentes disposi5vos dentro de la misma clase (p.ej: modelos diferentes de la misma impresora)
• Este iden5ficador permite al kernel saber que driver 5ene que usar para comunicarse con el disposi5vo • Hay un fichero visible para el usuario con ese major y minor
SO2/SOA
8
10/12/13
Registro de device drivers • Los device drivers se 5enen que registrar en el sistema asociándole su iden5ficador int register_chrdev_region (dev_t first, unsigned int count, const char *name);
• Y para eliminar su registro: void unregister_chrdev_region (dev_t first, unsigned int count);
• El interfaz depende del 5po de disposi5vo SO2/SOA
Asignar operaciones a disposi5vos • Primero, crear una estructura cdev: struct cdev * cdev_alloc()
• Segundo, inicializar sus campos: – owner: con THIS_MODULE • Para que el kernel se encargue de la ges5on de los contadores
– ops: con la estructura file_opera4ons del disposi5vo
• Finalmente, asignar la estructura al disposi5vo/s: int cdev_add (struct cdev *dev, dev_t num, unsigned int count);
• Para borrarlo: void cdev_del (struct cdev *dev); SO2/SOA
9
10/12/13
Operaciones del disposi5vo • La estructura file_opera5ons esta en • struct file_opera5ons my_opera5ons = { owner: THIS_MODULE, read: my_read, ioctl: my_ioctl, open: my_open, release: my_release, }; • El campo owner automa5za ges5ón contadores SO2/SOA
Device Driver's API • Cuando usuario hace open/close sobre disposi5vo: – int my_open (struct inode * i, struct file * f); – int my_release (struct inode * i, struct file * f);
• ssize t my_read (struct file * f, char * buffer, size t_size, loff_t * offset); – Es necesario usar copy_to_user para acceder al buffer – offset es un parám. de entrada/salida. Posición actual en “file”
• int my_ioctl(struct inode * i, struct file * f, unsigned int request, unsigned long argp); – Usado para controlar las operaciones dentro del disposi5vo SO2/SOA
10
10/12/13
Insertar un device driver con un modulo Variable de 5po dev_t con el major i minor del disp. Funciones del disposi5vo Variable de 5po struct file_opera5ons inicializada Variable de 5po cdev para ligar las operaciones y el disposi5vo • Al inicializar el módulo: • • • •
– Registrar el disposi5vo dentro del kernel y asociar las operaciones
• Al finalizar el módulo: – Eliminar el registro y borrar el cdev SO2/SOA
Como puede el usuario usar un nuevo disposi5vo? • Administrador crea el disposi5vo con el comando 'mknod', usando el iden5ficador del disposi5vo: – mknod – p.ej: mknod mydevice c 255 1 • Crea un fichero 'mydevice' que usará el driver de caracteres iden5ficado con el major 255 y minor 1
• Ahora el usuario puede acceder a este fichero con el API de entrada/salida estandar SO2/SOA
11