Notas de estudio de Linux integradas (1) programación del módulo del kernel

1. Resumen

  He estado involucrado en la industria incrustada durante muchos años. Aunque he estado expuesto a Linux embebido por razones de trabajo y también he participado en el desarrollo de las funciones subyacentes y de aplicación de productos relacionados, para el núcleo, los controladores y el desarrollo de la capa superior de Linux embebido, todavía me mantengo en lo básico. El sistema no ha resumido completamente el nivel de uso práctico. Con el aumento de los años de trabajo, siento cada vez más el cuello de botella técnico causado por esta sensación impetuosa. Desde que se encontró el problema, es natural resolverlo. Recordando mi experiencia de ingresar a la industria integrada, son las notas resumidas de aprendizaje del chip STM32 y la parte de la red las que me apoyan hasta el momento. El desarrollo del controlador de Linux comenzó, y el estudio sistemático y el resumen de Linux embebido también es la solución más adecuada para mi situación actual, razón por la cual estoy decidido a abandonar el entretenimiento diario y comenzar esta serie.

  El dominio y el aprendizaje de Linux embebido es un proceso muy complicado: desde la instalación más básica de Linux, aprendizaje y aplicación de instrucciones de shell, construcción de entornos de compilación cruzada, desarrollo de lenguaje C, interfaz de kernel de Linux, interfaz de sistema Linux, después de dominar todo el conocimiento previo , Solo completó la construcción básica del desarrollo del producto. Este conocimiento no solo es difícil de aprender, sino también para aquellos que han dominado el uso del texto para describir claramente, especialmente los problemas de compilación y depuración causados ​​por la versión del sistema / software, encontrados en el aprendizaje y el desarrollo. Las preguntas se resolverán y se tratarán en este artículo. Si no entiende, debe ser bueno en el uso de motores de búsqueda, y básicamente puede encontrar las respuestas a los problemas encontrados en el desarrollo de Linux incorporado . Debe recordar. No hay mucho que decir, la siguiente es la descripción del artículo principal.

2. Implementación del módulo de kernel

   Los controladores Linux integrados están en forma de módulos, y es necesario dominar la realización de los módulos del núcleo. De hecho, en términos simples, Linux define las interfaces que el módulo del núcleo debe implementar. Los desarrolladores solo necesitan implementar estas interfaces requeridas en lenguaje C de acuerdo con las reglas. Después de compilar de acuerdo con ciertas reglas, pueden usar los comandos del sistema lsmod / rmmod para cargar y eliminar Módulos definidos, este conjunto de reglas es lo que necesitamos aprender sobre el módulo del núcleo, que se divide en las siguientes interfaces según la función:

Debe módulo

  Función de carga del módulo: module_init (func)

  Función de descarga del módulo: module_exit (func)

  Declaración de licencia del módulo: MODULE_LICENSE ("str")

    支持 的 许可 有: "GPL", "GPL V2", "GPL y derecho adicional", "Dual BSCD / GPL", "DUAL MPL / GPL", "Propietario"

Módulos opcionales

  Parámetros del módulo: pase la variable module_param (name, charp, S_IRUGO) cuando se carga el módulo;

  Símbolos de exportación de módulos: se utilizan para exportar símbolos para su uso por otros módulos del núcleo.

    EXPORT_SYSMBOL (función) / EXPORT_SYSMBOL_GPL (función)

    El kernel 2.6 de Linux agrega un mecanismo de verificación de la función. Cuando es necesario introducir módulos posteriores, la ruta y el símbolo del núcleo de la función importado deben agregarse en Module.symvers.

  Módulo autor-MODULE_AUTHOR ("str")

  Descripción del módulo-MODULE_DESCRIPTION ("str")

  Versión del módulo-MODULE_VERSION ("str")

  Módulo alias-MODULE_ALIAS ("str")

  Tabla de dispositivo de módulo-MODULE_DEVICE_TABLE, para dispositivos USB o PCI que necesitan ser compatibles, indicando dispositivos compatibles, actualmente no descritos en detalle.

  Sobre la base de la comprensión de los módulos anteriores, se puede realizar el siguiente código de módulo:

// hello.ko 
#include <linux / init.h> 
#include <linux / module.h> // extern int add_integar (int a, int b); char estático * buf = " driver " ; 
module_param (buf, charp, S_IRUGO); // 模块 参数static int __init hello_init ( void ) 
{ int dat = 3 ; // int dat = add_integar (5, 6); 
        printk (KERN_WARNING " hola mundo enter,% s,% d \ n " , buf, dat);
        devuelve 0 ; 
module_init (hello_init);  



 

 
         
} // Función de carga del módulo 

