zoukankan      html  css  js  c++  java
  • Linux 内核源码外编译 linux模块--编译驱动模块的基本方法

    1、先编写一个简单的hello模块,hello.c 源码如下:

    #ifndef __KERNEL__
    #  define __KERNEL__
    #endif
    #ifndef MODULE
    #  define MODULE
    #endif
    
    // 下面的是主要的内容
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    static int year=2012;
    
    int hello_init()
    {
        printk(KERN_WARNING "Hello kernel, it's %d!
    ",year);
        return 0;
    }
    
    
    void hello_exit()
    {
        printk("Bye, kernel!
    ");
    }
    
    // 下面两个为关键的模块函数
    module_init(hello_init);
    module_exit(hello_exit);

    如果上面的代码看起来不太熟悉,那么需要查看以下相关的书籍,比如《Linux设备驱动程序,第三版》,也就是大名鼎鼎的LDD;

    2、老式驱动模块编译方法:

    直接写出make规则到makefile文件中,引用内核体系的头文件路径,举例如下:

    # The path of kernel source code
    INCLUDEDIR = /media/GoldenResources/linux/linux-2.6.30/include
    
    # Compiler
    CC = gcc
    
    # Options
    CFLAGS = -D__KERNEL__ -DMODULE -O -Wall -I$(INCLUDEDIR)
    
    # Target
    OBJS = hello.o
    
    all: $(OBJS)
    
    $(OBJS): hello.c
        $(CC) $(CFLAGS) -c $<
    
    install:
        insmod $(OBJS)
    
    uninstall:
        rmmod hello
    
    .PHONY: clean
    clean:
        rm -f *.o

    这里有我是用的一个linux内核源代码路径:/media/GoldenResources/linux/linux-2.6.30/include ,注意设置到正确的源码路径。

    尝试这编译:$make

    gcc -D__KERNEL__ -DMODULE -O -Wall -I/media/GoldenResources/linux/linux-2.6.30/include -c hello.c
    In file included from /media/GoldenResources/linux/linux-2.6.30/include/linux/kernel.h:11:0,
                     from hello.c:8:
    /media/GoldenResources/linux/linux-2.6.30/include/linux/linkage.h:5:25: fatal error: asm/linkage.h: No such file or directory
    compilation tterminate
    make:
    *** [hello.o] Error 1

    出现错误: include/linux/linkage.h:5:25: fatal error: asm/linkage.h: No such file or directory , 网上查阅相关资料后,找到不错的说明:

    请查看:http://stackoverflow.com/questions/9492559/module-compiling-asm-linkage-h-file-not-found 

    主要意思是这种编译方法不能很好的解决相关的依赖体系,主要是源于历史原因,linux内核升级很快,越来越复杂,所以建议使用kbuild体系来自动完成;故下面采用了可行的kbuild体系来完成。

    3、使用kbuild进行模块编译:

    基本方法可以参考: http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt

    核心思想是,通过-C指明系统上的内核体系路径,通过M=指明模块源文件路径,然后自己构造一个makefile文件,从而实现编译过程。

    3.1 构建适用于kbuild方法的makefile:

    obj-m := hello.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

    开始make:

    $make
    make -C /lib/modules/3.5.0-17-generic/build M=/media/GoldenResources/arm/ARM/HelloWorld/hello modules
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
    scripts/Makefile.build:44: /media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile: No such file or directory
    make[2]: *** No rule to make target `/media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile'.  Stop.
    make[1]: *** [_module_/media/GoldenResources/arm/ARM/HelloWorld/hello] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'
    make: *** [all] Error 2

    自动使用了当前运行中的内核,构建对应的模块,但是提示找不到Makefile,而该目录下的文件为makefile,所以尝试修改名字:

    $mv makefile  Makefile

    特别注意,要使用Makefile才行!不能时makefile;

    修改后,编译成功:

    $make
    make -C /lib/modules/3.5.0-17-generic/build M=/media/GoldenResources/arm/ARM/HelloWorld/hello modules
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic'
      Building modules, stage 2.
      MODPOST 1 modules  # 说明成功编译了一个模块
    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic'

    3.2 加载和删除内核模块:

    $sudo insmod ./hello.ko #加载
    $sudo rmmod hello       #删除

    并没有看到源代码中的输出信息,查看系统相应日志即可:

    $tail /var/log/kern.log   # 注意ubuntu下的日志路径
    Oct 23 22:22:22 qunengrong-Studio-1450 kernel: [43021.773888] Hello kernel, it's 2012!
    Oct 23 22:22:37 qunengrong-Studio-1450 kernel: [43037.092339] Bye, kernel!

    至此,我们已经可以成功编译和加载内核模块了;

    4、额外成就,要注意模块与内核版本的匹配:

    假设我直接使用另一个内核体系进行构建,比如3.5.0-15-generic,但是当前系统运行的为3.5.0-17-generic的内核,则加载时报错,如下:

    $make -C /lib/modules/3.5.0-15-generic/build M=`pwd` modules
    make: Entering directory `/usr/src/linux-headers-3.5.0-15-generic'
      CC [M]  /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.o
    /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c:16:5: warning: function declaration isn’t a prototype
    /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c:23:6: warning: function declaration isn’t a prototype
      Building modules, stage 2.
      MODPOST 1 modules
      CC      /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.mod.o
      LD [M]  /media/GoldenResources/arm/AR/HelloWorld/heARo/hello.ko
    make: Leaving directory `/usr/src/linux-headers-3.5.0-15-generic'
    
    $sudo insmod ./hello.ko  # 版本不一致报错
    insmod: error inserting './hello.ko': -1 Invalid module format

    由此可见,使用自动构建带来的方便,将该通用Makefile分享如下:

    obj-m := name.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

    转:http://www.cnblogs.com/QuLory/ 

  • 相关阅读:
    Lodop简短问答客户反馈篇 及排查步骤 及注册相关
    Win10图片打不开文件系统错误2147416359解决方法
    Lodop中特殊符号¥打印设计和预览不同
    LODOP安装参数 及静默安装
    LODOP打印安装到win的特殊字体
    Lodop打印设计(PRINT_DESIGN)介绍
    Lodop打印设计里的 打印项对齐
    System.out.println与System.err.println的区别(输出顺序!!!)
    享元模式
    Java中关于HashMap的元素遍历的顺序问题
  • 原文地址:https://www.cnblogs.com/Lxk0825/p/10412957.html
Copyright © 2011-2022 走看看