Drivers en Linux

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda

Relacionat: Sistemes operatius, Linux, Gestió de memòria, Gestió de E/S, Processos en Linux, Comandos del shell, Scripts Bash, Drivers en Linux, Configuració de la xarxa en Linux, Instal·lar en Linux

Els drivers en Linux poden ser carregats dinàmicament sense necessitat de reiniciar el sistema.

Mòduls

El drivers carregats de forma dinàmica es coneixen com a mòduls. Estan en fitxer que terminen amb .ko (Kernel Object). Linux ha de tindre un lloc específic per a guardar el mòduls.

/lib/modules/<versió del kernel>/kernel

Els comandaments per a manipular els mòduls del kernel són:

  • lsmod - Per a listar els mòduls carregats actualment
  • insmod - Per a carregar un mòdul
  • modprobe - Per a carregar un mòdul amb les seues dependències.
  • rmmod - Per a descarregar un mòdul.

Un driver bàsic

Exemples extrets de: http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html

En Linux, els drivers són implementats com a móduls del kernel. Els móduls són porcions del kernel que poden ser carregades a demanda. Poden extendre les funcions del kernel sense necessitat de reinici.

Un driver mai s'executa per ell mateix. És similar a una biblioteca, que s'executa quant es carrega i s'invoca. Està escrit en C, però no té main(). Les capçaleres que es poden incluir són les del Kernel, no les habituals de /usr/include.

Un fet interessant sobre el kernel és que és una implementació orientada a objectes en C, com anem a observar fins i tot amb el nostre primer driver. Qualsevol controlador de Linux té un constructor i un destructor. El constructor del mòdul ens diu quan el mòdul s'ha carregat correctament en el nucli, i el destructor quan rmmod té èxit en la descàrrega del mòdul. Aquests dos són com les funcions normals del driver, llevat que s'especifiquen com les funcions d'inici i sortida, respectivament, pel module_init() i module_exit(), que es defineixen a la capçalera del kernel de module.h.

/*  
 *  hello-1.c - The simplest kernel module.
 */
#include <linux/module.h>	/* Needed by all modules */
#include <linux/kernel.h>	/* Needed for KERN_INFO */
 
int init_module(void)
{
	printk(KERN_INFO "Hello world 1.\n");

	/* 
	 * A non 0 return means init_module failed; module can't be loaded. 
	 */
	return 0;
}

void cleanup_module(void)
{
	printk(KERN_INFO "Goodbye world 1.\n");
}

Cal destacar que no té stdio.h, a canvi té kernel.h. La capçalera version.h serveix per a que el mòdul siga compatible amb la versió del kernel. Els macros MODULE* són com una signatura.

Compilant

Una vegada tenim el ofd.c tenim que compilar i crear el ofc.ko. S'utilitza el Kernel build system. A continuació anem a veure un Makefile per a crear un mòdul del kernel.


obj-m += hello-1.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

En aquest cas es suposa que codi font del kernel es troba en /usr/src/linux. Si està en un altra localització, cal modificar el KERNEL_SOURCE.

$ make
make -C /lib/modules/2.6.32-47-generic/build M=/home/ubuntu/drivers modules
make[1]: se ingresa al directorio «/usr/src/linux-headers-2.6.32-47-generic»
  CC [M]  /home/ubuntu/drivers/hello-1.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/ubuntu/drivers/hello-1.mod.o
  LD [M]  /home/ubuntu/drivers/hello-1.ko
make[1]: se sale del directorio «/usr/src/linux-headers-2.6.32-47-generic»
$ ls
hello-1.c   hello-1.mod.c  hello-1.o  Makefile~      Module.symvers
hello-1.ko  hello-1.mod.o  Makefile   modules.order  ofd.c

Si fem:

# insmod hello-1.ko
# rmmod hello-1

Podem veure que en /var/log/messages o kern.log el módul ha escrit un missatge.

Segona versió (macros)

A partir del kernel 2.4, es poden crear macros per a sustituir al init_module i el cleanup_module(). Els macros es diuen module_init() i module_exit().

/*  
*  hello-2.c - Demonstrating the module_init() and module_exit() macros.
*  This is preferred over using init_module() and cleanup_module().
*/
#include <linux/module.h>	/* Needed by all modules */
#include <linux/kernel.h>	/* Needed for KERN_INFO */
#include <linux/init.h>		/* Needed for the macros */

static int __init hello_2_init(void)
{
	printk(KERN_INFO "Hello, world 2\n");
	return 0;
}

static void __exit hello_2_exit(void)
{ 
	printk(KERN_INFO "Goodbye, world 2\n");
}

module_init(hello_2_init);
module_exit(hello_2_exit);

En el Makefile cal afegir:

obj-m += hello-2.o


Tercer Versió (Documentació)

Existeixen una serie de macros per a informar de l'autor o de la llicència. No són útils per al kernel, sols per al modinfo

/*  
 *  hello-4.c - Demonstrates module documentation.
 */
#include <linux/module.h>	/* Needed by all modules */
#include <linux/kernel.h>	/* Needed for KERN_INFO */
#include <linux/init.h>		/* Needed for the macros */
#define DRIVER_AUTHOR "Peter Jay Salzman <p@dirac.org>"
#define DRIVER_DESC   "A sample driver"

static int __init init_hello_4(void)
{
	printk(KERN_INFO "Hello, world 4\n");
	return 0;
}

static void __exit cleanup_hello_4(void)
{
	printk(KERN_INFO "Goodbye, world 4\n");
}

module_init(init_hello_4);
module_exit(cleanup_hello_4);

/*  
 *  You can use strings, like this:
 */

/* 
 * Get rid of taint message by declaring code as GPL. 
 */
MODULE_LICENSE("GPL");

/*
 * Or with defines, like this:
 */
MODULE_AUTHOR(DRIVER_AUTHOR);	/* Who wrote this module? */
MODULE_DESCRIPTION(DRIVER_DESC);	/* What does this module do */

/*  
 *  This module uses /dev/testdevice.  The MODULE_SUPPORTED_DEVICE macro might
 *  be used in the future to help automatic configuration of modules, but is 
 *  currently unused other than for documentation purposes.
 */
MODULE_SUPPORTED_DEVICE("testdevice");

$ modinfo hello-4.ko
filename:       hello-4.ko
description:    A sample driver
author:         Peter Jay Salzman <p@dirac.org>
license:        GPL
srcversion:     9ACA98AD11775A2DCB1EE86
depends:        
vermagic:       3.2.0-45-generic SMP mod_unload modversions 

Passar argument per línia de comandaments a un módul

Enllaços

http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html

http://www.linuxforu.com/2010/12/writing-your-first-linux-driver/

http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html

http://www.freesoftwaremagazine.com/articles/drivers_linux