PDF de programación - Breve tutorial para escribir drivers en Linux

Imágen de pdf Breve tutorial para escribir drivers en Linux

Breve tutorial para escribir drivers en Linuxgráfica de visualizaciones

Publicado el 30 de Abril del 2019
624 visualizaciones desde el 30 de Abril del 2019
84,5 KB
27 paginas
Creado hace 23a (01/01/2001)
Breve tutorial para escribir

drivers en Linux

Xavier Calbet

GULIC (Grupo de Usuarios de LInux de Canarias)

[email protected]

“Do you pine for the nice days of Minix-1.1, when men were men and
wrote their own device drivers?”

Linus Torvalds

Licencia

Copyright (C) 2001 Xavier Calbet.

Se otorga permiso para copiar, distribuir y/o modificar este documento
bajo los términos de la Licencia de Documentación Libre GNU, Versión
1.1 o cualquier otra versión posterior publicada por la Free Software
Foundation. Puede consultar una copia de la licencia en:
http://www.gnu.org/copyleft/fdl.html

1. Requisitos preliminares

Para realizar drivers para Linux es necesario unos conocimientos previos mínimos que
son:

• Programar en C. Es necesario conocer de forma relativamente profunda la

programación en C como los punteros, funciones de manipulación de bits, etc.

• Nociones de funcionamiento de los microprocesadores. Es necesario tener nociones
del funcionamiento interno de los microordenadores tales como el direccionamiento

1

Breve tutorial para escribir drivers en Linux

de memoria, interrupciones, etc. Sabiendo programar en ensamblador todos estos
conceptos resultarán familiares.

Existen varios tipos de dispositivos diferentes en Linux. Por sencillez, en este breve
tutorial veremos los dispositivos tipo char cargados como módulos. Se utilizará la
versión del kernel 2.2.x (en concreto la 2.2.14), aunque los módulos funcionarán con
modificaciones pequeñas o nulas en la versión 2.4.x.

2. Espacio de usuario (“user space”) y espacio
de kernel (“kernel space”)

Cuando se escriben drivers es importante distinguir entre el espacio de usuario (“user
space”) y el espacio de kernel (“kernel space”).

• Espacio del kernel (“kernel space”). El sistema operativo Linux y en especial su

kernel se ocupan de gestionar los recursos de hardware de la máquina de una forma
eficiente y sencilla, ofreciendo al usuario una interfaz de programación simple y
uniforme. El kernel, y en especial sus drivers, constituyen así un puente o interfase
entre el programador de aplicaciones para el usuario final y el hardware. Toda
subrutina que forma parte del kernel tales como los módulos o drivers se consideran
que están en el espacio del kernel (“kernel space”).

• Espacio de usuario (“user space”). Los programas que utiliza el usuario final, tales
como las “shell” u otras aplicaciones con ventanas como por ejemplo “kpresenter”,
residen en el espacio de usuario (“user space”). Como es lógico estas aplicaciones
necesitan interaccionar con el hardware del sistema, pero no lo hacen directamente,
sino a través de las funciones que soporta el kernel.

Todo esto se puede visualizar en la Fig. 1.

2

Breve tutorial para escribir drivers en Linux

Figura 1. Espacio de usuario donde residen las aplicaciones y espacio de kernel donde
residen los módulos o drivers.

3. Funciones de intercambio entre el espacio
de usuario y el espacio de kernel

El kernel ofrece una serie de subrutinas o funciones en el espacio de usuario que
permiten al programador de aplicaciones finales interaccionar con el hardware.
Habitualmente, en sistemas UNIX o Linux, este diálogo se hace a través de las
funciones o subrutinas para leer y escribir en ficheros, ya que en estos sistemas los
propios dispositivos se ven desde el punto de vista del usuario como ficheros.

Por otro lado, en el espacio del kernel, Linux también ofrece una serie de funciones o
subrutinas para por un lado interaccionar directamente, a bajo nivel, con los
dispositivos hardware y por otro permite el paso de información desde el kernel al
espacio de usuario.

Es común que para cada función en el espacio de usuario que permite el uso de
dispositivos o ficheros haya su equivalente en el espacio de kernel que permite el

3

Breve tutorial para escribir drivers en Linux

trasvase de información del espacio de kernel al de usuario y viceversa. Esto se puede
apreciar en la Tabla 1, la cual de momento se quedará vacía y se irá rellenando a
medida que se vayan introduciendo los diferentes conceptos de los drivers.

Eventos

Funciones de usuarios

Funciones del kernel

Carga de módulo
Abrir dispositivo
Leer dispositivo

Escribir dispositivo
Cerrar dispositivo

Quitar módulo

Tabla 1. Eventos de los drivers y sus funciones asociadas de intercambio entre el
espacio de kernel y el espacio de usuario.

4. Funciones de intercambio entre el espacio
de kernel y el dispositivo hardware

De forma análoga existen funciones en el espacio de kernel que sirven para controlar el
dispositivo o trasvasar información entre el kernel y el hardware. La Tabla 2 nos ilustra
estos eventos, la cual iremos rellenando a medida que se vayan introduciendo los
conceptos.

Eventos
Leer datos

Escribir datos

Funciones del kernel

