admin 管理员组文章数量: 1086019
2024年6月7日发(作者:unicode 解码)
嵌入式Linux内核模块的配置与编译
一、简介
随着 Linux操作系统在嵌入式领域的快速发展,越来越多的人开始投身到
这方面的开发中来。但是,面对庞大的Linux内核源代码,开发者如何开始自己
的开发工作,在完成自己的代码后,该如何编译测试,以及如何将自己的代码编
译进内核中,所有的这些问题都直接和Linux的驱动的编译以及Linux的内核配
置系统相关。
内核模块是一些在操作系统内核需要时载入和执行的代码,它们扩展了操作
系统内核的功能却不需要重新启动系统,在不需要时可以被操作系统卸载,又节
约了系统的资源占用。设备驱动程序模块就是一种内核模块,它们可以用来让操
作系统正确识别和使用使用安装在系统上的硬件设备。
Linux内核是由分布在全球的Linux爱好者共同开发的,为了方便开发者修
改内核,Linux的内核采用了模块化的内核配置系统,从而保证内核扩展的简单
与方便。
本文通过一个简单的示例,首先介绍了如何在Linux下编译出一个内核模块,
然后介绍了Linux内核中的配置系统,讲述了如何将一个自定义的模块作为系统
源码的一部分编译出新的操作系统,注意,在这里我们介绍的内容均在内核
2.6.13.2(也是笔者的开发平台的版本)上编译运行通过,在2.6.*的版本上基
本上是可以通用的。
二、单独编译内核模块
首先,我们先来写一个最简单的内核模块:
#include
#include
#include
#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是笔者使用的内核源码的目录名,你需要
将它改成你自己使用对应版本的的内核源码的目录名。
经过上述三步,一般来将,该内核模块都可以编译通过了,生成的
就是我们需要的内核模块的最终版本,你可以使用:
insmod ./将该模块载入系统。
请注意:如果想将模块载入系统,请保证编译模块使用的内核源码的版本与
要载入的系统的版本一致!否则无法载入!
嵌入式开发实作(Linux内核编译及安装)
部分内容译自《Embedded Linux kernel and driver development 》by Michael Opdenacker
刘建文(/keminlau )
KEY:Linux内核编译内核配置嵌入式
内核配置(Kernel configuration)
Makefile版本修改
为了区别基于同一源码构建(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: useful options!)
具有文件浏览功能,更易的加载配置文件
命令:makemenuconfig
老式字符界面,依然很管用。你够自信,完全可以手写配置文件!
命令:makeoldconfig
用于升级早期发布内核的配置文件
对一些绝对符号(obsolete symbols)发出警告
询问新符号的配置值
何为makefile?
makefile包含用以构建应用程序的一组规则集(set of rules)。并且第一条[规则 ]是特殊的[规
则 ],叫[默认规则 ](default rule)。一条[规则]由三部分组成:目标(target)、前提条件
(prerequisites)和命令动作(command):
target: prereq1 prereq2
target: prereq1 prereq2
target: prereq1 prereq2
[目标]是被构建(made)的[文件 ]或其它东西。[前提条件 ]或者叫依赖(dependents)构建
目标的“材料”。而[命令动作]是利用[前提条件]构建[目标]的shell命令。
以下是编译C源码的规则例子:
foo.o: .h
lt;tab>gcc -c foo.c
foo.o: .h
lt;tab>gcc -c foo.c
foo.o: .h
注意格式,冒号前是[目标],后是[前提条件];[命令]在第二行,并且开始于一个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
$ make modules (done by make)
$ make depends
$ make modules (done by make)
提升编译速度
多花一些时间在内核配置上,并且只编译那些你硬件需要的模块。这样可以把编译时间缩短
为原来的1/30,并且节省数百MB的空间。另外,你还可以并行编译多个文件:
$ make -j
make 可以并行执行多个目标(target)(KEMIN:前提是目标规则间没有交叉依赖项,这个怎
么做到的?)
$ make -j 4
即便是在单处理器的工作站上也会很快,读写文件的时间被节省下来了。多线程让CPU保
持忙碌。
number大于4不见得有效了,因为上下文切换过多反而降低的工作的速度。
make -j <4*number_of_processors>
内核编译tips
查看完整的 (gcc, ld)命令行: $ make V=1
清理所有的生成文件 (to ): $ make mrproper
部分编译:$ make M=drivers/usb/serial
单独模块编译:$ make drivers/usb/serial/
别处编译(假设源码在CDROM):
$ cd /mnt/cdrom/linux-2.6.17.11
$ make O=~/linux/linux-2.6.17.11
最终生成的文件
vmlinux原始内核镜像,非压缩的
arch/
arch/
image on i386)
安装的文件
/boot/vmlinuz-
/boot/-
/boot/initrd-
块。安装命令“make install”为替你运行“mkinitrd”生成initrd;
/etc/ or /etc/
bootloader的配置文件:“make install”会为你的新内核更新相应的bootloader的配置文件。
如果你使用的是LILO,它会在生成配置文件后,执行/sbin/lilo,让LILO的配置生效。
/lib/modules/
build/
为本
information (build/s), kernel headers (build/include/)
kernel/
内核模块文件 .ko (Kernel Object),目录结构与源代码目标一一对应。
模块别名记录(用于insmod和modprobe),例如:
alias sound--service--?-0 snd_mixer_oss
模块依赖记录(用于insmod和modprobe)
s
标识某符号是属于哪个模块的。
这个目录的所有文件都是文本文件,可以直接查看。
小结编译及安装步骤:
编辑Makefile版本信息
定义内核特性,生成配置文件.config,用于编译:makexconfig
编译内核:make
安装内核:make install
安装模块:makemodules_install
交叉编译内核
Makefile修改
通常通过修改已有的makefile获得
你必须修改目标平台,假设目标平台是ARM,修改以下:
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
或运行带参数的make:
$ cd /usr/scr/linuxXX
$ make ARCH=arm CROSS_COMPILE=arm-linux-
$ cd /usr/scr/linuxXX
$ make ARCH=arm CROSS_COMPILE=arm-linux-
$ cd /usr/scr/linuxXX
$ make ARCH=arm CROSS_COMPILE=arm-linux-
内核配置文件
配置过程和本地配置一样;可以把生成的配置文件(.config)分享给其他人,比如像:
$
$ cp .config arch/
$
$ cp .config arch/
$
$ cp .config arch/
这样其他同样开发ACME系统的开发人员可以通过以下命令编译出同样的内核:
$ make acme_defconfig
$
$ make acme_defconfig
$
$ make acme_defconfig
$
建立交叉编译环境(Cross--compiling setup)
假设你有ARM的交叉编译工具(cross--compiling toolchain)在 in /usr/local/arm/3.3.2/,你
得把它输出到PATH:
$ export PATH=/usr/local/arm/ 3.3 . 2 /bin:$PATH
$ export PATH=/usr/local/arm/3.3.2/bin:$PATH
$ export PATH=/usr/local/arm/3.3.2/bin:$PATH
注意查看内核文档(在Documentation/Changes)有关最低工具版本要求。
编译并安装内核
1. $ make //如果你修改了Makefile
或者
1'. $ make ARCH=arm CROSS_COMPILE=arm-linux-
2. 拷贝 arch/
$ make modules_install
3. 拷贝 /lib/modules/
你可以通过 arch/
何为交叉编译工具链(cross--compiling toolchain)?
有如任何其它开发活动一般,嵌入式开发的第一步是建立(setting up)用于构建嵌入式Linux
内核(当然包括驱动程序)及应用程序的工具链(toolchains)。不过,嵌入式开发需要是跨
平台工具链。跨平台是什么意思呢?一般开发活动是在本地编译,使用是本地的工具链;而
由于嵌入式的软硬资源(内存不足、没有本地编译器或操作系统都没有)限制等没法进行本
地开发。需要在Linux-x86 主机(HOST)开发,使用主机的编译器生成目标(TARGET)平台
代码,这个过程叫交叉编译。
我们常常说的编译器有广义和狭义之分。狭义的编译器只完软件编译(或者叫软件构建)的
第一步;广义的编译器包括了软件编译(或者叫软件构建)所需要代码库(比如libc)和其
它构建工具(比如汇编器和连接器)。无论是什么编译器都需要支持的代码库和各种构建工
具,交叉编译也不例外。一整套广义的编译器称为交叉编译工具链。
何为工具链?
In software, a toolchain is the set of computer programs (tools) that are used to create a product
(typically another computer program or system of programs). The tools may be used in a chain,
so that the output of each tool becomes the input for the next, but the term is used widely to
refer to any set of linked development tools.
A simple software development toolchain consists of a text editor for editing source code, a
compiler and linker to transform the source code into an executable program, libraries to provide
interfaces to the operating system, and a debugger.
The GNU toolchain is a blanket term for a collection of programming tools produced by the GNU
Project. These tools form a toolchain (suite of tools used in a serial manner) used for developing
applications and operating systems.
Projects included in the GNU toolchain are:
* GNU make: Automation tool for compilation and build;
* GNU Compiler Collection (GCC): Suite of compilers for several programming languages;
* GNU Binutils: Suite of tools including linker, assembler and other tools;
* GNU Bison: Parser generator
* GNU m4: m4 macro processor
* GNU Debugger (GDB): Code debugging tool;
* GNU build system (autotools):
oAutoconf
oAutoheader
oAutomake
oLibtool
参考
//2006/01/05/autotools-tutorial/
本文来自CSDN博客,转载请标明出处
/shijizhisheng/archive/2009/09/16/
:
把设备驱动程序编译进嵌入式linux内核
文章来源网络 属于linux分类 电脑编程网整理 2007107
简介:这是把设备驱动程序编译进嵌入式linux内核的详细页面,介绍了和linux,有关的知识,加入收藏
请按键盘ctrl+D,谢谢大家的观看!要查看更多有关信息,请点击此处
驱动程序的使用可以按照两种方式编译,一种是静态编译进内核,另一种是编译成模块以供动态加载。
由于uclinux不支持模块动态加载,而且嵌入式linux不能够象桌面linux那样灵活的使用insmod/rmmod加
载卸载设备驱动程序,因而这里只介绍将设备驱动程序静态编译进uclinux内核的方法。
下面以uclinux为例,介绍在一个以模块方式出现的驱动程序test.c基础之上,将其编译进内核的一
系列步骤:
(1) 改动test.c源带代码
第一步,将原来的:
#include
#include
char kernel_version[]=uts_release;
和 "把设备驱动程序编译进嵌入式linux内核" 有关的编程小帖士:
strong>session_encode
Session 资料编码。
语法: booleansession_encode(void);
返回值: 布尔值
内容说明
本函数可将 Session 资料编码,编码以 ZEND 引擎做哈稀编码。本函数没有参数。成功则返回 true 值。
改动为:
#ifdef module
#include
#include
char kernel_version[]=uts_release;
#else
#define mod_inc_use_count
#define mod_dec_use_count
#endif
第二步,新建函数intinit_test(void)
将设备注册写在此处:
result=register_chrdev(254,"test",&test_fops);
(2) 将test.c复制到/uclinux/linux/drivers/char目录下,并且在/uclinux/linux/drivers/char
目录下mem.c中,intchr_dev_init( )函数中增加如下代码:
#ifdefconfig_testdrive
init_test();
#endif
(3) 在/uclinux/cinux/drivers/char目录下makefile中增加如下代码:
ifeq($(config_testdrive),y)
l_objs+=test.o
endif
(4) 在/uclinux/linux/arch/m68knommu目录下中字符设备段里增加如下代码:
bool 'support for testdrive' config_testdrive y
(5) 运行make menuconfig(在menuconfig的字符设备选项里你可以看见我们刚刚添加的'support
for testdrive'选项,并且已经被选中);make dep;make linux;make ;make ;
>.
(6) 在 /uclinux/romdisk/romdisk/dev/目录下创建设备:
mknod test c 254 0
并且在/uclinux/appsrc/下运行make,生成新的romdisk.s19文件。
到这里,在uclinux中增加设备驱动程序的工作可以说是完成了,只要将新的与romdisk.s19
烧入目标板中,你就可以使用自己的新设备test了。
用命令行加挂linux的文件系统简介
linux中mount其他文件系统
版权声明:本文标题:嵌入式Linux内核模块的配置与编译 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/b/1717698036a711107.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论