嵌入式Linux内核模块的配置与编译.docx
- 文档编号:10834948
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:15
- 大小:22.72KB
嵌入式Linux内核模块的配置与编译.docx
《嵌入式Linux内核模块的配置与编译.docx》由会员分享,可在线阅读,更多相关《嵌入式Linux内核模块的配置与编译.docx(15页珍藏版)》请在冰豆网上搜索。
嵌入式Linux内核模块的配置与编译
嵌入式Linux内核模块的配置与编译
一、简介
随着Linux操作系统在嵌入式领域的快速发展,越来越多的人开始投身到这方面的开发中来。
但是,面对庞大的Linux内核源代码,开发者如何开始自己的开发工作,在完成自己的代码后,该如何编译测试,以及如何将自己的代码编译进内核中,所有的这些问题都直接和Linux的驱动的编译以及Linux的内核配置系统相关。
内核模块是一些在操作系统内核需要时载入和执行的代码,它们扩展了操作系统内核的功能却不需要重新启动系统,在不需要时可以被操作系统卸载,又节约了系统的资源占用。
设备驱动程序模块就是一种内核模块,它们可以用来让操作系统正确识别和使用使用安装在系统上的硬件设备。
Linux内核是由分布在全球的Linux爱好者共同开发的,为了方便开发者修改内核,Linux的内核采用了模块化的内核配置系统,从而保证内核扩展的简单与方便。
本文通过一个简单的示例,首先介绍了如何在Linux下编译出一个内核模块,然后介绍了Linux内核中的配置系统,讲述了如何将一个自定义的模块作为系统源码的一部分编译出新的操作系统,注意,在这里我们介绍的内容均在内核2.6.13.2(也是笔者的开发平台的版本)上编译运行通过,在2.6.*的版本上基本上是可以通用的。
二、单独编译内核模块
首先,我们先来写一个最简单的内核模块:
#include
#include
#include
#defineDRIVER_VERSION"v1.0"
#defineDRIVER_AUTHOR"RF"
#defineDRIVER_DESC"justfortest"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
staticintrfmodule_init(void)
{
printk("hello,world:
modele_init");
return0;
}
staticvoidrfmodule_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=$PWDmodules
回车后,也许你会发现有一堆的报错,请检查如下配置是否正确:
1、在/usr/src/下有无放置你需要使用的内核源码树?
如果没有,请上网down一个你需要的内核源码版本,解压后放在这里。
2、如果你已经将内核源码解压在/usr/src/下了,那么请先使用在内核源码的主目录下,在笔者的系统中就是/usr/src/linux-2.6.13.2/,使用:
makeconfig或者makemenuconfig或者makegconfig等命令来配置内核,然后使用makeall将整个内核完整编译一次。
3、上述命令中的linux-2.6.13.2是笔者使用的内核源码的目录名,你需要将它改成你自己使用对应版本的的内核源码的目录名。
经过上述三步,一般来将,该内核模块都可以编译通过了,生成的test.ko就是我们需要的内核模块的最终版本,你可以使用:
insmod./test.ko将该模块载入系统。
请注意:
如果想将模块载入系统,请保证编译模块使用的内核源码的版本与要载入的系统的版本一致!
否则无法载入!
嵌入式开发实作(Linux内核编译及安装)
部分内容译自《EmbeddedLinuxkernelanddriverdevelopment》byMichaelOpdenacker
刘建文()
KEY:
Linux内核编译内核配置嵌入式
内核配置(Kernelconfiguration)
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.内核配置
先定义内核需要什么特性,并进行配置。
内核构建系统(Thekernelbuildsystem)远不是简单用来构建整个内核和模块,想了解更多的高级内核构建选项,你可以查看Documentation/kbuild目录内的内核文档。
可用的配置命令和方式:
makexconfig
makemenuconfig
makeoldconfig
或者手动编写
内核编译的配置文件.config与内核配置的makefile?
内核配置文件(Makefile语法的)保存为内核源代码的顶层目录的.config文件。
发行版的内核配置文件通常在/boot/内。
命令:
makexconfig
qconf:
全新的基于QT的配置接口,2.6版本内核
更易使用(切记阅读help->introduction:
usefuloptions!
)
具有文件浏览功能,更易的加载配置文件
命令:
makemenuconfig
老式字符界面,依然很管用。
你够自信,完全可以手写配置文件!
命令:
makeoldconfig
用于升级早期发布内核的配置文件
对一些绝对符号(obsoletesymbols)发出警告
询问新符号的配置值
何为makefile?
makefile包含用以构建应用程序的一组规则集(setofrules)。
并且第一条[规则]是特殊的[规则],叫[默认规则](defaultrule)。
一条[规则]由三部分组成:
目标(target)、前提条件(prerequisites)和命令动作(command):
target:
prereq1prereq2
target:
prereq1prereq2
target:
prereq1prereq2
[目标]是被构建(made)的[文件]或其它东西。
[前提条件]或者叫依赖(dependents)构建目标的“材料”。
而[命令动作]是利用[前提条件]构建[目标]的shell命令。
以下是编译C源码的规则例子:
foo.o:
foo.cfoo.h
lt;tab>gcc-cfoo.c
foo.o:
foo.cfoo.h
lt;tab>gcc-cfoo.c
foo.o:
foo.cfoo.h
注意格式,冒号前是[目标],后是[前提条件];[命令]在第二行,并且开始于一个tab字符。
编译内核
编译和安装内核
编译步骤:
$cd/usr/src/linux2.6
$make
$cd/usr/src/linux2.6
$make
$cd/usr/src/linux2.6
$make
安装步骤(loggedasroot!
)
$makeinstall
$makemodules_install
$makeinstall
$makemodules_install
$makeinstall
$makemodules_install
以下的步骤在2.6版本不再使用:
$makedepends
$makemodules(donebymake)
$makedepends
$makemodules(donebymake)
$makedepends
$makemodules(donebymake)
提升编译速度
多花一些时间在内核配置上,并且只编译那些你硬件需要的模块。
这样可以把编译时间缩短为原来的1/30,并且节省数百MB的空间。
另外,你还可以并行编译多个文件:
$make-j
make可以并行执行多个目标(target)(KEMIN:
前提是目标规则间没有交叉依赖项,这个怎么做到的?
)
$make-j4
即便是在单处理器的工作站上也会很快,读写文件的时间被节省下来了。
多线程让CPU保持忙碌。
number大于4不见得有效了,因为上下文切换过多反而降低的工作的速度。
make-j<4*number_of_processors>
内核编译tips
查看完整的(gcc,ld)命令行:
$makeV=1
清理所有的生成文件(tocreatepatches...):
$makemrproper
部分编译:
$makeM=drivers/usb/serial
单独模块编译:
$makedrivers/usb/serial/visor.ko
别处编译(假设源码在CDROM):
$cd/mnt/cdrom/linux-2.6.17.11
$makeO=~/linux/linux-2.6.17.11
最终生成的文件
vmlinux原始内核镜像,非压缩的
arch/
arch/
通常很小,足够放入一张软盘(Defaultimageoni386)
安装的文件
/boot/vmlinuz-
/boot/System.map-
/boot/initrd-
保存有你需要在引导时挂接最终根文件系统的模块。
安装命令“makeinstall”为替你运行“mkinitrd”生成initrd;
/etc/grub.confor/etc/lilo.conf
bootloader的配置文件:
“makeinstall”会为你的新内核更新相应的bootloader的配置文件。
如果你使用的是LILO,它会在生成配置文件后,执行/sbin/lilo,让LILO的配置生效。
/lib/modules/
build/
为本
.configfile(build/.config),modulesymbolinformation(build/module.symVers),kernelheaders(build/include/)
kernel/
内核模块文件.ko(KernelObject),目录结构与源代码目标一一对应。
modules.alias
模块别名记录(用于insmod和modprobe),例如:
aliassound--service--?
-0snd_mixer_oss
modules.dep
模块依赖记录(用于insmod和modprobe)
modules.symbols
标识某符号是属于哪个模块的。
这个目录的所有文件都是文本文件,可以直接查看。
小结编译及安装步骤:
编辑Makefile版本信息
定义内核特性,生成配置文件.config,用于编译:
makexconfig
编译内核:
make
安装内核:
makeinstall
安装模块:
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
$makeARCH=armCROSS_COMPILE=arm-linux-
$cd/usr/scr/linuxXX
$makeARCH=armCROSS_COMPILE=arm-linux-
$cd/usr/scr/linuxXX
$makeARCH=armCROSS_COMPILE=arm-linux-
内核配置文件
配置过程和本地配置一样;可以把生成的配置文件(.config)分享给其他人,比如像:
$
$cp.configarch/
$
$cp.configarch/
$
$cp.configarch/
这样其他同样开发ACME系统的开发人员可以通过以下命令编译出同样的内核:
$makeacme_defconfig
$
$makeacme_defconfig
$
$makeacme_defconfig
$
建立交叉编译环境(Cross--compilingsetup)
假设你有ARM的交叉编译工具(cross--compilingtoolchain)在in/usr/local/arm/3.3.2/,你得把它输出到PATH:
$exportPATH=/usr/local/arm/3.3.2/bin:
$PATH
$exportPATH=/usr/local/arm/3.3.2/bin:
$PATH
$exportPATH=/usr/local/arm/3.3.2/bin:
$PATH
注意查看内核文档(在Documentation/Changes)有关最低工具版本要求。
编译并安装内核
1.$make//如果你修改了Makefile
或者
1'.$makeARCH=armCROSS_COMPILE=arm-linux-
2.拷贝arch/
$makemodules_install
3.拷贝/lib/modules/
你可以通过arch/
何为交叉编译工具链(cross--compilingtoolchain)?
有如任何其它开发活动一般,嵌入式开发的第一步是建立(settingup)用于构建嵌入式Linux内核(当然包括驱动程序)及应用程序的工具链(toolchains)。
不过,嵌入式开发需要是跨平台工具链。
跨平台是什么意思呢?
一般开发活动是在本地编译,使用是本地的工具链;而由于嵌入式的软硬资源(内存不足、没有本地编译器或操作系统都没有)限制等没法进行本地开发。
需要在Linux-x86主机(HOST)开发,使用主机的编译器生成目标(TARGET)平台代码,这个过程叫交叉编译。
我们常常说的编译器有广义和狭义之分。
狭义的编译器只完软件编译(或者叫软件构建)的第一步;广义的编译器包括了软件编译(或者叫软件构建)所需要代码库(比如libc)和其它构建工具(比如汇编器和连接器)。
无论是什么编译器都需要支持的代码库和各种构建工具,交叉编译也不例外。
一整套广义的编译器称为交叉编译工具链。
何为工具链?
Insoftware,atoolchainisthesetofcomputerprograms(tools)thatareusedtocreateaproduct(typicallyanothercomputerprogramorsystemofprograms).Thetoolsmaybeusedinachain,sothattheoutputofeachtoolbecomestheinputforthenext,butthetermisusedwidelytorefertoanysetoflinkeddevelopmenttools.
Asimplesoftwaredevelopmenttoolchainconsistsofatexteditorforeditingsourcecode,acompilerandlinkertotransformthesourcecodeintoanexecutableprogram,librariestoprovideinterfacestotheoperatingsystem,andadebugger.
TheGNUtoolchainisablankettermforacollectionofprogrammingtoolsproducedbytheGNUProject.Thesetoolsformatoolchain(suiteoftoolsusedinaserialmanner)usedfordevelopingapplicationsandoperatingsystems.
ProjectsincludedintheGNUtoolchainare:
*GNUmake:
Automationtoolforcompilationandbuild;
*GNUCompilerCollection(GCC):
Suiteofcompilersforseveralprogramminglanguages;
*GNUBinutils:
Suiteoftoolsincludinglinker,assemblerandothertools;
*GNUBison:
Parsergenerator
*GNUm4:
m4macroprocessor
*GNUDebugger(GDB):
Codedebuggingtool;
*GNUbuildsystem(autotools):
oAutoconf
oAutoheader
oAutomake
oLibtool
参考
本文来自CSDN博客,转载请标明出处:
把设备驱动程序编译进嵌入式linux内核
文章来源网络 属于linux分类 电脑编程网整理 2007107
简介:
这是把设备驱动程序编译进嵌入式linux内核的详细页面,介绍了和linux,有关的知识,加入收藏请按键盘ctrl+D,谢谢大家的观看!
要查看更多有关信息,请点击此处
驱动程序的使用可以按照两种方式编译,一种是静态编译进内核,另一种是编译成模块以供动态加载。
由于uclinux不支持模块动态加载,而且嵌入式linux不能够象桌面linux那样灵活的使用insmod/rmmod加载卸载设备驱动程序,因而这里只介绍将设备驱动程序静态编译进uclinux内核的方法。
下面以uclinux为例,介绍在一个以模块方式出现的驱动程序test.c基础之上,将其编译进内核的一系列步骤:
(1)改动test.c源带代码
第一步,将原来的:
#include
#include
charkernel_version[]=uts_release;
和 "把设备驱动程序编译进嵌入式linux内核" 有关的编程小帖士:
strong>session_encode
Session资料编码。
语法:
booleansession_encode(void);
返回值:
布尔值
内容说明
本函数可将Session资料编码,编码以ZEND引擎做哈稀编码。
本函数没有参数。
成功则返回true值。
改动为:
#ifdefmodule
#include
#include
charkernel_version[]=uts_release;
#else
#definemod_inc_use_count
#definemod_dec_use_count
#endif
第二步,新建函数intinit_test(void)
将设备注册写在此处:
result=re
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 Linux 内核 模块 配置 编译