Notas sobre o estudo do Linux embarcado (1) programação de módulos do kernel

1. Resumo

  Há muitos anos que estou envolvido no setor de embarcações, apesar de ter sido exposto ao Linux embarcado por motivos de trabalho e também participado do desenvolvimento das funções subjacentes e de aplicativos de produtos relacionados, para o kernel, drivers e desenvolvimento da camada superior do Linux embarcado, ainda permaneço no entendimento básico O nível de uso prático não foi completamente resumido pelo sistema.Com o aumento dos anos de trabalho, sinto cada vez mais o gargalo técnico causado por esse sentimento impetuoso. Desde que o problema foi encontrado, é natural resolvê-lo.Lembrando minha experiência de ingressar na indústria incorporada, são as notas de resumo de aprendizado do chip STM32 e da parte da rede que me apoiam até o presente momento. O desenvolvimento do driver Linux foi iniciado, e o estudo sistemático e o resumo do Linux incorporado também são a solução mais adequada para a minha situação atual.Esta é também a razão pela qual estou determinado a desistir do entretenimento diário e iniciar esta série.

  Dominar e aprender o Linux embarcado é um processo muito complicado: desde a instalação mais básica do Linux, aprendizado e aplicação de instruções do shell, construção do ambiente de compilação cruzada, desenvolvimento da linguagem C, interface do kernel Linux, interface do sistema Linux, depois de dominar todo o conhecimento anterior , Concluiu apenas a construção básica do desenvolvimento do produto.Este conhecimento não é apenas difícil de aprender, mas também para aqueles que aprenderam a usar o texto para descrever claramente, especialmente os problemas de compilação e depuração causados ​​pela versão do sistema / software encontrados no aprendizado e no desenvolvimento. As perguntas serão resolvidas e serão abordadas neste artigo. Se você não entende, deve ser bom em usar mecanismos de pesquisa e basicamente pode encontrar as respostas para os problemas encontrados no desenvolvimento do Linux embarcado . Não há muito a dizer, a seguir está a descrição do artigo principal.

2. Implementação do módulo Kernel

   Os drivers Linux embutidos são todos na forma de módulos, e é necessário dominar a realização dos módulos do kernel. De fato, em termos simples, o Linux define as interfaces que o módulo do kernel precisa implementar: enquanto os desenvolvedores implementam essas interfaces necessárias na linguagem C de acordo com as regras, compilam de acordo com certas regras, eles podem usar os comandos do sistema lsmod / rmmod para carregar e remover Módulos definidos, este conjunto de regras é o que precisamos aprender sobre o módulo do kernel, que é dividido nas seguintes interfaces de acordo com a função:

Módulo obrigatório

  Função de carregamento do módulo: module_init (func)

  Função de descarregamento do módulo: module_exit (func)

  Declaração de licença do módulo: MODULE_LICENSE ("str")

    有 的 许可 有: "GPL", "GPL V2", "GPL e direito adicional", "BSCD / GPL duplo", "MPL / GPL DUAL", "Proprietário"

Módulos opcionais

  Parâmetros do módulo - passe a variável module_param (name, charp, S_IRUGO) quando o módulo estiver carregado;

  Símbolos de exportação de módulo - usados ​​para exportar símbolos para uso por outros módulos do kernel.

    EXPORT_SYSMBOL (função) / EXPORT_SYSMBOL_GPL (função)

    O kernel Linux 2.6 adiciona um mecanismo de verificação de função.Quando os módulos subseqüentes precisam ser introduzidos, o caminho e o símbolo do kernel de função importado devem ser adicionados em Module.symvers.

  Autor do módulo-MODULE_AUTHOR ("str")

  Descrição do módulo-MODULE_DESCRIPTION ("str")

  Módulo version-MODULE_VERSION ("str")

  Alias ​​do módulo-MODULE_ALIAS ("str")

  Tabela de dispositivos do módulo-MODULE_DEVICE_TABLE, para dispositivos USB ou PCI que precisam ser suportados, indicando dispositivos suportados, atualmente não descritos em detalhes.

  Com base na compreensão dos módulos acima, o seguinte código de módulo pode ser realizado:

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



 

 
         
module_init (hello_init);   // Função de carregamento do módulo 

static  void __exit hello_exit ( void ) 
{ 
    printk (KERN_WARNING " olá mundo saída \ n " ); 
} 
module_exit (hello_exit);              // função de desinstalação do módulo 

MODULE_AUTHOR ( " ZC " );                          // Autor do módulo 
MODULE_LICENSE ( " GPL v2 " );                      // Contrato de licença do módulo 
MODULE_DESCRIPTION ( " um simples módulo hello " );   // Descrição da licença do módulo
MODULE_ALIAS ( "um módulo mais simples " );             // alias do módulo

Use o arquivo Makefile da seguinte maneira:

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

Após salvar, você pode usar Make para compilar. Se você encontrar um erro de compilação, verifique as observações no final do artigo. Se não houver nenhum problema, pesquise ou deixe uma mensagem.O resultado da compilação é mostrado na figura.

 

Em seguida, execute o comando modinfo hello.ko para visualizar as informações atuais do módulo.

Se você não conseguir visualizar as informações, poderá visualizar as informações de carregamento através do dmesg.

2. Chamada entre módulos do módulo do kernel

  A seção anterior pode resolver a maioria dos problemas de implementação do kernel que encontramos, mas às vezes podemos precisar de alguns módulos comuns do kernel para fornecer interfaces para a maioria dos módulos, o que envolve chamadas entre módulos dos módulos do kernel.

  Para a implementação da chamada de módulo cross-core, para o módulo chamado, existem principalmente duas etapas:

    1. Adicione extern int add_integar (int a, int b) à implementação do código;

    2. Modifique o Module.symvers no ambiente de compilação, adicione o endereço do módulo vinculado e o valor de verificação da função (você pode copiá-lo visualizando o Module.symvers no ambiente de compilação do módulo vinculado)

  Para os módulos vinculados, a implementação do código é a seguinte:

//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)

 

Acho que você gosta

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