Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1673297
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3943
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: LINUX

2011-06-08 17:33:04

摘要:

    有时需要编译低版本内核,但往往高版本Linux发行版无法编译低版本内核,所以采用相应发行版来编译相应版本内核。本文在Ubuntu 6.06LTS(2.6.15)编译2.6.16(为了修改O(1)调度)。并记录了全过程。

  

    最近因实验需要,需修改O(1)调度算法,鉴于2.6.16以后(不包括2.6.16)的版本不采用O(1)调度而是公平调度,这就要求编译出2.6.16以前的内核。
  第一次编译内核,生怕把原系统搞崩溃,遂采用VMware+SecureCRT。首先得解决VMware下Ubuntu与XP共享数据,方法有很多。我觉得SecureCRT更好用,为了让Ubuntu更好支持CRT,需要在Ubuntu安装openssh-server、lrzsz,如下:(这样就可以在CRT通过sz、rz与Ubuntu实现数据传输)

jelline@jelline-desktop:~$ sudo apt-get install openssh-server
jelline@jelline
-desktop:~$ sudo apt-get install lrzsz

   is a FREE version of the SSH connectivity tools that technical users of the Internet rely on.
   is a unix communication package providing the XMODEM, YMODEM ZMODEM file transfer protocols.

一、过高版本内核无法编通低版本

  最初的想法,是用实验室服务器Ubuntu 9.10(2.6.31)编译2.6.16,结果出现如下错误: 


  网上有解释,说编译工具版本太新不适合编译旧版本,删除现有工具,安装合适版本编译工具。(这点我理解并不深,如果你知道,请你务必告诉我)如何界定“合适”?这个好办,你解压待编译的内核源码,打开linux-2.6.16/Documentation/Changes文件,内有关于版本说明,如下:(可以比下图给出版本稍高点,总之,版本不能太高也不能太低) 

  那好,更换编译工具版本可以编译通过,但问题又来了。编译好的未必能运行的起来(我同学试过,把原的内核版本跑飞了),这点还是很容易理解,支持系统运行的一些接口在旧版本内核没有得到实现。

二、用稍低版本编译2.6.16

  很自然就想到,用恰是2.6.16版本内核的Ubuntu或稍低版本编译2.6.16内核来完成该实验。我同学GOOGLE,找到Ubuntu 6.06LTS(内核版本2.6.15)。以下简述各步骤:(事实上linux-2.6.16/README文件已经告知)因为整个过程都需要管理者权限,通过命令sudo -s切换到root权限。

1、下载内核源码

  地址并解压bzip2 -dc linux-2.6.16.tar.bz2 | tar xvf -  (因Ubuntu 6.06没有默认安装gcc、make工具,直接通过apt-get install安装即可)

2、安装编译内核实用工具

  在配置内核之前,需要安装若干编译内核实用工具,主要如下:

apt-get install build-essential kernel-package libncurses5-dev libqt3-headers

  build-essential—— ubuntu提供了build-essential包让一次把相关软件安装(基本的编程库,gcc, make等)

            查看哪些包被 build-essential依赖用命令:apt-cache depends build-essential
  kernel-package ——系统里生成 kernel-image 的一些配置文件和工具

  libncurses5-dev——meke menuconfig要调用的

  libqt3-headers ——qt库,make xconfig要调用的


3、配置内核

  有5种方式配置(README文件有说明),我采用make menuconfig,回车YES。如果需要对比更改后内核与更改前内核的一些性能指标(事实上,这点很常用),可以通过选择General setup——>Local version在内核版本后面加上自定义的版本字符串加已区分,比如在Local version分别设为original、modified。
4、编译内核

  就一个命令:make(可以带-jN选项,使N个进程并行编译),在虚拟机下做奇慢无比,可以考虑晚上挂机编译。第二次编译就快很多了(Makefile的精髓)。如果需要清除所有旧的配置和旧的编译目标等文件,用make mrproper命令。
5、把模块编译进内核

  用命令make modules_install把模块编译进内核,编译好的模块默认路径为/lib/modules/2.6.16(如果你前面配置了Local vision,会在版本号加上original、modified加以区分同一内核版本不同修改版本)
6、安装内核

  通过命令make install把内核代码树中生成的内核镜像拷贝到系统/boot路径中,同时生成内核启动所需文件,但此时还没更新grub引导文件
7、制作内核引导文件

  initrd.img.*为了在initramfs中添加指定kernel的驱动模块,内核模块需要创建initramfs的kernel版本号。(在Fedora下面一般是用mkinitrd,而在Ubuntu/Debian下是用mkintramfs)通过如下命令,mkinitramfs会把/lib/modules/2.6.16/目录下的一些启动时用到的模块加到initramfs中。

sudo mkinitramfs -o /boot/initrd.img-2.6.16modified /lib/modules/2.6.16modified/

   is a root filesystem which is embedded into the kernel and loaded at an early stage of the boot process. 

附:

  内核引导文件initrd.img简介initrd = init ramdisk,是一个启动时存在于内存的文件系统。 initrd的最初的目的是为了把kernel的启动分成两个阶段:在kernel中保留最少最基本的启动代码,然后把对各种各样硬件设备的支持以模块的 方式放在 initrd中,这样就在启动过程中可以从initrd所mount的根文件系统中装载需要的模块。这样的一个好处就是在保持kernel不变的情况下, 通过修改initrd中的内容就可以灵活的支持不同的硬件。在启动完成的最后阶段,根文件系统可以重新mount到其他设备上。(此段引自)

8、更新grub引导文件

  可以直接手动修改(vim /boot/grub/menu.lst),建议先用命令update-grub自动更新menu.lst再人工确认,主要得确认下图中initrd是否自动写入(我的就没补上)。若无,手动补上。

 
9、重启reboot

  重启虚拟机,按ESC进入启动项选择:

选择所编译的版本进入系统,看是否能正常启动,并用uname –r观察内核版本。 


三、常见问题

1、rebooot无法进入系统

  提示Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0),这大多是menu.lst没设置好。

解决:

  重启系统,选择没修改过的内核版本(如Ubuntu 6.06自带的2.6.15)进入系统,检查menu.lst文件(可以再update-grub下)
2、高版本内核无法编译低版本内核

  正如上文所说,编译工具太新了,建议用适当的发行版编译内核。同理,如果低版本无法编译高版本,则需考虑是否应该升级相应工具。


最后,感谢小强同学悉心的指导。


主要参考:

[1].博文:《linux2.6.16内核在ubuntu下的编译和启动

[3].Robert Love.Linux内核设计与实现.

阅读(5386) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

yfj3002015-06-17 09:09:16

LZ好强大