static  void __exit hello_exit ( void ) 
{ 
    printk (KERN_WARNING " hello world exit \ n " ); 
} 
module_exit (hello_exit);              // Función de desinstalación del módulo 

MODULE_AUTHOR ( " ZC " );                          // Autor del módulo 
MODULE_LICENSE ( " GPL v2 " );                      // Acuerdo de licencia del módulo 
MODULE_DESCRIPTION ( " un simple módulo de saludo " );   // Descripción de la licencia del módulo
MODULE_ALIAS ( "un módulo más simple " );             // alias de módulo

Use el archivo Makefile de la siguiente manera:

ifeq ($ (KERNELRELEASE),) 
KDIR: = / lib / modules / $ (shell uname -r) / build 
PWD: = $ (shell pwd ) 
módulos: 
        $ (MAKE) -C $ (KDIR) M = $ (PWD ) módulos 
módulos_instalación: 
        $ (MAKE) -C $ (KDIR) M = $ (PWD) módulos_install 
clean: 
        rm -rf * .o * .ko .depend * .mod.o * .mod.c modules. * 
.PHONY: módulos modules_install clean 
else 
obj -m: = hello.o 
endif

Después de guardar, puede usar Make para compilar. Si encuentra un error de compilación, verifique los comentarios al final del artículo. Si no hay problemas, busque o deje un mensaje.

 

Luego ejecute el comando modinfo hello.ko para ver la información del módulo actual.

Si no puede ver la información, puede ver la información de carga a través de dmesg.

2. Llamada de módulo cruzado del módulo del núcleo

  La sección anterior puede resolver la mayoría de los problemas de implementación de kernel que encontramos, pero a veces es posible que necesitemos algunos módulos de kernel comunes para proporcionar interfaces para la mayoría de los módulos, lo que implica llamadas entre módulos de módulos de kernel.

  Para la implementación de la llamada de módulo de núcleo cruzado, para el módulo llamado, existen principalmente dos pasos:

    1. Agregue extern int add_integar (int a, int b) a la implementación del código;

    2. Modifique el archivo Module.symvers en el entorno de compilación, agregue la dirección del módulo vinculado y el valor de verificación de la función (puede copiarlo visualizando Module.symvers en el entorno de compilación del módulo vinculado)

  Para los módulos vinculados, la implementación del código es la siguiente:

//math.ko
#include <linux/init.h>
#include <linux/module.h>

static int __init math_init(void)
{
    printk(KERN_WARNING "math enter\n");
    return 0;
}
module_init(math_init);

static void __exit math_exit(void)
{
    printk(KERN_WARNING "math exit\n");
}
module_exit(math_exit);

int add_integar(int a, int b)
{
        return a+b;
}
EXPORT_SYMBOL(add_integar);

int sub_integar(int a, int b)
{
        return a-b;
}
EXPORT_SYMBOL(sub_integar);

MODULE_LICENSE("GPL V2");

编译Makefile同上,需要将obj-m :=hello.o修改为obj-m :=math.o

执行make编译完成该文件,并通过insmod加载完模块后,可通过

grep integar /proc/kallsyms 查看加载在内核中的符号,状态如下:

 然后加载insmod hello.ko, 即可跨文件调用该接口。如此,便初步完成对Linux内核模块的学习。

本文参考资料:

 1. 《Linux设备驱动开发详解:基于最新的Linux4.0内核》 第四章

备注:

  下面讲述编译遇到的问题和解决方案。

  1.内核编译名称必须为Makefile,否则编译会出错

    make[2]: *** No rule to make target `/usr/kernel/hello/Makefile'.  Stop.

    make[1]: *** [_module_/usr/kernel/hello] Error 2

    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-23-generic'

    2.Makefile的内容,如果编译多个文件obj-m :=hello.o test.o

  3.Makefile中,指令必须以Tab对齐,否则编译会异常。

  4.printk不打印,一般来说输出的KERNEL_INFO为超过最大输出值,可直接通过dmesg,在系统信息内查看。

  5.内核跨文件访问接口

  除EXPORT_SYSMBOL外,在编译时Module.symvers需要包含对应函数的校验值,路径

  0x13db98c9      sub_integar     /usr/kernel/math/math   EXPORT_SYMBOL

  0xe1626dee      add_integar     /usr/kernel/math/math   EXPORT_SYMBOL

  否则编译时报警告

    WARNING: "add_integar" [/usr/kernel/hello/hello.ko] undefined!

  安装模块时出错

    [ 9091.025357] hello: no symbol version for add_integar

    [ 9091.025360] hello: Unknown symbol add_integar (err -22)

 

Supongo que te gusta

Origin www.cnblogs.com/zc110747/p/12747213.html
Recomendado
Clasificación