本文是基于2.6
![](/icons/50781de.gif)
内核
![](/icons/50781dou.gif)
也建议各位可以先看
![](/icons/50781yi.gif)
下
![](/icons/50781smhl.gif)
Linux内核设计和实现(第 2版)
![](/icons/50781smhr.gif)
作为
![](/icons/50781yi.gif)
个基础知识
![](/icons/50781de.gif)
铺垫
![](/icons/50781dou2.gif)
当然
![](/icons/50781dou.gif)
从实战角度来看
![](/icons/50781dou.gif)
只要按着以下
![](/icons/50781de.gif)
步骤去做也应该可以实现成功编译内核及加载模块
![](/icons/50781dou2.gif)
个人用
![](/icons/50781de.gif)
Linux版本为:Debian GNU/Linux
![](/icons/50781dou.gif)
内核版本为:2.6.20-1-686.
第
![](/icons/50781yi.gif)
步
![](/icons/50781dou.gif)
Linux内核
![](/icons/50781de.gif)
源代码
![](/icons/50781dou.gif)
即构建LDD3(Linux Device Drivers 3rd)上面所说
![](/icons/50781de.gif)
内核树
![](/icons/50781dou2.gif)
如过安装
![](/icons/50781de.gif)
Linux系统中已经自带了源代码
![](/icons/50781de.gif)
话
![](/icons/50781dou.gif)
应该在/usr/src目录下
![](/icons/50781dou2.gif)
如果该目录为空
![](/icons/50781de.gif)
话
![](/icons/50781dou.gif)
则需要自己手动源代码
![](/icons/50781dou2.gif)
代码
![](/icons/50781de.gif)
思路方法和链接很多
![](/icons/50781dou.gif)
也可以在CU上通过去下载
![](/icons/50781dou2.gif)
不过
![](/icons/50781dou.gif)
下载
![](/icons/50781de.gif)
内核版本最好和所运行
![](/icons/50781de.gif)
Linux系统
![](/icons/50781de.gif)
内核版本
![](/icons/50781yi.gif)
致
![](/icons/50781dou2.gif)
当然
![](/icons/50781dou.gif)
也可以比Linux系统内核
![](/icons/50781de.gif)
版本低
![](/icons/50781dou.gif)
但高
![](/icons/50781de.gif)
话应该不行(个人尚未实战)
![](/icons/50781dou2.gif)
Debian下可以很方便
![](/icons/50781de.gif)
通过Debian源下载:
首先查找
![](/icons/50781yi.gif)
下可下载
![](/icons/50781de.gif)
内核源代码:
# apt-cache search -source
其中显示
![](/icons/50781de.gif)
有:-source-2.6.20,没有和我
![](/icons/50781de.gif)
内核版本完全匹配
![](/icons/50781dou.gif)
不过也没关系
![](/icons/50781dou.gif)
直接下载就可以了:
# apt-get
![](/icons/50781install.gif)
linux-source-2.6.20
下载完成后
![](/icons/50781dou.gif)
安装在/usr/src下
![](/icons/50781dou.gif)
文件名为:linux-source-2.6.20.tar.bz2,是
![](/icons/50781yi.gif)
个压缩包
![](/icons/50781dou.gif)
解压缩既可以得到整个内核
![](/icons/50781de.gif)
源代码:
# tar jxvf linux-source-2.6.20.tar.bz2
解压后生成
![](/icons/50781yi.gif)
个新
![](/icons/50781de.gif)
目录/usr/src/linux——source-2.6.20
![](/icons/50781dou.gif)
所有
![](/icons/50781de.gif)
源代码都在该目录下
![](/icons/50781dou2.gif)
注:该目录会因内核版本
![](/icons/50781de.gif)
区别而区别
![](/icons/50781dou.gif)
各位动手实战
![](/icons/50781de.gif)
朋友只需知道自己
![](/icons/50781de.gif)
源代码所在
![](/icons/50781de.gif)
具体位置即可
![](/icons/50781dou2.gif)
第 2步:配置及编译内核
![](/icons/50781dou2.gif)
进入/usr/src/linux——source-2.6.20目录下
![](/icons/50781dou.gif)
可以看到Makefile文件
![](/icons/50781dou.gif)
它包含了整个内核树编译信息
![](/icons/50781dou2.gif)
该文件最上面 4行是有关内核版本
![](/icons/50781de.gif)
信息
![](/icons/50781dou2.gif)
对于整个Makefile可以不用做修改
![](/icons/50781dou.gif)
采用默认
![](/icons/50781de.gif)
就可以了
![](/icons/50781yi.gif)
般情况下
![](/icons/50781dou.gif)
需要先用命令诸如"make menuconfig", "make xconfig"或者"make oldcofig"对内核进行配置
![](/icons/50781dou.gif)
这几个都是对内核进行配置
![](/icons/50781de.gif)
命令
![](/icons/50781dou.gif)
只是它们运行
![](/icons/50781de.gif)
环境不
![](/icons/50781yi.gif)
样
![](/icons/50781dou.gif)
执行
![](/icons/50781yi.gif)
下这几个命令中
![](/icons/50781de.gif)
任何
![](/icons/50781yi.gif)
个即可对内核进行配置:
make menuconfig是基于界面
![](/icons/50781de.gif)
内核配置思路方法
![](/icons/50781dou.gif)
make xconfig应该是基于QT库
![](/icons/50781de.gif)
![](/icons/50781dou.gif)
还有make gcofig也是基于图形
![](/icons/50781de.gif)
配置思路方法
![](/icons/50781dou.gif)
应该是需要GTK
![](/icons/50781de.gif)
环境
![](/icons/50781dou.gif)
make oldcofig就是对内核树原有
![](/icons/50781de.gif)
.config文件进行配置
![](/icons/50781yi.gif)
下即可
![](/icons/50781dou2.gif)
其实内核
![](/icons/50781de.gif)
配置部分
![](/icons/50781dou.gif)
主要是保证内核启动模块可动态加载
![](/icons/50781de.gif)
配置
![](/icons/50781dou.gif)
默认配置里面应该已经包含了这样
![](/icons/50781de.gif)
内容
![](/icons/50781dou.gif)
因此
![](/icons/50781dou.gif)
我用
![](/icons/50781de.gif)
是make oldconfig.
在内核源码
![](/icons/50781de.gif)
目录下执行:
# make
# make bzImage
其中
![](/icons/50781dou.gif)
第
![](/icons/50781yi.gif)
个make也可以不执行
![](/icons/50781dou.gif)
直接make bzImage
![](/icons/50781dou2.gif)
这个过程可能要持续
![](/icons/50781yi.gif)
个小时左右
![](/icons/50781dou.gif)
因此是对整个内核重新编译了
![](/icons/50781dou2.gif)
执行结束后
![](/icons/50781dou.gif)
可以看到在当前目录下生成了
![](/icons/50781yi.gif)
个新
![](/icons/50781de.gif)
文件: vmlinux, 其属性为-rwxr-xr-x
![](/icons/50781dou2.gif)
然后执行:
# make modules
# make modules_
![](/icons/50781install.gif)
对内核
![](/icons/50781de.gif)
所有模块进行编译和安装
![](/icons/50781dou2.gif)
执行结束的后
![](/icons/50781dou.gif)
会在/lib/modules下生成新
![](/icons/50781de.gif)
目录/lib/modules/2.6.20/
![](/icons/50781dou2.gif)
在随后
![](/icons/50781de.gif)
编译模块文件时
![](/icons/50781dou.gif)
要用到这个路径下
![](/icons/50781de.gif)
build目录
![](/icons/50781dou2.gif)
至此
![](/icons/50781dou.gif)
内核编译完成
![](/icons/50781dou2.gif)
可以重启
![](/icons/50781yi.gif)
下系统
![](/icons/50781dou2.gif)
第 3步:编写模块文件及Makefile
以LDD3上
![](/icons/50781de.gif)
hello.c为例:
//hello.c
#
<linux/init.h>
#
<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
hello_init(void)
{
pr
k(KERN_ALERT "Hello, world\n");
0;
}
void hello_exit(void)
{
pr
k(KERN_ALERT"Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile文件
![](/icons/50781de.gif)
内容为:
obj-m := hello.o
KERNELDIR := /lib/modules/2.6.20/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_
:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
其中,hello.c和Makefile文件应该位于同
![](/icons/50781yi.gif)
个目录下,可以放在/home下,我
![](/icons/50781de.gif)
两个文件都位于/home/david/.
第 4步:编译和装载模块
在文件所处
![](/icons/50781de.gif)
目录下,执行:
debian:/home/david # make
然后查看该目录下有哪些文件生成:
debian:/home/david # ls -l
总计 28
drwxr-xr-x 2 david david 4096 2007-02-07 17:49 Desktop
-rw-r--r-- 1 david david 462 2007-07-20 13:42 hello.c
-rw-r--r-- 1 root root 2432 2007-07-20 13:55 hello.ko
-rw-r--r-- 1 root root 607 2007-07-20 13:55 hello.mod.c
-rw-r--r-- 1 root root 1968 2007-07-20 13:55 hello.mod.o
-rw-r--r-- 1 root root 1140 2007-07-20 13:55 hello.o
-rw-r--r-- 1 david david 267 2007-07-20 13:48 Makefile
-rw-r--r-- 1 root root 0 2007-07-05 14:11 Module.symvers
可见,已经生成模块文件hello.ko.
然后,就可以加载该模块:
debian:/home/david # insmod hello.ko
查看模块是否加载进内核:
debian:/home/david # lsmod
Module Size Used by
hello 1344 0
nfs 219468 0
nfsd 202224 17
…… ……
其中Module名为hello
![](/icons/50781de.gif)
即为我们所加载
![](/icons/50781de.gif)
模块.
卸载模块:
debian:/home/david # rmmod hello
同样可以通过lsmod来查看该模块是否被卸载.
这里有两个问题,其
![](/icons/50781yi.gif)
就是pr
![](/icons/50781int.gif)
k
![](/icons/50781kh.gif)
输出
![](/icons/50781de.gif)
问题.LDD3上也说,在加载和卸载模块
![](/icons/50781de.gif)
时候都会有信息输出在屏幕上,如果在下通过终端仿真器(我们常用
![](/icons/50781de.gif)
虚拟机算是
![](/icons/50781yi.gif)
种),则在屏幕上看不到任何输出.我同时在虚拟机和和物理机都运行了该模块,均未看到有"Hello, world"(加载模块时pr
![](/icons/50781int.gif)
k
![](/icons/50781de.gif)
输出)或"Goodby, cruel world"(卸载模块时pr
![](/icons/50781int.gif)
k
![](/icons/50781de.gif)
输出). 这个不知道是我操作系统发行版
![](/icons/50781de.gif)
原因还是系统配置
![](/icons/50781de.gif)
问题,请了解这个问题
![](/icons/50781de.gif)
朋友指点
![](/icons/50781yi.gif)
下.
其 2,书上讲到如果屏幕上看不到信息,可能输出在某个日志文件里面了,并说可能在/var/log/messages文件中.并且看到网上很多网友也说是输出到这个文件里面.我不知道有没有发现输出在其他日志文件里
![](/icons/50781de.gif)
,不过我
![](/icons/50781de.gif)
这个信息输出在/var/log/syslog里面.在加载和卸载完该模块后, 执行命令:
debian:/home/david # cat /var/log/syslog | grep world
可以看到有两行内容.当然,也可以不用grep world, 应该会出现在最后两行.
Jul 20 14:15:29 localhost kernel: Hello, world
Jul 20 14:15:34 localhost kernel: Goodbye, cruel world
这就是pr
![](/icons/50781int.gif)
k应该输出
![](/icons/50781de.gif)
信息.
这里有另外
![](/icons/50781yi.gif)
个思路方法,可以实现pr
![](/icons/50781int.gif)
k
![](/icons/50781de.gif)
信息输出在屏幕上,即更改pr
![](/icons/50781int.gif)
k输出
![](/icons/50781de.gif)
优先级.例子中
![](/icons/50781de.gif)
优先级为:KERN_ALERT,优先级为<1>,如果将优先级改为KERN_EMERG即<0>,则可以看到屏幕
![](/icons/50781de.gif)
输出信息.
修改
![](/icons/50781de.gif)
思路方法只是修改
![](/icons/50781yi.gif)
下hello.c中两句pr
![](/icons/50781int.gif)
k
![](/icons/50781kh.gif)
![](/icons/50781de.gif)
内容,修改后
![](/icons/50781de.gif)
hello.c如下:
#
<linux/init.h>
#
<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
hello_init(void)
{
pr
k(KERN_EMERG "Hello, world\n"); /*改动部分*/
0;
}
void hello_exit(void)
{
pr
k(KERN_EMERG"Goodbye, cruel world\n"); /*改动部分*/
}
module_init(hello_init);
module_exit(hello_exit); 同样
![](/icons/50781de.gif)
思路方法编译生成模块,再次用insmod和rmmod,则在屏幕上看到
![](/icons/50781de.gif)
输出信息为:
debian:/home/david# insmod hello.ko
debian:/home/david#
Message from syslogd@localhost at Fri Jul 20 14:27:32 2007 ...
localhost kernel: Hello, world
debian:/home/david# rmmod hello
debian:/home/david#
Message from syslogd@localhost at Fri Jul 20 14:27:42 2007 ...
localhost kernel: Goodbye, cruel world
debian:/home/david 但是,是否能够将pr
![](/icons/50781int.gif)
k
![](/icons/50781kh.gif)
![](/icons/50781de.gif)
优先级改为KERN_EMERG值得商榷.
![](/icons/50781yinwei.gif)
在Linux Kernel Development中,对该优先级
![](/icons/50781de.gif)
描述为: An emergency condition; the system is probably dead.
以上就是整个2.6内核编译步骤以及模块动态加载
![](/icons/50781de.gif)
思路方法.理解和解释有误
![](/icons/50781de.gif)
地方,也请各位浏览本文
![](/icons/50781de.gif)
朋友指点,也希望能和对内核和驱动感兴趣
![](/icons/50781de.gif)
朋友交流