《linux2.6内核的编译步骤及模块的动态加载-内核源码学习-linux论坛.docx》由会员分享,可在线阅读,更多相关《linux2.6内核的编译步骤及模块的动态加载-内核源码学习-linux论坛.docx(10页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、linux2.6内核的编译步骤及模块的动态加载-内核源码学习-linux论坛 原创linux2.6内核的编译步骤及模块的动态加载-内核源码学习-linux论坛05年本科毕业设计做的是Linux下驱动的分析,当时就买了一本(Linux设备驱动程序第二版),但是没有实现将最简单的helloworld程序编译成模块,加载到kernel里。不过,如今本人确实打算做一款芯片的Linux的驱动,因而,又开场看了(Linux设备驱动程序)这本书,不过已经是第三版了。第二版讲的是2.4的内核,第三版讲的是2.6的内核。两个内核版本之间关于编译内核以及加载模块的方法都有所变化。本文是基于2.6的内核,也建议各位
2、能够先看一下(Linux内核设计与实现第二版)作为一个基础知识的铺垫。当然,从实践角度来看,只要按着下面的步骤去做也应该能够实现成功编译内核及加载模块。个人用的Linux版本为:DebianGNU/Linux,内核版本为:2.6.20-1-686.第一步,下载Linux内核的源代码,即构建LDD3LinuxDeviceDrivers3rd上面所讲的内核树。如过安装的Linux系统中已经自带了源代码的话,应该在/usr/src目录下。假如该目录为空的话,则需要本人手动下载源代码。下载代码的方法和链接很多,可以以在CU上通过httpdocsj/doc/29cc6e95d05abe23482fb4d
3、aa58da0116c171fcb./search/?key=q=kernelfrmid=53去下载。不过,下载的内核版本最好和所运行的Linux系统的内核版本一致。当然,可以以比Linux系统内核的版本低,但高的话应该不行个人尚未实践。Debian下能够很方便的通过Debian源下载:首先查找一下可下载的内核源代码:#apt-cachesearchlinux-source其中显示的有:linux-source-2.6.20,没有和我的内核版本完全匹配,不过也没关系,直接下载就能够了:#apt-getinstalllinux-source-2.6.20下载完成后,安装在/usr/src下,文件
4、名为:linux-source-2.6.20.tar.bz2,是一个压缩包,解压缩既能够得到整个内核的源代码:#tarjxvflinux-source-2.6.20.tar.bz2解压后生成一个新的目录/usr/src/linux-source-2.6.20,所有的源代码都在该目录下。注:该目录会因内核版本的不同而不同,各位动手实践的朋友只需知道本人的源代码所在的详细位置即可。第二步:配置及编译内核。进入/usr/src/linux-source-2.6.20目录下,能够看到Makefile文件,它包含了整个内核树编译信息。该文件最上面四行是关于内核版本的信息。对于整个Makefile能够不用
5、做修改,采用默认的就能够了。一般情况下,需要先用命令诸如makemenuconfig,makexconfig或者makeoldcofig对内核进行配置,这几个都是对内核进行配置的命令,只是它们运行的环境不一样,执行一下这几个命令中的任何一个即可对内核进行配置:makemenuconfig是基于界面的内核配置方法,makexconfig应该是基于QT库的,还有makegcofig也是基于图形的配置方法,应该是需要GTK的环境,makeoldcofig就是对内核树原有的.config文件进行配置一下即可。其实内核的配置部分,主要是保证内核启动模块可动态加载的配置,默认配置里面应该已经包含了这样的内
6、容,因而,我用的是makeoldconfig.内核的具体配置请见另外一位网友的帖子,这里给出链接:httpdocsj/doc/29cc6e95d05abe23482fb4daa58da0116c171fcb./bbs/viewthread.php?tid=885597extra=page%3D1%26amp%3Bfilter%3Ddigest在内核源码的目录下执行:#make#makebzImage其中,第一个make可以以不执行,直接makebzImage。这个经过可能要持续一个小时左右,因而是对整个内核重新编译了。执行结束后,能够看到在当前目录下生成了一个新的文件:vmlinux,其属性为
7、-rwxr-xr-x。然后执行:#makemodules#makemodules_install对内核的所有模块进行编译和安装。执行结束之后,会在/lib/modules下生成新的目录/lib/modules/2.6.20/。在随后的编译模块文件时,要用到这个途径下的build目录。至此,内核编译完成。能够重启一下系统。第三步:编写模块文件及Makefile以LDD3上的hello.c为例:/hello.c#includelinux/init.h#includelinux/module.hMODULE_LICENSE(DualBSD/GPL);staticinthello_init(void)
8、printk(KERN_ALERTHello,worldn);return0;staticvoidhello_exit(void)printk(KERN_ALERTGoodbye,cruelworldn);module_init(hello_init);module_exit(hello_exit);Makefile文件的内容为:obj-m:=hello.oKERNELDIR:=/lib/modules/2.6.20/buildPWD:=$(shellpwd)modules:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulesmodules_install:$(MAKE)-
9、C$(KERNELDIR)M=$(PWD)modules_installclean:rm-rf*.o*core.depend.*d*.ko*.mod.c.tmp_versions其中,hello.c和Makefile文件应该位于同一个目录下,能够放在/home下,我的两个文件都位于/home/david/.第四步:编译和装载模块在文件所处的目录下,执行:debian:/home/david#make然后查看该目录下有哪些文件生成:debian:/home/david#ls-l总计28drwxr-xr-x2daviddavid40962007-02-0717:49Desktop-rw-r-r-1
10、daviddavid4622007-07-2013:42hello.c-rw-r-r-1rootroot24322007-07-2013:55hello.ko-rw-r-r-1rootroot6072007-07-2013:55hello.mod.c-rw-r-r-1rootroot19682007-07-2013:55hello.mod.o-rw-r-r-1rootroot11402007-07-2013:55hello.o-rw-r-r-1daviddavid2672007-07-2013:48Makefile-rw-r-r-1rootroot02007-07-0514:11Module.
11、symvers可见,已经生成模块文件hello.ko.然后,就能够加载该模块:debian:/home/david#insmodhello.ko查看模块能否加载进内核:debian:/home/david#lsmodModuleSizeUsedbyhello13440nfs2194680nfsd20222417.其中Module名为hello的即为我们所加载的模块.卸载模块:debian:/home/david#rmmodhello同样能够通过lsmod来查看该模块能否被卸载.这里有两个问题,其一就是printk()输出的问题.LDD3上也讲,在加载和卸载模块的时候都会有信息输出在屏幕上,假如
12、通过终端仿真器(,则在屏幕上看不到任何输出.我同时在虚拟机和和物理机都运行了该模块,均未看到有Hello,world(加载模块时printk的输出)或Goodby,cruelworld(卸载模块时printk的输出).这个不知道是我操作系统发行版的原因还是系统配置的问题,请了解这个问题的朋友指点一下.其二,书上讲到假如屏幕上看不到信息,可能输出在某个日志文件里面了,并讲可能在/var/log/messages文件中.并且看到网上很多网友也讲是输出到这个文件里面.我不知道有没有发现输出在其他日志文件里的,不过我的这个信息输出在/var/log/syslog里面.在加载和卸载完该模块后,执行命令:
13、debian:/home/david#cat/var/log/syslog|grepworld能够看到有两行内容.当然,可以以不用grepworld,应该会出如今最后两行.Jul2014:15:29localhostkernel:Hello,worldJul2014:15:34localhostkernel:Goodbye,cruelworld这就是printk应该输出的信息.这里有另外一个方法,能够实现printk的信息输出在屏幕上,即更改printk输出的优先级.例子中的优先级为:KERN_ALERT,优先级为1,假如将优先级改为KERN_EMERG即0,则能够看到屏幕的输出信息.修改的方
14、法只是修改一下hello.c中两句printk()的内容,修改后的hello.c如下:#includelinux/init.h#includelinux/module.hMODULE_LICENSE(DualBSD/GPL);staticinthello_init(void)printk(KERN_EMERGHello,worldn);/*改动部分*/return0;staticvoidhello_exit(void)printk(KERN_EMERGGoodbye,cruelworldn);/*改动部分*/module_init(hello_init);module_exit(hello_exit);同样的方法编译生成模块,再次用insmod和rmmod,则在屏幕上看到的输出信息为:debian:/home/david#insmodhello.kodebian:/home/david#MessagefromsyslogdlocalhostatFriJul2014:27:322007.