En muchos ejemplos previos, tuvimos que codificar algo en el módulo del núcleo, tal como el nombre del fichero para los ficheros /proc o el número mayor del dispositivo para el dispositivo para que pudiéramos hacer ioctls en él. Esto va en contra de la filosofía de Unix, y Linux, que es escribir un programa flexible que el usuario pueda configurar.
La forma de decirle a un programa, o a un módulo del núcleo, algo que necesitan antes de empezar a trabajar es mediante los parámetros de la línea de órdenes. En el caso de los módulos del núcleo, no disponemos de argc y argv; en cambio tenemos algo mejor. Podemos definir variables globales en el módulo del núcleo e insmod las rellenará por nosotros.
En este módulo del núcleo definimos dos de ellas: str1 y str2. Todo lo que necesitas hacer es compilar el módulo del núcleo y entonces ejecutar insmod str1=xxx str2=yyy. Cuando se llama a init_module, str1 apuntará a la cadena de caracteres `xxx' y str2 a la cadena de caracteres `yyy'.
En la versión 2.0 no hay comprobación de tipos de estos argumentos6.1. Si el primer carácter de str1 o str2 es un dígito, el núcleo rellenará la variable con el valor del entero, en vez de con un puntero a la cadena de caracteres. En una situación de la vida real tienes que verificar esto.
En cambio, en la versión 2.2 usas la macro MACRO_PARM para decir a insmod lo que esperas como parámetros, su nombre y su tipo. Esto resuelve el problema de los tipos y permite a los módulos del núcleo recibir cadenas de caracteres que empiezan con un dígito, por ejemplo.
/* param.c
*
* Recibe en linea de comandos los parámetros en la instalación del módulo
*/
/* Copyright (C) 1998-99 by Ori Pomerantz */
/* Los ficheros de cabeceras necesarios */
/* Estándar en los módulos del núcleo */
#include <linux/kernel.h> /* Estamos haciendo trabajo del núcleo */
#include <linux/module.h> /* Específicamente, un módulo */
/* Distribuido con CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
#include <stdio.h> /* Necesito NULL */
/* En 2.2.3 /usr/include/linux/version.h se incluye
* una macro para esto, pero 2.0.35 no lo hace - por lo
* tanto lo añado aquí si es necesario */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif
/* Emmanuel Papirakis:
*
* Los nombres de parámetros son ahora (2.2)
* manejados en una macro.
* El núcleo no resuelve los nombres de los
* símbolos como parecía que tenía que hacer.
*
* Para pasar parámetros a un módulo, tienes que usar una macro
* definida en include/linux/modules.h (linea 176).
* La macro coge dos parámetros. El nombre del parámetro y
* su tipo. El tipo es una letra entre comillas.
* Por ejemplo, "i" debería de ser un entero y "s" debería
* de ser una cadena de caracteres.
*/
char *str1, *str2;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
MODULE_PARM(str1, "s");
MODULE_PARM(str2, "s");
#endif
/* Inicializa el módulo - muestra los parámetros */
int init_module()
{
if (str1 == NULL || str2 == NULL) {
printk("La próxima vez, haz insmod param str1=<algo>");
printk("str2=<algo>\n");
} else
printk("Cadenas de caracteres:%s y %s\n", str1, str2);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
printk("Si intentas hacer insmod a este módulo dos veces,");
printk("(sin borrar antes (rmmod)\n");
printk("al primero), quizás obtengas el mensaje");
printk("de error:\n");
printk("'el símbolo para el parámetro str1 no ha sido encontrado'.\n");
#endif
return 0;
}
/* Limpieza */
void cleanup_module()
{
}