嵌入式Linux内核模块的配置与编译
一、简介
随着 Linux操作系统在嵌入式领域的快速发展,越来越多的人开始投身到这方面的开发中来。但是,面对庞大的Linux内核源代码,开发者如何开始自己的开发工作,在完成自己的代码后,该如何编译测试,以及如何将自己的代码编译进内核中,所有的这些问题都直接和Linux的驱动的编译以及Linux的内核配置系统相关。
内核模块是一些在操作系统内核需要时载入和执行的代码,它们扩展了操作系统内核的功能却不需要重新启动系统,在不需要时可以被操作系统卸载,又节约了系统的资源占用。设备驱动程序模块就是一种内核模块,它们可以用来让操作系统正确识别和使用使用安装在系统上的硬件设备。
全肉动漫
Linux内核是由分布在全球的Linux爱好者共同开发的,为了方便开发者修改内核,Linux的内核采用了模块化的内核配置系统,从而保证内核扩展的简单与方便。
本文通过一个简单的示例,首先介绍了如何在Linux下编译出一个内核模块,然后介绍了Li
nux内核中的配置系统,讲述了如何将一个自定义的模块作为系统源码的一部分编译出新的操作系统,注意,在这里我们介绍的内容均在内核2.6.13.2(也是笔者的开发平台的版本)上编译运行通过,在2.6.*的版本上基本上是可以通用的。
二、单独编译内核模块
首先,我们先来写一个最简单的内核模块:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "RF"
#define DRIVER_DESC "just for test"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
staticintrfmodule_init(void)
{
printk("hello,world:modele_init");
return 0;
}
static void rfmodule_exit(void)
{
printk("hello,world:modele_exit");
}
module_init (rfmodule_init);
module_exit (rfmodule_exit);
这个内核模块除了在载入和卸载的时候打印2条信息之外,没有任何其他功能,不过,对于我们这个编译的例子来讲,已经足够了。
将上述源代码保存到一个test.c文件中,然后开始我们的内核模块的编译工作。
内核模块的编译与普通应用程序的编译一样,也使用的GCC,但是内核模块在用GCC编
译的时候时需要使用特定的参数并定义一些宏。 这是因为在编译普通应用程序的可执行文件和内核模块时,内核头文件起的作用是不同的。在以往的内核版本需要我们去在Makefile中手动设置这些设定,虽然这些Makefile都是按目录分层次存放的,但使用维护起来还是比较伏在。幸运的是,一种称为kbuild的新方法被引入,现在外部的可加载内核模块的编译的方法已经同内核编译统一起来,编译新的内核模块或者将自己的内核模块集成到内核源码中都已经变得非常简单了。
现在让我们看一下如何编译一个名字叫做test.c的模块。
首先,我们需要写一个简单的Makefile文件:
obj-m += test.o
将test.c和Makefile文件放在同一个目录下,然后就可以开始编译了,使用编译命令:
make -C /usr/src/linux-2.6.13.2/ SUBDIRS=$PWD modules
回车后,也许你会发现有一堆的报错,请检查如下配置是否正确:
1、在/usr/src/下有无放置你需要使用的内核源码树?如果没有,请上网down一个你需要的内核源码版本,解压后放在这里。
2、如果你已经将内核源码解压在/usr/src/下了,那么请先使用在内核源码的主目录下,在笔者的系统中就是/usr/src/linux-2.6.13.2/,使用:
make config或者make menuconfig或者make gconfig等命令来配置内核,然后使用make all将整个内核完整编译一次。
3、上述命令中的linux-2.6.13.2是笔者使用的内核源码的目录名,你需要将它改成你自己使用对应版本的的内核源码的目录名。
经过上述三步,一般来将,该内核模块都可以编译通过了,生成的test.ko就是我们需要的内核模块的最终版本,你可以使用:
insmod ./test.ko将该模块载入系统。
请注意:如果想将模块载入系统,请保证编译模块使用的内核源码的版本与要载入的系
统的版本一致!否则无法载入!
嵌入式开发实作(Linux内核编译及安装)
部分内容译自《Embedded Linux kernel and driver development 》by Michael Opdenacker
刘建文(blog.csdn/keminlau )
KEY:Linux内核编译内核配置嵌入式
内核配置(Kernel configuration)
不平则鸣2Makefile版本修改
为了区别基于同一源码构建(bulid)的不内核镜像,可使用变量EXTRAVERSION(定义位于makefile的顶部):
自己事情自己做VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 7
EXTRAVERSION = -acme1
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 7 学习烤鱼
EXTRAVERSION = -acme1
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 7
EXTRAVERSION = -acme1
运行“uname --r”会返回: 2.6.7--acme1
2.内核配置
先定义内核需要什么特性,并进行配置。内核构建系统(The kernel build system)远不是简单用来构建整个内核和模块,想了解更多的高级内核构建选项,你可以查看 Documentation/kbuild目录内的内核文档。
马拉松路线图>孤立无助可用的配置命令和方式:
makexconfig
makemenuconfig
makeoldconfig
或者手动编写
内核编译的配置文件.config与内核配置的makefile?
内核配置文件(Makefile语法的)保存为内核源代码的顶层目录的.config文件。发行版的内核配置文件通常在/boot/内。
命令:makexconfig
qconf: 全新的基于QT的配置接口,2.6版本内核
更易使用(切记阅读 help -> introduction: uful options!)
具有文件浏览功能,更易的加载配置文件
命令:makemenuconfig
老式字符界面,依然很管用。你够自信,完全可以手写配置文件!
命令:makeoldconfig
用于升级早期发布内核的配置文件
对一些绝对符号(obsolete symbols)发出警告
询问新符号的配置值
何为makefile?
makefile包含用以构建应用程序的一组规则集(t of rules)。并且第一条[规则 ]是特殊的[规则 ],叫[默认规则 ](default rule)。一条[规则]由三部分组成:目标(target)、前提条件(prerequisites)和命令动作(command):
target: prereq1 prereq2
<tab>commands
target: prereq1 prereq2
<tab>commands
target: prereq1 prereq2
<tab>commands
[目标]是被构建(made)的[文件 ]或其它东西。[前提条件 ]或者叫依赖(dependents)构建目标的“材料”。而[命令动作]是利用[前提条件]构建[目标]的shell命令。
以下是编译C源码的规则例子:桃花怎么写
foo.o: foo.cfoo.h
lt;tab>gcc -c foo.c
foo.o: foo.cfoo.h
lt;tab>gcc -c foo.c
foo.o: foo.cfoo.h
<tab>gcc -c foo.c
注意格式,冒号前是[目标],后是[前提条件];[命令]在第二行,并且开始于一个tab字符。
编译内核
编译和安装内核
编译步骤:
$ cd /usr/src/linux2. 6
$ make
$ cd /usr/src/linux2.6
$ make
$ cd /usr/src/linux2.6
$ make
安装步骤 (logged as root!)
$ make install
$ make modules_install
$ make install
$ make modules_install
$ make install
$ make modules_install
以下的步骤在2.6版本不再使用:
$ make depends
$ make modules (done by make)
$ make depends
周记400
$ make modules (done by make)
$ make depends
$ make modules (done by make)
提升编译速度
多花一些时间在内核配置上,并且只编译那些你硬件需要的模块。这样可以把编译时间缩短为原来的1/30,并且节省数百MB的空间。另外,你还可以并行编译多个文件: