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

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

     1 #ifndef __KERNEL__
     2 #  define __KERNEL__
     3 #endif
     4 #ifndef MODULE
     5 #  define MODULE
     6 #endif
     7 
     8 // 下面的是主要的内容
     9 #include <linux/kernel.h>
    10 #include <linux/module.h>
    11 #include <linux/init.h>
    12 
    13 MODULE_LICENSE("GPL");
    14 
    15 static int year=2012;
    16 
    17 int hello_init()
    18 {
    19     printk(KERN_WARNING "Hello kernel, it's %d!\n",year);
    20     return 0;
    21 }
    22 
    23 
    24 void hello_exit()
    25 {
    26     printk("Bye, kernel!\n");
    27 }
    28 
    29 // 下面两个为关键的模块函数
    30 module_init(hello_init);
    31 module_exit(hello_exit);

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

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

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

     1 # The path of kernel source code
     2 INCLUDEDIR = /media/GoldenResources/linux/linux-2.6.30/include
     3 
     4 # Compiler
     5 CC = gcc
     6 
     7 # Options
     8 CFLAGS = -D__KERNEL__ -DMODULE -O -Wall -I$(INCLUDEDIR)
     9 
    10 # Target
    11 OBJS = hello.o
    12 
    13 all: $(OBJS)
    14 
    15 $(OBJS): hello.c
    16     $(CC) $(CFLAGS) -c $<
    17 
    18 install:
    19     insmod $(OBJS)
    20 
    21 uninstall:
    22     rmmod hello
    23 
    24 .PHONY: clean
    25 clean:
    26     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 terminated.
    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/ARM高级班/内核第一天/实验代码/HelloWorld/hello/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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    tcpdump抓包
    openldap quick start guide
    深入理解PHP内核(六)函数的定义、传参及返回值
    深入理解PHP内核(五)函数的内部结构
    mongodb 关系、引用、覆盖索引查询
    mongodb php
    mongodb-$type、limit、skip、sort方法、索引、聚合
    mongodb简介与增删该查
    深入理解PHP内核(四)概览-PHP脚本的执行
    深入理解PHP内核(三)概览-SAPI概述
  • 原文地址:https://www.cnblogs.com/QuLory/p/2736339.html
Copyright © 2011-2022 走看看