分类: LINUX
2013-01-31 11:22:12
我曾经手动编译内核,这必须按顺序进行一系列的步骤;kernel-package就是写来完成这些所必须的步骤的.(现在他已超出这个范畴,但是实际上,
那正是他所完成的).这对于新手来说是相当重要的:make-kpkg完成了编译一个内核所需的所有步骤,并且内核的安装是一个快照.--kpkg-
package的作者Manoj Srivastava.
如果我们曾经编译过一个内核,我们就会惊异于他的简单.这个指南就是设计用来可以使得我们使用Debian的kernel-package系统,这可以极大的简化自定义内核的构建与安装.学习创建Debian的内核包与他们的模块,并且使用dpkg来管理产生的内核映像.
注意:如果我们不小心我们就会使得我们的系统不能启动.强烈建议至少要读一遍整个文档,并且按照他来编译我们的内核.
在这里我们要记住的就是,不可避免的,一些人会使用这个文档搞遭他们的系统.不要成为他们中的一员.如果我们不量解一些事,要动手之前要得到更为详细的信息.
2.准备
2.1.备份启动磁盘
在我们制作一个新的内核之前,我们要做的第一件事就是要为我们正在运行的内核制作一个启动磁盘.这样,如果一些事情使得我们的系统崩溃,我们可以启动我们的机器并且进行修复.取一个我们不介意擦除的软盘来做这样的事情(以root用户):
bash:~# mkboot path_to_kernel
使用合适的信息来代替path_to_kernel,例如"/boot/vmlinuz-2.4.18-bf2.4"(如果我们安装的是2.4内核的Woody).
2.2.安装什么
我们要使用Debian 3.0r1(Woody版本1);我们需要下面的软件包:
> 1.
> gcc
> 2.
> kernel-package
> 3.
> kernel-source-2.4.18 (或者是我们要使用的任何内核源码)
> 4.
> libc6-dev
> 5.
> tk8.0 or tk8.1 or tk8.3
> 6.
> libncurses5-dev
> 7.
> fakeroot
> 8.
> bin86 (为在PC机上安装2.2.x内核)
我们可以通过下面的命令来安装这些软件包(以root用户):
bash:~# apt-get install gcc kernel-package kernel-source-2.4.18 libc6-dev tk8.3 libncurses5-dev fakeroot
安装这些软件包会使得为了满足一些依赖关系而安装一些其他的软件包.
注意:如果我们是在PC结构上安装2.2系统的内核(使用AMD处理器的机器为PC机,但是Mac或Alpha不是),我们需要bin86软件包.
我
们可以使用我们希望的任何内核:我选择2.4.18,因为这在Woody中是最新的.Debian的维护者做了十分出色的工作将内核源码打包到一个.
deb文件中,推荐使用这些源码包而不是其他的源码包.我可以理解的使用其他源码包的唯一原因就是得到Debian中并支持的硬件支持.
3.设置源码树
源码树就是我们包含我们要编译的内核源码的目录.
3.1.加入src组
当
安装了内核源码包,源码包放在/usr/src目录中.要在这个目录工作,我们必须是root用户或是src组的成员.为了避免任何时候以root用户工
作,可以将我们自己加入src组.只有root用户可以添加用户到组,所以先要成为root用户,然后执行下面的命令:
bash:~# adduser my_username src
Adding user my_username to group src...
Done.
当然,我们要使用我们自己的用户名来代替"my_username".我们组的成员关系会在登陆时进行检测,所以我们需要注销然后再次登陆以被识别为src的成员.这有三种方法:
1.如果我们在X中一个终端窗口,注销X并从控制台退出.然后登陆到控制台并启动另一个X会话.
2.如果我们正在使用一个图形化登陆管理器,如xdm,gdm,kdm,退出X并再次登陆.
3.如果我们在控制台,退出后再次登入.
要保证我们真正的加入到src组中,可以执行下面的命令(在我们完成了退出/登入之后):
bash:~$ groups
my_username src
我们会在组列表中看到src(在默认情况下,我们也属于非用户组"my_username").
3.2.解压源码包
作为普通用户,进入/usr/src目录并列出他的内容;我们就会看到我们安装的bzip格式的tar包文件:
bash:~$ cd /usr/src
bash:/usr/src$ ls
kernel-source-2.4.18.tar.bz2
如果我们同时也看到一个名为linux符号链接,移除他:
bash:/usr/src$ rm linux
注意:如果我们有这个链接但却没有在解压我们新的源码包之前移除他,我们就会使得旧的与新的源码文件混合,这样就不会正确的编译.
Debian
的源码包解压到一个名为kernel-source-x.y.z的目录中.官方的内核源码直到2.4.18解压到一个名为linux目录中(我们建议将那
个目录改名为linux-x.y.z).2.4.19的官方源码以及以后的将会解压到linux-x.y.z/.
要解压一个源码包,我们可以以常规用户执行下面的命令:
bash:/usr/src$ tar -jxf kernel-source-2.4.18.tar.bz2
这将会创建一个属于我们与src组的名为kernel-source-2.4.18/目录.
3.3.设置符号链接
现在没有指向任何源码树的符号链接,现在我们要创建一个:
bash:/usr/src$ ln -s kernel-source-2.4.18 linux
将这里的"kernel-source-2.4.18"源码目录替换为我们解压源码时创建的源码目录.
检测符号链接是一个好主意.如下面的样子:
bash:/usr/src$ ls -l
total 66908
-rw-r--r--- 1 roott roott 23833519 Mar 20 16:18 kernel-source-2.4.18.tar.bz2
drwxr-sr-xx 15 kjmckk srcc 4096 Mar 20 16:30 kernel-source-2.4.18
lrwxrwxrwxx 1 kjmckk srcc 20 Mar 20 16:36 linux -> kernel-source-2.4.18
3.4.检测当前的需要
进入linux目录我们就会发现另一个名为Documentaion的目录.进入这个目录查看Changes文件.用我们最喜欢的编辑器打开这个文件并且找到"Current Minimal Requirements"部分.下面的是一个例子:
Current Minimal Requirements
============================
Upgrade to at *least* these software revisions before thinking you've
encountered a bug!! If you're unsure what version you're currently
running, the suggested command should tell you.
oo Gnu CC 2.95.33 # gcc --version
oo Gnu makee 3.777 # make --version
oo binutilss 2.9.1.0.255 # ld -v
oo util-linuxx 2.10oo # fdformat --version
oo modutilss 2.4.22 # insmod -V
oo e2fsprogss 1.255 # tune2fs
oo reiserfsprogss 3.x.0jj # reiserfsck 2&>1|grep reiserfsprogs
oo pcmcia-css 3.1.211 # cardmgr -V
oo PPPP 2.4.00 # pppd --version
oo isdn4k-utilss 3.1pre11 # isdnctrl 2>&1|grep version
Changes文件在第一列列出了所需要的程序,所需的版本列在第二列,而检测版本的命令列在第三列.我们也许并不需要列出的所有的程序或是软件包.(例如,如果我们不使用PC卡,我们就不需要pcmcia-cs).
我们不必单独的检测每一个需要的程序,我们可以运行ver_linux脚本,这可以在内核树的scripts目录中找到.我们首先要使其可运行.在这里我们要注意的是这个脚本也许并不会检测Changes中列出的所有所需的程序,而会检测一些并没有列出的程序.
如下面的检测结果:
bash:/usr/src/linux/Documentation$ cd ../scripts
bash:/usr/src/linux/scripts$ chmod +x ver_linux
bash:/usr/src/linux/scripts$ ./ver_linux
If some fields are empty or look unusual you may have an old version.
Compare to the current minimal requirements in Documentation/Changes.
>
Linux sirius 2.4.18.030309 #1 Sun Mar 9 22:15:39 EST 2003 i586 unknown unknown GNU/Linux
>
> Gnu CC 2.95.4
> Gnu makee 3.79.1
> util-linuxx 2.11n
> mountt 2.11n
> modutilss 2.4.15
> e2fsprogss 1.27
> pcmcia-css 3.1.33
> Linux C Libraryy 2.3.1
> Dynamic linker (ldd)) 2.3.1
> Procpss 2.0.7
> Net-toolss 1.60
> Console-toolss 0.2.3
> Sh-utilss 2.0.11
> Modules Loadedd ds i82365 3c589_cs pcmcia_core ext3 jbd rtc
如果在Debian系统上使用上面的方法并不能决定程序版本,试着使用dpkg.
如下面的使用dpkg来检测所需要的内容:
bash:/usr/src/linux/scripts$ dpkg -l make
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Namee Versionn Description
+++-==============-==============-============================================
iii makee 3.79.1-144 The GNU version of the "make" utility.
如
果我们使用kernel.org上的版本或是使用Description
testing或是unstable的分支,我们需要更新一些工具来适应我们的需要.如果我们使用Debian的stable分支的源我们就不需要上面那
样.现在我们就完成了配置内核源码树的设置.
4.配置内核
4.1.注意
内核配置的一个重要原则就是TANSTAAFL(There Ain't No Such Thing As A Free Lunch).我们加入到内核中的任何特征都会增加内核的尺寸以及内核编译的时间,即使我们是选择作为模块来添加的。
为
了使得内核可以在大多数的硬件上为大多数的人所使用,Linux发行版本通常包含了对于大多数硬件与功能的支持。Debian也是如此。预编译的内核包含
了对于我们绝不会用到的硬件以及我们绝不会读到的语言的支持。我的内核配置的一般原则是:“如果有疑问就保持他“。如果我们测试我们的新内核但是发现一些
硬件不能正常的工作,这样就可以很容易的切换另一个配置并且编译另一个内核。
为了避免越来越大的尺寸,最近内核镜像的另一个特征就是initrd
的使用。在我的电脑旁边的一个特殊的字典将initrd定义为“需要担心的一些事情“。我们可以通过将对于我们的启动硬件与根文件系统的支持直接编译入内
核(而不是作为模块)来避免担心的必要。如果我们的启动硬盘是IDE,将IDE支持编译进入内核。如果我们的根文件系统是Reiserfs,一定要保证将
Reiserfs的支持编译入内核,而不是作为模块。
在这里我们要注意是一定要软盘的支持编译进入内核。如果我们将其编译为模块,那么就不可以从软盘来启动我们的新内核了。
不幸的是,内核选项的详细解释已经超出了这个文档的范围。要得到内核配置的更多信息,我们可以查看LDP,/usr/src/linux/Documentaion文件,以及硬件文档。
4.2 make xconfig
有许多的方法可以用来配置内核,我们在这里第一个接触到的就是xconfig。在我们进入/usr/src/linux目录后,我们可以输入命令:
bash:/usr/src/linux$ make xconfig
4.3 make menuconfig
也许我们并没有在使用X。也许我们在配置这一步会做得更好,而且我们相信键盘要比鼠标来得快。运行命令如下:
bash:/usr/src/linux$ make menuconfig
4.4 make config
内核0.01根本没有配置选项。内核1.0有49个不同的配置选项,所以一个配置机制是必须的。键入make config.
现在我们退出make config。我们并不希望一次回答1300多个不同的问题。更好的方法就是使用xconfig或是menuconfig。
5 编译内核镜像(kernel image)
如果我们的机器是一台低速处理器的老式机器,也许得需要花费几个的小时的时间来编译一个Debian kernel image。(我们也可以在一个快速的机器上来编译我们的内核而将其安装到一个低速的机器上,在这里我们并不讨论这个话题)。
5.1 make-kpkg
要编译内核,我们可以调用make-kpkg,这是一个可以自动替换"make dep;make clean;make bzImage;make modules"命令序列的脚本。我们有向要花费一些时间来阅读一下make-kpkg的手册页。
注:make-kpkg是kernel-package软件包的一部分。他的文档位于/usr/share/doc/kernel-package/.
make-kpkg命令是相当复杂的,而且初看起来有一些吓人。基本语法格式如下:
make-kpkg
而我们的target可以是kernel_image。下面我们来解释一下两个比较重要且常用的用法选项,"--append-to-version"与"--revision".
5.2 --append-to-version
第一个选项可以让我们来指定一个额外的内核版本,这个可以成为内核名的一问分。我们可以使用数字,"+",".",但是不要使用下划线"_".
下面的是我正在运行的内核:
bash:/usr/src/linux$ uname -a
bash:/usr/src/linux$
Linux sirius 2.4.18.030309 #1 Sun Mar 9 22:15:39 EST 2003 i586 unknown
unknown GNU/Linux当我编译这个内核时使用的选项为"--append-to-version=.030309"(注意开头的".")。
注意:我们要避免设置--append-to-version为如"-686","-K7","-sparc"等值,因为这些值常为Debian的预编译内核所使用。
内核模块位于/lib/modules子目录下。每一个内核有他自己的子目录。每次当我们以一个新的名字来安装一个新的内核时,这个包安装程序就会在/lib/modules目录下创建一个新的子目录来保存他自己的模块。
这就意味着每一次我们使用--append-to-version的一个新的值来编译一个内核时,我们就可以保证这个内核有一个新的名字,而他的模块也不会与其他的内核模块相冲突。
注意:如果我们使用相同的名字来安装一个内核时,安装程序就会覆盖掉已安装的内核及其模块。
5.3 --revision
make
-kpkg的另一个选项就是"--revision",他只会影响Debian软件包本身的名字而不是内核的名字。与--append-to-
version相似,我们只可以使用数,"+",".",不要使用下划线"_"。如果我们并没有为--revision指定一个值,make-kpkg就
会使用"10.00.Custom".
使用不同的--revision的值就可以避免相同名字的内核之间的冲突。
5.4 内核软件包字
Debian kernel-image文件的名字格式如下:
kernel-image-(kernel-version)(--append-to-version)_(--revision)_(architecture).deb
软件包的名字是第一个下划线之间的所有内容。如下面的是我的内核软件包的一个列表:
bash:/usr/src$ ls
kernel-image-2.4.18.030309_1.0_i386.deb
kernel-image-2.4.18.030320_1.0_i386.deb
kernel-image-2.4.18.030320_10.00.Custom_i386.deb
现在我们就会明白为什么不要在make-kpkg的选项中使用下划线的原因了,他用来分隔软件名字之间的元素。
5.5 fakeroot
当我们将自己添加到src组时,我们就可以以普通用户的权限来完成大多数的kernel-package的工作了。然而作为内核软件包一部分的文件(如内核与内核模块)却为root用户所有,而且要以root权限来运行。他们必须创建为root权限。
使用fakeroot我们可以普通用户的身份来运行make-kpkg,并且可以以普通的权限来完成大多数的工作。在接近工作的结尾时,fakeroot就会以模拟root环境来创建一个kernel-image软件包。
make-kpkg的手册页描述了使用fakeroot的方法,我们在这里使用将fakeroot放在make-kpkg命令的开头的最简单的方法:
fakeroot make-kpkg
5.4 制作kernel image
最后的时刻到了,我们已经准备好来制作kernel image了:
bash:/usr/src/linux$ fakeroot make-kpkg clean
然后执行下面的命令:
bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030320 kernel_image
现在我们所要作的就是等待计算机来完成这些工作。
6 安装kernel-image软件包
一旦构建了kernel image,我们就可以安装kernel-image软件包了,这个软件包包含内核与相应的模块。首先我们要进入/usr/src目录来检测以确保成功的进行了构建,并且列出其中的内容:
bash:/usr/src/linux$ cd ..
bash:/usr/src$ ls
kernel-source-2.4.18
kernel-source-2.4.18.tar.bz2
kernel-image-2.4.18.030320_10.00.Custom_i386.deb
linux
要安装内核及其所有的模块,我们要以root身份来运行:
bash:/usr/src# dpkg -i kernel-image-2.4.18.030320_10.00.Custom_i386.deb
要从磁盘上安装一个kernel-image软件包,我们需要指定完整的文件名。
post-install脚本会询问我们是否要创建一个启动盘,如果我们在以前已经创建了,在这里我们就可以加答no。
如果一切正常,我们就可以重新启动我们的机器并且用新的内核来引导了。
7 现在做什么?
7.1 保存内核
如果我们使用了--append-to-version,我们就不需要担心apt-get会试着更新我们的内核了。如果我们是偏狂的人,我们可用root运行下面的命令:
bash:~# echo "kernel-image-2.4.18.030320 hold" | dpkg --set-selections
当然在这里我们要用我们实际的内核名来代替。我们可以用下面的命令来进行查询:
bash:~# dpkg --get-selections | grep kernel-image
kernel-image-2.4.18.0303200 hold
7.2 移除符号链接
我们可以用下面的命令来操作:
bash:~# cd /usr/src
bash:/usr/src# rm linux
7.3 备份我们的内核
当然这并不是必须的,但是备份我们自己的内核确实是一个好主意。
7.4 创建一个新的启动盘
为我们刚安装的内核创建一个新的启动盘:
bash:/usr/src# cd /boot
bash:/boot# mkboot /boot/vmlinuz-2.4.18.030320
7.5 移除旧内核
现在我们已经看到编译安装一个新内核是一件多么简单的事情,过不了多久的时间我们的/boot目录就会变得拥挤。我们可以使用dpkg来清除我们不需要的内核:
bash:/boot# dpkg -P kernel-image-2.4.18.030309
如果我们得到"/lib/modules/2.4.18.030309 is not empty so wasn't removed"的信息,也许是因为我们在那里安装了第三方模块。我们可以用类似于下面的命令来进行删除:
bash:/boot# dpkg -P pcmcia-modules-2.4.18.030309
如果我们的模块子目录仍然非空,也许是我们并没有使用make-kpkg来编译这些模块。我们可以手动来进行删除。
7.6 编译我们下一个内核
如
果我们因为新买了一个声卡而希望重新编译我们的内核,或者是我们希望使用一个新的特征,这时我们所要做的只是重新配置,执行"fakeroot
make-kpkg clean",然后使用不同的--append-to-version值来重新进行编译。我们的会话看起来如下面的样子:
bash:~$ cd /usr/src
bash:/usr/src$ ln -s kernel-source-2.4.18 linux
bash:/usr/src$ cd linux
bash:/usr/src/linux$ make xconfig
> (reconfigure your kernel)
bash:/usr/src/linux$ fakeroot make-kpkg clean
> (lots of cleaning here)
bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401 kernel_image
> (screens and screens of stuff)
8 高级主题
8.1 第三方模块
在这里我所谓的第三方模块是在内核源码树以外以源码的形式使用的内核模块。一个很好的例子就是pcmcia-cs,这是许多的笔记本用户所需要的对于PCMCIA的支持。
要
使用pcmcia-cs,可以使用apt-get来安装pcmcia-source软件包。这个源码包必须放在/usr/src目录下。以普通用户的身份
将源码包解压到/usr/src/modules/pcmcia-cs目录下。如果我们并没有这个模块目录,我们可以手动创建一个。
当我们配置我们的内核时,需要禁止PCMCIA支持。(如果我们打开了PCMCIA的支持,pcmcia-cs不会编译驱动)。如果我们要使用无线LAN,我们可以在 NetWork decive support下打开这个支持,但是不要选择任何设备。
当我们要准备好编译我们的内核时,我们可以在我们的命令行中加入modules_image:
bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401 kernel_image modules_image
当
我们创建了kernel_image
的deb安装包,make-kpkg会进入/usr/src/modules目录为每一个子目录编译一个模块的deb安装包,这个安装包将会与我们的内核
有着相同的version与--append-to-version.在我们安装了kernel_image的deb包以后我们就可以安装这些模块的
deb安装包了。
8.2 要已经存在的内核中加入第三方模块
当我们浏览Debian用户列表时,我们就会发现越来越多的人对alsa感兴
趣。而我们发现我们的声卡的声音听起来并不是很好,我们想要亲自试一下alsa。我们可以很熟练的使用make
menuconfig来进行配置,但是在Sound部分我们却并没有看到任何标为alsa的内容。怎么办?
安装alsa-source软件包。这时我们就会在/usr/src目录下有一个新的tar包。如下:
bash:/usr/src$ ls
alsa-driver.tar.bz2
kernel-image-2.4.18.030401_10.00.Custom_i386.deb
kernel-source-2.4.18
kernel-source-2.4.18.tar.bz2
modules
pcmcia-modules-2.4.18.030401_3.1.33-6+10.00.Custom_i386.deb
解压alsa-driver并且重新创建符号链接。这时我们要注意我们内核镜像的--append-to-version的值。我们需要将他作为make-kpkg的选项。
bash:/usr/src$ cd linux
bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401
--added-modules=alsa-driver modules_image
注意:在这里我们并不需要kernel_image的target。除非是我们重新配置了我们的内核,否则我们没有必要重新进行编译。使用"--added-modules"选项可以使得我们只编译我们需要的模块,而不是所有的模块。
8.3 Debian内核补丁
Debian提供了各种各样的内核补丁。根据需要,在这里我们下载了kernel-patch-debianlogo.
要安装一人内核补丁并不需要执行补丁。这可以通过调用make-kpkg,使用"--added-patches"选项来实现:
bash:/usr/src/linux$ fakeroot make-kpkg --append-to-version=.030401
--added-patches=debianlogo kernel_image modules_image
如果我们有多个内核补丁,我们可以在"--added-patches="后用逗号分隔列出多个补丁。
在
默认的情况下make-kpkg会运行"make
oldconfig"来执行内核补丁。如果我们的补丁中包含新内核的选项,系统就会向我们询问相关的内容。如果我们要查看整个内核配置选项,我们可以使用
另一个命令行选项,"--config=menuconfig".当我们保存我们的配置并退出后,make-kpkg将会继续执行。
在我们的内核镜像创建以后,make-kpkg会保留我们所执行的补丁,所以在每一个配置/编译循环中我们都会有一个未打过补丁的源码树。