Linux Kernel in a Nutshell - 6
Upgrading a Kernel
不可避免有这样一种情况:你具有一个客制化内核,工作起来简直完美,而这个内核唯一的一个小缺憾也在最近被内核开发者解决。现在,就面临了更新内核的问题了。
本章介绍如何简单地保留前一版本的配置选项情况下,完成老内核版本到新内核的更新。
首先,请备份内核源码目录中的 .config
文件。我们之前为了一个使用完美的内核做出了努力,当然不希望它付之东流。
$ cd ~/linux/linux-2.6.17.11
$ cp .config ../good_config
从上一个版本升级到新的版本,只需要下面五步:
- 获取新的内核源码
- 将修改内容应用到老源码树中
- 基于之前的内核配置重新配置内核
- 编译新内核
- 安装新内核
最后两步过程与之前讲解过的类似,因此我们只需要讨论前三个步骤。
在本章中,我们假设你已经具有了一个 2.6.17.9
版本的内核,希望升级到 2.6.17.11
发布版本。
Download the New Source
Linux
内核开发者明白用户不希望在每次升级时下载所有的源代码,因为这显然是浪费时间与带宽的。因此,他们提供了以补丁的方式将老版本升级到新版本。
在 kernel.org
主站上,你应该记得它具有各个版本的内核源码提供下载。
在更新时,我们要确定需要下载哪个补丁包。
Which Patch Applies to Which Release?
一个内核补丁文件只能从一个指定的版本升级到另一个指定版本,下面是可以使用的不同的补丁文件。
- 稳定内核补丁可以应用到基础内核版本。这意味着
2.6.17.10
补丁包只能应用到2.6.17
内核发行版本上,而2.6.17.10
补丁包不能打到2.6.17.9
版本或其他版本的内核版本上 - 基础内核发行补丁包,只能应用到之前的基础内核版本上,这意味着
2.6.18
补丁国宝,只能打到2.6.17
内核发行版本上,而不能打到2.6.17.y
内核发行版本或其他发行版本上 - 增补形式的补丁只将指定版本的内核升级到下一个版本。这允许开发者在不下载更低版本内核的基础上升级内核,只需要将下一个版本的补丁包打到现有源码上就好了,推荐你使用增量式的补丁包
Finding the Patch
因为我们希望从 2.6.17.9
内核版本升级到 2.6.17.11
内核版本,我们需要下载两个补丁包。首先将 2.6.17.9
内核升级到 2.6.17.10
内核版本,之后将 2.6.17.10
内核版本升级到 2.6.17.11
内核版本。
稳定版内核源码以及基础版的内核补丁位于官方站点的相同目录下。所有的增补形式的补丁可以在更低一层的目录下找到,在 incr
子目录中。因此查找能将 2.6.17.9
内核升级到 2.6.17.10
的补丁包,可以在 /pub/linux/kernel/v2.6/incr
子目录中查找到:
$ cd ~/linux
$ lftp ftp.kernel.org/pub/linux/kernel/v2.6/incr
lftp ftp.kernel.org:/pub/linux/kernel/v2.6/incr> ls *2.6.17.9*.bz2
-rw-rw-r-- 1 536 536 2872 Aug 22 19:23 patch-2.6.17.9-10.
bz2
lftp ftp.kernel.org:/pub/linux/kernel/v2.6/incr> get patch-2.6.17.9-10.bz2
2872 bytes transferred
lftp ftp.kernel.org:/pub/linux/kernel/v2.6/incr> get patch-2.6.17.10-11.bz2
7901 bytes transferred
lftp ftp.kernel.org:/pub/linux/kernel/v2.6/incr> exit
$ ls -F
good_config linux-2.6.17.9/ patch-2.6.17.10-11.bz2 patch-2.6.17.9-10.bz2
Applying the Patch
因为我们下载的补丁包为压缩文件,首先要对它们进行解压缩。
$ bzip2 -dv patch-2.6.17.9-10.bz2
$ bzip2 -dv patch-2.6.17.10-11.bz2
现在我们需要将这些补丁文件打到原本的内核源码树中,进入到内核源码目录中:
$ cd linux-2.6.17.9
使用 patch
程序将第一个补丁打进源码树种,将 2.6.17.9
升级为 2.6.17.10
:
$ patch -p1 < ../patch-2.6.17.9-10
查看源码树的顶层 Makefile
的头五行内容,确定我们成功的升级了我们的源码:
$ head -n 5 Makefile
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 17
EXTRAVERSION = .10
NAME=Crazed Snow-Weasel
接下来将另一个补丁也打进去:
$ patch -p1 < ../patch-2.6.17.10-11
再次查看是否成功升级源码:
$ head -n 5 Makefile
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 17
EXTRAVERSION = .11
NAME=Crazed Snow-Weasel
现在内核源代码成功升级到我们想要升级的版本了,一个良好的习惯是将这个升级后的源代码所处的目录更新为当前它所处的版本:
$ cd ..
$ mv linux-2.6.17.9 linux-2.6.17.11
Reconfigure the Kernel
之前我们使用 make menuconfig
或 gconfig
或 xconfig
方法修改了不同的配置选项。但是一旦已经拥有了一个能够工作的配置选项,后面要做的工作就是,更新出现在新内核版本中的配置选项。为实现这一工作,需要使用 make oldconfig
以及 make silentoldconfig
选项。
make oldconfig
使用当前 .config
文件的内核配置,并基于新内核对它进行更新。在完成这个工作的过程中,它会逐项打印所有配置问题,如果选项已经在当前的配置文件中存在,则自动使用这个配置。如果存在新选项,程序会暂停,并询问用户要设置的配置选项。在用户回答之后,程序继续进行,知道所有配置选项配置完成。
make silentoldconfig
与 oldconfig
工作时类似,只是如果不是一个新选项出现,不会向屏幕打印任何信息。
通常情况下,在不同版本的稳定内核升级过程中,如果是同一个稳定的内核序列,不会有新配置选项被添加进来。这种情况下,对内核进行配置就不会有配置选项的问题出现,程序持续运行直到成功配置或用户打断。
新版本的移除了 silentoldconfig
这个选项
Can't This Be Automated?
前面所有的内容,下载合适的补丁文件,解压缩补丁文件,将补丁打到源码树中,显然是可以自动化完成的。内核开发者开发了一款工具名为 ketchup
,可以帮助自动化完成上面的工作。