Tabla 2. Eventos de los drivers y sus funciones asociadas entre el espacio de kernel y el
dispositivo hardware.

5. El primer driver: carga y descarga del driver

4

en el espacio de usuario

Breve tutorial para escribir drivers en Linux

Veremos ahora un driver con el que empezar. Se introducirá dentro del kernel como un
módulo.

Para ello se escribe este programa en un fichero llamado nada.c

<<nada.c>>=

#define MODULE
#include <linux/module.h>

Lo compilamos con el siguiente comando:

$ gcc -c nada.c

(en realidad, para que funcione siempre sin problemas el comando para compilar
debería ser

$ gcc -I/usr/src/linux/include -O -Wall -c nada.c ,

donde detrás de -I debe aparecer el directorio donde se encuentren los ficheros include
del kernel)

Este elemental módulo pertenece al espacio de kernel y entrará a formar parte de él
cuando se cargue.

Dentro del espacio de usuario podemos cargar el módulo en el kernel en la línea de
comandos como usuario root con

# insmod nada.o

(si éste no funciona se puede probar insmod -f nada.o).

El comando insmod permite instalar nuestro módulo en el kernel, aunque éste en
concreto no tenga ninguna utilidad.

Podemos comprobar que el módulo ha sido instalado mediante el comando que lista
todos los módulos instalados:

# lsmod

Finalmente podemos eliminar el módulo del kernel con el comando

# rmmod nada

Podemos comprobar que el módulo ya no está instalado de nuevo con el comando
lsmod.

Podemos ver un resumen de todo esto en la Tabla 3.

5

Breve tutorial para escribir drivers en Linux

Eventos

Funciones de usuarios

Funciones del kernel

Carga de módulo
Abrir dispositivo
Leer dispositivo

Escribir dispositivo
Cerrar dispositivo

Quitar módulo

insmod

rmmod

Tabla 3. Eventos de los drivers y sus funciones asociadas de intercambio entre el
espacio de kernel y el espacio de usuario.

6. El driver “Hola mundo”: carga y descarga del
driver en el espacio de kernel

Normalmente cuando se carga un módulo de un driver de un dispositivo en el kernel se
suelen realizar una serie de tareas preliminares como reiniciar el dispositivo, reservar
RAM, reservar interrupciones, reservar los puertos de entrada/salida del dispositivo,
etc.

Para ello existen dos funciones, init_module y cleanup_module, dentro del espacio de
kernel correspondientes a las del espacio de usuario, insmod y rmmod, que se utilizan
cuando se instala o quita un módulo. Dichas funciones son llamadas por el kernel
cuando se realizan estas operaciones.

Veamos un ejemplo práctico con el clásico programa “Hola mundo”:

<<hola.c>>=

#define MODULE
#include <linux/module.h>

int init_module(void) {

printk("<1>Hola mundo\n");
return 0;

}

void cleanup_module(void) {

printk("<1>Adios mundo cruel\n");

6

}

Breve tutorial para escribir drivers en Linux

También se ha introducido la función printk, la cual es muy similar a la conocida printf
sólo que opera dentro del kernel. El símbolo <1> indica la prioridad del mensaje, se ha
especificado una alta prioridad (bajo número) para que el mensaje aparezca por pantalla
y no se quede en los ficheros de mensajes del kernel.

Cuando se cargue y descargue el módulo aparecerán en la consola los mensajes que
hemos escrito dentro de printk. Si no los vemos inmediatamente en la consola podemos
escribir el comando dmesg en la línea de comandos para verlos o mostrando el fichero
de mensajes del sistema con cat /var/log/syslog.

En la Tabla 4 se pueden ver estas dos nuevas funciones.

Eventos

Funciones de usuarios

Funciones del kernel

Carga de módulo
Abrir dispositivo
Leer dispositivo

Escribir dispositivo
Cerrar dispositivo

Quitar módulo

insmod

init_module

rmmod

cleanup_module

Tabla 4. Eventos de los drivers y sus funciones asociadas de intercambio entre el
espacio de kernel y el espacio de usuario.

7. El driver completo “memoria”: parte inicial
del driver

Ahora realizaremos un driver completo, memoria.c, utilizando la memoria del
ordenador que nos permitirá escribir y leer un carácter en memoria. Este dispositivo,
aunque no muy útil, es muy ilustrativo dado que es un driver completo y fácil de
implementar ya que no se necesita un dispositivo real.

Para realizar un driver, en la parte inicial de él, tendremos que definir las constantes
MODULE y __KERNEL__. Además tendremos que incluir, con #include, una serie de
ficheros habituales en los drivers:

7

Breve tutorial para escribir drivers en Linux

<<memoria inicio>>=

/* Definiciones e includes necesarios para los drivers */
#define MODULE
#define __KERNEL__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/malloc.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */

/* Declaracion de funciones de memoria.c */
int memoria_open(struct inode *inode, struct file *filp);
int memoria_release(struct inode *inode, struct file *filp);
ssize_t memoria_read(struct file *filp, char *buf,

size_t count, loff_t *f_pos);

ssize_t memoria_write(struct
  • Links de descarga
http://lwp-l.com/pdf15798

Comentarios de: Breve tutorial para escribir drivers en Linux (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad