Download Práctica 2. Módulos del núcleo de Linux: acceso a recursos de

Document related concepts
no text concepts found
Transcript
Arquitectura y Tecnologı́a de Ordenadores Personales (IS37 - II37)
Ingenierı́a Técnica en Informática de Sistemas - Ingenierı́a Informática
Práctica 2. Módulos del núcleo de
Linux: acceso a recursos de
dispositivos.
1.
Objetivos
Con el desarrollo de esta práctica, además de continuar con el estudio de la estructura
de los módulos de Linux –versión 2.6.x del núcleo– se verá cómo acceder a los registros de
los dispostivos, mapeados en memoria o en entrada/salida del bus PCI.
2.
Introducción
El núcleo accede a los registros de los dispositivos mediante accesos al mapa de memoria
o de entrada/salida del sistema. Los drivers programados especı́ficamente –módulos en caso
de linux– conocen estos registros, sus direcciones relativas y su función. En el caso de un
dipositivo PCI, el driver debe primero encontrar las direcciones base del dispositivo, que el
núcleo ha asignado durante el proceso de configuración del bus PCI.
Una vez obtenida la dirección base, en el caso de tratarse de registros en el mapa de
memoria, el driver debe remapear el bloque de memoria fı́sica en una zona de memoria
virtual del núcleo. En el caso de la entrada/salida, se accederá normalmente usando las
funciones intrı́nsecas que el compilador traduce a las instrucciones de E/S de la arquitectura.
En esta práctica se verá cómo se obtiene la información del dispositivo –proceso que se
estudió en la práctica 1–, cómo se realiza el mapeo de la memoria y cómo se llevan a cabo
los accesos. Se trabajará con el dispositivo controlador de bus USB EHCI y con el puente al
bus SMB, presentes ambos en el ICH del chipset. Se compilará un módulo y un programa
de prueba para cada uno de ellos.
3.
Estructura de los módulos ejemplo
accesoMEM.c y accesoES.c
El módulo implementa las funciones básicas que se vieron en la práctica 1. Más adelante
se describirán sus particularidades. A nivel general, en este ejemplo se ha hecho uso de
las macros MODULE LICENSE(), MODULE AUTHOR() y MODULE DESCRIPTION() para evitar los
avisos del núcleo y para dar información acerca del módulo.
A continuación se comentan las funciones más importantes, haciendo hincapié en sus
diferencias con respecto a lo visto en la primera práctica.
init module(): Es la función que carga el módulo en memoria del núcleo. En este
caso, como el manejador de un dispositivo real, lo primero que se hace es ver que
el dispositivo existe, identificar los recursos y crear las direcciones de acceso. Todo
esto se hace en la función prueba(). Es interesante estudiar el uso de la llamada
pci get device() y de la estructura que devuelve, ası́ como de la función ioremap()
que permite proyectar la memoria fı́sica del dispositivo PCI en el mapa de memoria
del núcleo.
Como en un caso real, si el dispositivo no se encuentra o los recursos no son los
esperados, el módulo indica esta circunstancia y no se carga.
cleanup module(): Es la función que se invoca al eliminar el módulo del núcleo. No
ofrece ninguna particularidad.
acceso read(): La llamada read() en este caso accede realmente a los recursos del
dispositivo, y nos devuelve el valor del registro que previamente hemos seleccionado –con write(). Es interesante constatar cómo se accede a memoria mediante la
función readw() –de la que existen las versiones de 8 y 32 bits, readb() y readl()
respectivamente– o al mapa de entrada/salida mediante la función intrı́nseca inb() –de
la que también existen las versiones de 16 y 32 bits, inw() y inl() respectivamente.
acceso write(): La llamada write() selecciona un registro para efectuar luego la
lectura con read(). Verifica que el registro esté dentro de la zona de recursos reservada
y en el caso de acceso a memoria, fuerza que sea múltiplo de 4 –dado que los accesos
son de 32 bits.
acceso open(): A diferencia de la función de la práctica 1, esta llamada indica al
núcleo que el módulo está siendo usado, mediante la llamada try module get(THIS MODULE),
para que no pueda ser descargado por error.
acceso
módulo
módulo
módulo
4.
release(): En este caso también, la llamada close() indica al núcleo que el
tiene un usario menos –en este ejemplo que no permite más que uno, que el
no está en uso– mediante la función module put(THIS MODULE) para que el
pueda ser descargado sin problemas.
Trabajo a desarrollar
1. Descargad el código de los módulos y de los programas de prueba, en el fichero acceso.v2.tgz. En el archivo acceso.h será necesario eliminar el comentario de la lı́nea que
identifica el chipset de los ordenadores del laboratorio. Observad el fichero Makefile;
permite generar los programas de prueba para ambos módulos invocando el objetivo
correspondiente prES o prMEM. Sin embargo es necesario eliminar el comentario de una
de las dos lı́neas iniciales para generar el módulo correspondiente. Compilad todos los
programas y módulos y cargadlos en el núcleo.
2. Cread los dispositivos adecuados en /dev –consultad para ello el código del programa
de prueba– con las caracterı́sticas correspondientes, y ejecutad las pruebas. Cotejad
los valores devueltos con lo esperado según el manual del chip ICH del chipset del
laboratorio.
3. Observad el código de los módulos, las funciones más significativas y los textos que se
imprimen en los mensajes núcleo. Recompiladlos sin la opción de depuración y probarlo
de nuevo.
4. Crear un nuevo módulo para acceder a memoria o a entrada/salida de algún otro
dispositivo del chipset.
5.
Bibliografı́a
Se puede encontrar más información acerca de los módulos, su creación y la forma de
acceder a ellos en el documento The Linux Kernel Module Programming Guide disponible
en http://www.tldp.org o en la web de la asignatura.