Lxk0825

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!\n",year);
    return 0;
}


void hello_exit()
{
    printk("Bye, kernel!\n");
}

// 下面两个为关键的模块函数
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/ 

分类:

技术点:

相关文章: