为什么要编译内核源代码树
LDD3中提到,要想为2.6内核构造模块,必须在自己的的系统中配置并构造好内核树。这一要求和先前板本的内核不同,先前的内核只需要一套内核头文件就够了。 所以学习驱动编写前,我们需要先准备好内核树。
编译内核树包括以下几个步骤
1、下载内核源代码
推荐到内核源代码主页 www.kernel.org 去下载社区主线版本,因为发行版厂商提供的内核通常打了许多补丁。标准内核对学习驱动程序的编写是最好的。
2、解压内核源代码
# tar -zxf linux-2.6.36.tar.gz -C /usr/src/ //解压到该目录/usr/src/
# cd /usr/src/linux-2.6.36/ #进入目录
# make mrproper //去除内核的依赖关系以及编译后的垃圾信息
3、配置内核
# make menuconfig //进入菜单方式界面配置内核
需要勾选上General Setup下面的 “enable deprecated sysfs features to support old userspace tools”,不然编译安装之后会找不到原来的挂载点。
在升级3.x内核时勾选这一项出现了问题,具体需不需要勾选此项请阅读此项 HELP 文档 或者参考文章
http://hi.baidu.com/mhlovejn/blog/item/7a4a55fe65de7488b801a020.html
4、编译内核
make //编译内核
make modules //编译模块
make modules_install //安装内核模块
make install //安装内核
5、升级内核
修改引导启动管理器的配置文件
# vim /boot/grub/grub.conf
default=1
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux Server (2.6.36)
root (hd0,0)
kernel /vmlinuz-2.6.36 ro root=/dev/VolGroup00/LogVol00 rhgb quiet
initrd /initrd-2.6.36.img
title Red Hat Enterprise Linux Server (2.6.18-8.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-8.el5 ro root=/dev/VolGroup00/LogVol00 rhgb quiet
initrd /initrd-2.6.18-8.el5.img
其实不需要进行修改,内核升级好之后会自动在grub.conf文件中加入上门红色的配置。重启电脑就可以选择需要启动的内核,如果不需要旧的内核可以在grub.conf配置文件中将旧内核的参数注释掉即可。
6、测试编译驱动模块
前面步骤准备好了内核源代码树并且升级了内核,现在可以测试我们自己写的驱动模块了。
编译驱动模块不一定要升级内核,但是内核源代码树一定要有。如果不升级内核,需要保证内核源代码树版本和正在运行的内核版本号一致,否则insmod驱动模块时会报错。
内核源代码树版本号可以在顶层Makefile中找到 例如
采用uname -r 命令查看内核版本号
2.6.38.6-45.fc14.i686
可以看到主版本号是一致的都是 2.6.38, 需要把内核源代码树的EXTRAVERSION改为 .6-45.fc14.i686并且重新编译。只有保证版本号完全一致,才能使在内核源代码树环境下编译的内核在系统中安装成功。
此方法可以用在不升级内核情况下编译运行驱动模块。
编写内核模块源文件:
// hello.c #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world/n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world/n"); } module_init(hello_init); module_exit(hello_exit);编写Makefile:
# Makefile obj-m:=hello.o KDIR:=/lib/modules/2.6.15-1.2054_FC5/build //注意 此处修改为内核源代码树目录 PWD:=$(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules
hello.ko
hello.mod.c
hello.mod.o
hello.o
运行命令:
# insmod hello.ko
应该可以看到返回的信息:Hello, world
然后再运行命令:
# rmmod hello
应该可以看到返回的信息:Goodbye, cruel world
如果没看到,就是输出到系统的日志文件中去了,可以查看文件:
tail -f /var/log/messages //tail - output the last part of files
cat /var/log/syslog
应该有信息的输出。
以通过 lsmod 来查看该模块是否被卸载 .
参考文档:
http://www.liusuping.com/ubuntu-linux/redhat-linux-kernel-update.html
http://blog.csdn.net/skypia0000/article/details/5566224