next up previous contents index
Next: Un ejemplo de función Up: Módulos para dispositivos de Previous: Escribiendo código reentrante   Índice General   Índice de Materias


La función ioctl().

El módulo que hemos construido hasta ahora parece completo, podemos escribir en el dispositivo y leer de él. Pero generalmente lo dispositivos tienen un rango mayor de posibilidades. Las lectoras de CDROM pueden sacar la bandeja de CD mediante un comando y los discos duros pueden disminuir su velocidad de rotación para ahorrar energía en periodos en los que no se va a hacer uso de ellos.

Si echamos un vistazo de nuevo a las operaciones definidas sobre nuestro dispositivo (file_operations, sección 4.2.2, pág [*]) comprobaremos que no hay ninguna función específicamente dedicada a estos menesteres. En cambio notamos que la función ioctl() está descrita como la función comodín . Es precisamente ioctl() la que nos va a permitir realizar este tipo de tareas.

Supongamos que nuestro dispositivo hardware de cintas es un Walkman con altavoces (si un Walkman, ¡qué pasa!). Hasta ahora estábamos usando el Walkman para escribir y leer datos de él como si fuese disco duro. Pero supongamos que queremos darle otras capacidades, como por ejemplo meterle una cinta de música y hacer que suene. Podemos hacer esto simplemente abriendo la portezuela del Walkman, insertando una cinta de música y apretando al botón de <play>.

Pero también nos gustaría poder hacer un programa que automáticamente abriese la portezuela, esperase unos segundos a que un usuario metiese la cinta, la cerrase y se pusiese a reproducir la música. Dicho programa no tendría que usar para nada las funciones de read y write definidas en nuestro módulo, pues no necesitamos manejar los datos de la cinta para nada, ¡para eso le hemos puesto unos altavoces al Walkman!.

Todas estas capacidades adicionales pueden ser resultas a través de la función ioctl(). Dependiendo de los parámetros que le mandemos a ioctl(), esta podría mandar al Walkman la orden de abrir la portezuela, cerrarla, ponerse a reproducir la cinta (como si hubiésemos apretado el botón de <play>) o parar de reproducirla (como si hubiésemos apretado el botón de <stop>).

Según lo que acabamos de decir parece claro que la función ioctl() de nuestro módulo va a estar formada por un switch que, según los argumentos que le pasemos a la misma, ejecutara un cierto código u otro. Por conveniencia se incluye aquí el prototipo de la función ioctl() de un módulo:

int mpcinta_ioctl(struct inode *pinodo, struct file *pfile, unsigned int comando,
                 unsigned long argumentos)

Como se puede observar los argumentos de entrada a ioctl() son el inodo del dispositivo, la estructura file del dispositivo asociada al proceso que la invocó, un argumento numérico que identificará cual de todas las posibles acciones se quiere realizar (play, stop, abrir la portezuela...) y por último otro argumento numérico (en realidad un puntero) en el que irán los posibles argumentos de las diferentes acciones a realizar, en el caso de que fuesen necesarios.

El identificador numérico del comando se construye concatenando cuatro campos de bits en un unsigned int:

Para la construcción de cada comando, la librería asm/ioctl.h nos proporciona las siguientes macros:

En asm/ioctl.h también se definen unas cuantas macros para decodificar el comando:



Subsecciones
next up previous contents index
Next: Un ejemplo de función Up: Módulos para dispositivos de Previous: Escribiendo código reentrante   Índice General   Índice de Materias
Alberto Cortés 2001-03-26