• I.Mx6 hello world模块驱动实验及相关问题解决


    1、模块驱动描述

    1)模块本身不被编译入内核映像,从而控制了内核的大小

    2)模块一旦被加载,它就和内核中的其他部分完全一样

    2、实验步骤

    1) 解压原厂提供的 linux-3.0.35 内核

    $ tar xf linux-3.0.35.tar.bz2

    2)建立一个专门用于编写驱动模块的目录,该目录不在内核目录中

    $ mkdir s-module

    3)进入该模块目录进行 hello world 驱动模块的编写

    $ cd s-module
    $ emacs hello.c &

    hello world 驱动模块的内容如下:

    #include <linux/init.h>
    #include <linux/module.h>
    
    static int __init hello_init(void)
    {
        printk(KERN_ALERT "Hello World
    ");
        return 0;
    }
    
    static void __exit hello_exit(void)
    {
        printk(KERN_ALERT "Saya, Hello World !
    ");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    
    MODULE_AUTHOR("Rex <Rex@fk.com>");
    MODULE_DESCRIPTION("hello world driver");
    MODULE_LICENSE("GPL");

    这个最简单的内核模块只包含内核模块加载函数,卸载函数和对GPL许可权限的声明以及一些描述信息。

    4)linux 内核模块程序结构

    •  模块加载函数 (程序中 module_init 中传入的函数)

          当通过insmod或modprobe 命令加载到内核模块时,模块的加载函数会自动被内核执行。

    • 模块卸载函数(程序中 module_exit 中传入的函数)

              当通过rmmod 命令卸载某模块时,模块的卸载函数会自动被内核执行。

    • 模块许可证声明

              许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将会收到内核的警告

              信息(kernel tainted)

    通常来说模块卸载函数要完成与模块加载函数相反的功能,如下示:

    • 若模块加载函数注册了xxx,则模块卸载函数应注销xxx
    • 若模块加载函数动态申请了内在,则模块卸载函数应释放该内存
    • 若模块加载函数申请了硬件资源(DMA,中断,I/O端口,I/O内存)的占用,则模块卸载函数应释放这些硬件资源
    • 若模块加载函数开启了硬件,则卸载函数中一般要关闭

    5)模块的编译

    通过编写Makefile 由make来完成模块的编译工作,Makefile与hello.c在相同目录下,具体内容如下:

    KDIR=/home/xxx/s-linux-3.0.35
    PWD:=$(shell pwd)
    
    # kernel modules
    obj-m := hello.o
    
    modules:
        make -C $(KDIR) M=$(PWD) modules
    
    clean:
        rm -rf *.o *.ko *.mod.c *.markesr *.order *.symvers
    
    .PHONY:modules clean

    6)模块的编译及遇到的问题

    直接在s-module 目录下进行 make,出现如下错误提示:

    ERROR: Kernel configuration is invalid.
             include/generated/autoconf.h or include/config/auto.conf are missing.
             Run 'make oldconfig && make prepare' on kernel src to fix it.

    解决方法:编译生成内核后再编译模块

    先进入内核根目录,进行如下操作:

    s-linux-3.0.35$ make distclean
    s-linux-3.0.35$ make imx6_defconfig
    s-linux-3.0.35$ make uImage

    然后再进入模块目录,编译模块,如下:

    s-module$ make
    s-module$ ls
    hello.c   hello.mod.c  hello.o   modules.order
    hello.ko  hello.mod.o  Makefile  Module.symvers

    7)注册hello 驱动模块至 I.Mx6 开发板

    目前开发板挂载的是 nfs 文件系统,将hello.ko复制到该nfs 系统中的 /root 下

    在开发板上执行,有如下提示:

    root@freescale ~$ insmod hello.ko 
    hello: version magic '3.0.35-2666-gbdde708 SMP preempt mod_unload modversions ARMv7 ' should be '3.0.35-gae4624f-dirty SMP preempt mod_unload modversions ARMv7 p2v8 '
    insmod: can't insert 'hello.ko': invalid module format

    错误原因:模块驱动的版本信息与内核的版本信息不匹配,开发板加载的内核不是刚刚编译的内核

    解决办法:将新编译好的uImage 内核放至tftp根目录下(开发板通过tftp下载内核),开发板执行

    root@freescale ~$ reboot

     系统启动之后再执行加载操作:

    root@freescale ~$ insmod hello.ko 
    Hello World
    root@freescale ~$ rmmod hello.ko 
    Saya, Hello World !
  • 相关阅读:
    (1)java设计模式之简单工厂模式
    QuartZ Cron表达式在java定时框架中的应用
    java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得
    https实现安全传输的流程
    liunx上运行mybase
    liux之sed用法
    java并发之CyclicBarrier
    java并发之Semaphore
    关于ConcurrentSkipListMap的理解
    java中Iterator和ListIterator的区别与联系
  • 原文地址:https://www.cnblogs.com/aqing1987/p/4346503.html
Copyright © 2020-2023  润新知