初学者编译Linux内核,最简单ko模块

最近工作要在内核态编程,学习了一下自己编译内核,流程如下:

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 内核代码目录中

    #cd zcl-linux-2.6.32.84-0.7

    #make mrproper          //删除原来编译产生的垃圾

    #make menuconfig      //文本界面配置内核编译选项,也可用更原始的 #make config

      在弹出界面中选中自己需要编译的模块,比如在

       Genral setup--> 中选择 GCOV 功能等,选择完后,退出;  

      Genral setup 还可以选择编译好的内核 lib 安装路径,Local Version,可在后面填加字符串

       这样就可以将编译好的模块安装到不同目录中


3.  #vi Makefile

       VERSION = 2
       PATCHLEVEL = 6
       SUBLEVEL = 16
       EXTRAVERSION = .84       //将扩展版本号修改一下,以便和系统中原本内核版本区分
       NAME=zhangcunli              

     2.6 的内核代码编译只需要执行一步即可

     #make            但这样编译时间太长,可以按如下步骤执行:

     //可以替换为如下步骤:

     #make bzImage    /*编译大内核*/  

       或者 male -jn bzImage ,其中 n 的值为 2*cpu核的个数,这样可以加快编译速度

       比如,我的电脑有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 install

     该命令会做如下事情:

      (1)把压缩内核映象拷贝到/boot目录下, 并创建相应的System.map符号链接; 
     (2)修改bootloader的配置文件;
     (3)调用mkinitrd程序创建内核的initrd映象. 对于GRUB而言,

          将在/boot/grub/menu.lst配置文件自动增加如下类似的配置行:

      title zhangcunli SUSSE10 SP2 10.2-0 - 2.6.3216.84-0.7
      root (hd0,1)
      kernel /boot/vmlinuz-2.6.32.84-0.7-default root=/dev/sda2 vga=0x314 resume=/dev/sda1 splash=silent showopts
      initrd /boot/initrd-2.6.32.84-0.7-default

      自己再修改一下新填加进来的配置行 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
#include
#include
MODULE_LICENSE("GPL");
static int __init helloko_init()
{
/* KERN_ALERT 表示以高优先级将打印输出的控制台,注:X界面环境不行*/
printk(KERN_ALERT"Hello, World - this is the kernel speaking\n");
        
    return 0;
}
static void __exit helloko_exit()
{
printk(KERN_ALERT"Short is the life of a kernel module\n");
}
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  查看日志





     

    

      


你可能感兴趣的:(linux)