最近工作在内核状态下编程。 我学会了自己编译内核。 流程如下。
1. #cd /usr/src/
复制linux内核代码
# CP-r Linux-2.6.32.12-0.7 zcl-Linux-2.6.32.84-0.7
如果系统中未安装内核代码,则可以将最新的内核代码下载到gnu官方网站
2 .将CD放入自己的linux内核代码目录中
#cdzcl-linux-2.6.32.84-0.7
#make mrproper //删除原始编译中产生的垃圾
#make menuconfig //文本界面设置内核编译选项,还可以使用更原始的#make config
在弹出界面中选择要编译的模块。 例如
用Genral setup--选择GCOV功能等,选择后退出;
在Genral setup中,还可以在编译内核的lib安装路径、本地版本和字符串之后填写
这样,您就可以将编译的模块安装在其他目录中
3. #vi Makefile
版本=2
PATCHLEVEL=6
SUBLEVEL=16
修改extra版本=.84//扩展版本号以与系统中的原始内核版本区分开来
NAME=zhangcunli
2.6内核代码的编译只需执行一步
#make但是,这样编译时间太长,可以执行以下操作:
//可以替换为以下步骤。
#make bzImage /*大核心编译*
或male -jn bzImage。 其中,n的值是2*cpu核心的数量,可以提高编译速度
例如,我的电脑有两个cpu,每个都是双核的,所以我用#make -j8 bzImage进行编译
或#make zImage编译压缩格式的内核
#make modules //编译选定模块或使用make -j8 modules
#make modules_install
将编译的模块安装在系统指定的目录中
/lib/modules/2.6.32.84-0.7-default此处/lib/modules下一级目录以前设置了自己的版本号
4 .编译成功后,可以安装内核
#请备份CP/boot/grub/menu.lst/boot/grub/menu.lst.bak grub引导配置文件
# make安装
此命令将执行以下操作:
(1)将压缩内核映像复制到/boot目录,并创建相应的System.map符号链接; )2)修改引导加载器配置文件; )3)调用mkinitrd程序创建内核的initrd映像。 对于GRUB来说,
将以下配置行:自动添加到/boot/grub/menu.lst配置文件中
titlezhangcunlisusse 10s p 210.2-0-2.6.3216.84-0.7
根(hd0,1 ) )。
kernel/boot/vmlinuz-2.6.32.84-0.7-defaultroot=/dev/sda2VGA=0x 314 resume=/dev/sda1splash=silentshohon
initrd/boot/initrd-2.6.32.84-0.7 -默认
自己再修改一下新填加进来的配置行 title
最后,修改 menu.lst 的default 项,default 的值从 0 开始算起。
5. 最后终结一下,编译自己的内核所需要的步骤:
5.1: 拷贝一份内核代码
5.2: make menuconfig 选择配置,vi Makefile 修改扩展版本号
5.3: make bzImage 编译内核
5.4: make modules 编译模块 【或者只执行一次make编译所有】
5.5: make moduels_install 将编译好的模块安装到 /lib/modules 下
5.6: make install 安装编译好的内核版本
5.7: 修改 /boot/grub/menu.lst 将自己的内核设置为默认启动项
记:自己编译的时候,一直没敢执行 make install 这一步,生怕这一步会替换掉系统原有的内核,以及如何生成/boot/initrd-2.6.32.84-0.7-default这个文件,一直在找如何通过修改参数将内核安装到指定目录;【应该是修改 Makefile 下面的几个宏可以实现】,最后发现只要修改的 Makefile 里面的版本号,make install 会自动将生成的内核文件按版本号命名,并且这一步会生成 initrd 文件,不需要手动使用 mkinitrd 命令生成。
注意啦:当我在公司的suse11上编译新内核的时候,却发现如上步骤在启动新内核时失败,提示:unsupported ko 之类的错误,经过实验发现可用如下步骤安装成功:
执行完5.5后,
5.6: #cp /usr/src/zcl-linux-2.6.32.84-0.7/arch/boot/x86/bzImage /boot/vmlinuz-2.6.32.84-0.7
#cp /usr/src/zcl-linux-2.6.32.84-0.7/System.map /boot
#cp /usr/src/.config /boot
#vi /etc/modprobe.d/unsupported****
里面应该只有一个值 allow-unsupported- (想不起叫什么名字的)由 0 改成 1;
#cd /boot
#mkinitrd
该命令会根据 /boot 下所有的 vmlinuz 文件生成对应的 initrd 文件,并且写系统映射表;
5.7:修改 /boot/grub/menu.lst ,这回得拷贝一条记录,将其中的版本号改为刚才自己编译好的;reboot即可成功;
编写一个最简单的 xxx.ko 模块,使用 insmod 插入到内核中,再使用 rmmod 从内核中移除:
1. helloko.c 文件内容如下:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init helloko_init()
{
/* KERN_ALERT 表示以高优先级将打印输出的控制台,注:X界面环境不行*/
printk(KERN_ALERT"Hello, World - this is the kernel speakingn");
return 0;
}
static void __exit helloko_exit()
{
printk(KERN_ALERT"Short is the life of a kernel modulen");
}
module_init(helloko_init);
module_exit(helloko_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhangcunli");
这个模块定义了两个函数, 一个在模块加载到内核时被调用(helloko_init)以及一个在模块被去除时被调用( helloko_exit). moudle_init 和 module_exit 这几行使用了特别的内核宏来指出这两个函数的角色. 另一个特别的宏 (MODULE_LICENSE) 是用来告知内核, 该模块带有一个自由的许可证; 没有这样的说明, 在模块加载时内核会抱怨.
2. Makefile 文件如下:
obj-m:=helloko.o
KERNELBUILD := /lib/modules/`uname -r`/build
default:
@echo "BUILD kmod"
@make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
@echo "CLEAN kmod"
@rm -rf *.o *.ko
@rm -rf .depend .*.cmd *.mod.c .tmp_versions *.symvers .*.d *.markers *.order
3. 在 helloko.c 所在目录执行
#make
验证:
#insmod helloko.ko 插入 helloko.ko 模块
#dmesg | tail 查看日志
可以看到日志输出
#rmmod helloko.ko 移除 helloko.ko 模块
#dmesg | tail
或者
#tail /var/log/messages 查看日志