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=; int hello_init()
{
printk(KERN_WARNING "Hello kernel, it's %d!\n",year);
return ;
} 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./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./include -c hello.c
In file included from /media/GoldenResources/linux/linux-2.6./include/linux/kernel.h::,
from hello.c::
/media/GoldenResources/linux/linux-2.6./include/linux/linkage.h::: fatal error: asm/linkage.h: No such file or directory
compilation tterminate
make: *** [hello.o] Error

出现错误: 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.--generic/build M=/media/GoldenResources/arm/ARM/HelloWorld/hello modules
make[]: Entering directory `/usr/src/linux-headers-3.5.--generic'
scripts/Makefile.build:: /media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile: No such file or directory
make[]: *** No rule to make target `/media/GoldenResources/arm/ARM/HelloWorld/hello/Makefile'. Stop.
make[]: *** [_module_/media/GoldenResources/arm/ARM/HelloWorld/hello] Error
make[]: Leaving directory `/usr/src/linux-headers-3.5.--generic'
make: *** [all] Error

自动使用了当前运行中的内核,构建对应的模块,但是提示找不到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.--generic/build M=`pwd` modules
make: Entering directory `/usr/src/linux-headers-3.5.--generic'
CC [M] /media/GoldenResources/arm/ARM/HelloWorld/hello/hello.o
/media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c::: warning: function declaration isn’t a prototype
/media/GoldenResources/arm/ARM/HelloWorld/hello/hello.c::: warning: function declaration isn’t a prototype
Building modules, stage .
MODPOST 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.--generic' $sudo insmod ./hello.ko # 版本不一致报错
insmod: error inserting './hello.ko': - 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/

Linux 内核源码外编译 linux模块--编译驱动模块的基本方法的更多相关文章

  1. 和菜鸟一起学linux内核源码之基础准备篇

    来源:http://blog.csdn.net/eastmoon502136/article/details/8711104 推荐阅读:linux内核源码最初版linux内核源代码,简单易懂,适合初学 ...

  2. Linux基础系列—Linux内核源码目录结构

    /** ****************************************************************************** * @author    暴走的小 ...

  3. Linux内核源码分析方法

    一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都 ...

  4. Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】

    原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://bl ...

  5. 【转】Linux内核源码分析方法

    一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都 ...

  6. Linux内核源码分析方法_转

    Linux内核源码分析方法 转自:http://www.cnblogs.com/fanzhidongyzby/archive/2013/03/20/2970624.html 一.内核源码之我见 Lin ...

  7. linux内核源码注解

    轻松学习Linux操作系统内核源码的方法 针对好多Linux 爱好者对内核很有兴趣却无从下口,本文旨在介绍一种解读linux内核源码的入门方法,而不是解说linux复杂的内核机制:一.核心源程序的文件 ...

  8. ubuntu下linux内核源码阅读工具和调试方法总结

    http://blog.chinaunix.net/uid-20940095-id-66148.html 一 linux内核源码阅读工具 windows下当然首选source insight, 但是l ...

  9. Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7)

    http://blog.chinaunix.net/uid-20543672-id-3157283.html Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3 ...

随机推荐

  1. Laravel项目的结构文章

    http://esbenp.github.io/2016/04/11/modern-rest-api-laravel-part-1/

  2. H5如何做手机app(移动Web App)?图片轮播?ionic、MUI

    移动Web App 跨平台开发 用户不需要去卖场来下载安装App 任何时候都可以发布App只需要一个开发项目 可以使用HTML5,CSS3以及JavaScript以及服务器端语言来完成(PHP,Rub ...

  3. Android compress 压缩 会不会失真

    微信的缩略图要求是不大于32k,这就需要对我的图片进行压缩.试了几种方法,一一道来. 代码如下 ByteArrayOutputStream baos = new ByteArrayOutputStre ...

  4. @Enable*注解的工作原理

    @EnableAspectJAutoProxy @EnableAsync @EnableScheduling @EnableWebMv @EnableConfigurationProperties @ ...

  5. Redis分片(分区)

    分区的概念 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集. 如果只使用一个redis实例时,其中保存了服务器中全部的缓存数据,这样会有很大风险,如果单台redis服 ...

  6. HDU 4745 Two Rabbits (区间DP)

    题意: 两只兔子,在一个由n块石头围成的环上跳跃,每块石头有一个权值ai.开始时两兔站在同一石头上(也算跳1次),一只从左往右跳,一只从右往左跳,两只同时跳,而每跳一次,两只兔子所站的石头的权值都要相 ...

  7. java Vamei快速教程17 多线程

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 多线程 多线程(multiple thread)是计算机实现多任务并行处理的一种方 ...

  8. IOS - (id)initWithStyle... 方法的使用

    // 该方法只有在通过代码创建控件的时候才会调用, 如果控件是通过xib或者storyboard创建出来的不会调用该方法- (id)initWithStyle:(UITableViewCellStyl ...

  9. URL Schemes 不能识别和不能跳转的原因

    在app跳转的过程中 需要设置url schemes后,但是设置完后,却不能识别, (测试方式:URL scheme + ://)在浏览器中打开,如果能打开app,就是能跳转 今天遇到了一个坑爹的问题 ...

  10. python_18_三元运算

    # result=值1 if 条件 else 值2 如果条件为真:result=值1,否则result=值2. a,b,c=1,3,5 d=a if b>c else c print(d)