Linux 内核安装
对于许多用户来说,Linux 是他们接触真正强大、可配置的操作系统的入门。过去,类 Unix 操作系统对大多数人来说遥不可及。如果不是操作系统四位数的标价,那就是硬件。即使是现在免费供个人使用的 SCO Unixware 也需要配备 SCSI 驱动器的系统,而我们大多数人为了降低成本都在使用 IDE。Linux 带来的强大功能也带来了一项任务,用户在更简单的操作系统上不必执行这项任务:根据您的硬件和操作配置内核。
来自 1.2.x 及更早版本的先前安装内核建议您重新构建;然而,对于新的 2.0.x 内核,重新构建几乎已成为必然。来自 Red Hat、Caldera、Debian 和大多数其他发行版的安装包附带的内核是一个通用的“几乎包含所有内容”的内核。虽然重新构建内核似乎是一项艰巨的任务,并且使用已安装的内核可能还不错,但重新构建是了解您的系统的一个很好的入门。
标准安装内核旨在使尽可能多的系统可用于安装可用的 Linux 系统。因此,内核臃肿,并且对于普通机器来说包含许多不必要的代码。它也没有许多用户想要的一些代码。
当然,总是需要升级内核,因为您购买了新硬件等等。在同一系列中升级通常非常简单。当涉及到升级时,例如从 1.2.something 升级到 2.0.something,现在的任务超出了本文的范围,并且需要一些技巧。最好获取新的发行版 CD 并重新开始——这对于升级到实验性的 2.1.x 内核也是如此。
所有 Linux 内核版本号都包含三个数字,用句点(点)分隔。第一个数字是内核版本。我们现在处于第三个内核版本,2。你们中的一些人可能正在运行版本 1 内核,并且我知道至少有一个运行版本 0 内核。
第二个数字是内核主版本号。主版本号为偶数(0 被认为是偶数)被认为是稳定的。也就是说,这些内核不应该有任何严重的错误,因为它们已经过相当严格的测试。虽然有些包含小错误,但它们通常可以升级以获得硬件兼容性或保护内核免受系统破解者的攻击。例如,内核 2.0.30 因报告的错误而被一些人避开,转而支持 2.0.29,但它包含多个补丁,包括一个用于防止 SYN 拒绝服务攻击的补丁。主版本号为奇数的内核是开发内核。这些内核未经测试,并且通常会破坏您可能正在运行的任何软件包。偶尔,有一个内核工作得足够好,以至于会被需要在下一个稳定版本之前获得最新和最强大支持的用户采用。这是例外而不是规则,并且需要对系统进行重大更改。
最后一个数字是次版本号,每次发布增加 1。如果您看到内核版本 2.0.8,您就知道它是内核 2.0、稳定内核,并且是第九个版本(我们从 0 开始计数)。
我讨厌做任何假设;它们似乎总是会反咬我一口。所以我需要提及一些事情,以便我们使用同一张乐谱。为了编译内核,您需要一些东西。首先,我假设您已安装了带有 2.0.x 内核的发行版、所有基本软件包以及可能更多。您还需要安装 gcc 版本 2.7 和所有支持 gcc 库。您还需要 libc-dev 库以及 binutils 和 bin86 软件包(通常作为标准发行版安装的一部分安装)。如果您下载源代码或从 CD 复制源代码,您还需要 tar 和 gunzip 软件包。此外,您还需要大量的磁盘空间。计划下载 7MB,解压缩这个怪物需要另外 20MB,编译它还需要更多。
不用说,我们将讨论的许多事情都需要您以 root 身份登录。如果您以非特权用户身份下载了内核,并且您对 /usr/src 子目录具有写入权限,您仍然可以在不成为 root 用户的情况下完成此任务的大部分工作。对于 Linux 新手,我强烈建议您尽可能以非特权用户身份执行操作,并且仅在需要 root 权限的作业时才成为 root 用户(键入:su - face)。总有一天,您会庆幸自己养成了这个习惯。请记住,系统管理员有两种,一种是无意中以 root 身份登录时完全破坏了正在运行的设置的人,另一种是将会这样做的人。
Linux 的内核源代码可以从大量的 ftp 站点获得,并且几乎在每个 Linux 发行版 CD-ROM 上都有。对于初学者,您可以访问 ftp.funet.fi,这是 Linux 内核的主要站点。该站点列出了您可以从中下载内核的镜像站点列表。选择离您最近的站点有助于减少整体互联网流量。
获得源代码后,将其放在 /usr/src 目录中。创建一个子目录以在解压缩 tar 后保存源文件。我建议将目录命名为类似 linux-2.0.30 或 kernel-2.0.30 的名称,替换您的版本号。使用以下命令创建指向此子目录的链接,名为 linux
ln -sf linux-2.0.30 linux
我在链接命令中包含了 -f,因为如果您已经在 /usr/src 中有内核源代码,它也会包含此链接,并且我们希望强制它查找我们的子目录。1 唯一可能遇到问题的情况是 linux 是子目录名称,而不是链接。如果您遇到此问题,您必须在继续之前重命名子目录
mv linux linux-2.0.8现在发出命令
tar xzvf linux-kernel-source.tar.gz我有一个习惯,总是在 tar 选项字符串中包含 w(等待确认),然后当我看到 .tar.gz 或 .tgz 文件将解压缩到其自己的子目录中时,我 ctrl-C 退出并重新发出不带 w 的命令。这样我可以防止损坏的存档解压缩到当前目录中。
在某些版本的 ln(尤其是版本 3.13)中,force 选项 (-f) 不起作用。您必须先删除链接,然后再重新建立它。这在版本 3.16 中可以正常工作。
解压缩内核后,如果您有任何想要应用的补丁,现在是好时机。假设您不想运行内核 2.0.30,但您想要 tcp-syn-cookies。将补丁(名为 tcp-syn-cookies-patch-1)复制到 /usr/src 目录并发出命令
patch < tcp-syn-cookies-patch-1
此命令将补丁应用于内核。在 /usr/src 目录中查找带有 .rej 扩展名的文件。这些文件未正确修补。它们可能并不重要,但无论如何都要仔细阅读它们。如果您安装了 Red Hat 系统,其中包含一些但不是全部内核源代码(SPARC、PowerPC 等),您将看到其中一些文件。只要它们不是针对您的架构,您就没问题。
最后,在我们更改 (cd) 到内核源代码目录并开始构建新内核之前,让我们检查一些需要的链接。在您的 /usr/include 目录中,确保您具有以下软链接
asm - /usr/src/linux/include/asm linux - /usr/src/linux/include/linux scsi - /usr/src/linux/include/scsi
现在,您看到了标准化内核位置的另一个原因。如果您没有将您希望安装的最新内核放在 /usr/src/linux 中(通过链接),则上述链接将无法到达其预期目标(悬空链接),并且内核可能无法编译。
完成所有其他设置后,将目录更改为 /usr/src/linux。尽管您可能想停下来仔细阅读 Documentation 目录中的一些文档,特别是如果您有任何特殊的硬件需求。此外,一些 CD-ROM 驱动程序需要使用自定义设置构建。虽然它们通常可以按原样工作,但这些驱动程序在加载时可能会发出警告消息。如果这不会困扰您并且它们按应有的方式工作,请不要担心。否则,请阅读相应的 .txt、.h(头文件)和 .c(c 代码)文件。在大多数情况下,我发现它们的注释很完善并且易于配置。如果您没有勇气,您不必这样做。只需记住,您始终可以通过再次解压缩 gzipped tar 文件(或重新安装 .rpm 文件)来恢复原始文件。
现在,您已准备好配置内核。在开始之前,您需要了解一些关于模块的知识。将模块视为您可以插入内核以用于特殊目的的东西。如果您在家中有一个小型网络,并且有时想要使用它(但并非总是如此),也许您会想要将您的以太网卡编译为模块。要使用模块,机器必须正在运行并且可以访问 /lib/modules。这意味着驱动器(IDE、SCSI 等,但在 nfs 的情况下可以是网卡),文件系统(通常是 ext2,但可以是 nfs)和内核类型(希望是 elf)必须编译到内核中,并且不能是模块。模块在内核加载、驱动器(或网络)访问和文件系统挂载之前不可用。这些文件必须编译到内核中,否则它将无法挂载根分区。如果您通过网络挂载根分区,您将需要网络文件系统模块和编译的以太网卡。
为什么要使用模块?模块使内核更小。这减少了内核永远不会放弃的受保护空间量。模块加载和卸载,并且可以重新分配该内存。如果您在机器启动时间的 90% 以上的时间里使用模块,请编译它。在这种情况下使用模块可能会浪费内存,因为虽然模块占用的内存量与编译时相同,但内核需要更多代码来为模块提供挂钩。话虽如此,我并不经常遵循自己的建议。我仅编译:ext2、IDE 和 elf 支持。虽然我几乎一直使用以太网卡,但我将其他所有内容都编译为模块:a.out、java、软盘、iso9660、msdos、minix、vfat、smb、nfs、smc-ultra(以太网卡)、串行、打印机、声音、ppp 等。其中许多只在这里和那里运行几分钟。
下一步是配置内核。在这里我们有三种选择——虽然所有选择都做同样的事情,但我建议使用图形方法之一。旧方法是简单地键入:make config。这将开始一系列漫长的问题。但是,如果您犯了错误,您唯一的选择是按 ctrl-C 并重新开始。您也无法在序列中后退,并且一些问题取决于之前的答案。如果由于某种原因您绝对不能使用任何一种图形方法,请随意使用。
我建议使用 make menuconfig 或 make xconfig。为了使用 menuconfig,您必须安装 ncurses-dev 和 tk4-dev 库。如果您没有安装它们并且您不想使用下一种方法,我强烈建议您现在安装它们。您始终可以稍后卸载它们。
要运行 make xconfig,您必须安装和配置 X。由于 X 非常占用内存,因此我仅在此过程的这一部分安装、配置和 startx,在内核编译时返回到控制台,以便它可以拥有所需的所有内存。在我看来,xconfig 菜单是配置内核的最佳和最简单的方法。在 menuconfig 下,如果您禁用一个选项,则不会显示任何从属选项。在 xconfig 下,如果您禁用一个选项,从属选项仍然显示,它们只是灰色的。我喜欢这样,因为我可以查看自上次内核以来添加了什么。我可能想要启用一个选项以获得其中一个新的子选项以便进行实验。
我将在这里占用一些空间来描述内核配置中的各个部分,并告诉您我发现的一些事情——主要是通过艰苦的方式。
第一部分是代码成熟度级别选项。唯一的问题是您是否要使用开发驱动程序和代码。如果您有一些尖端硬件,您可能别无选择。如果您选择“否”,则实验代码将灰显或不显示。如果您将此内核用于商业生产目的,您可能需要选择“否”。
第二部分涉及模块。如果您想要模块,请对问题 1 和 3 选择“是”。如果您想使用某些发行版(例如 Caldera 的 OpenLinux 用于其 Netware 支持)附带的专有模块,也请对第二个问题回答“是”,因为您将无法重新编译该模块。
第三部分是一般设置。请将内核编译为 ELF 并编译对 ELF 二进制文件的支持。不编译正确的支持是一个明确的“陷阱”。您可以获得更高效的代码,为机器的特定架构(奔腾或 486)编译内核,但 386 内核将在任何 32 位 Intel 兼容克隆中运行;奔腾内核则不会。大量计算机的紧急启动盘(以及发行版安装盘)最好编译为 386。但是,386 将无法运行为奔腾编译的内核。
接下来是块设备——这里没有什么特别的。如果您的根设备位于 IDE 驱动器上,只需确保您编译它即可。
然后是网络。对于未连接到网络的计算机,除非您计划使用一台计算机拨出,而其他计算机通过它连接,否则您在这里不需要太多内容。在这种情况下,您需要阅读有关伪装之类的内容,并遵循建议的指南。
SCSI 支持是下一个,尽管我不知道为什么它不直接跟随块设备。如果您的根分区位于 SCSI 设备上,请不要为 SCSI 支持选择模块。
SCSI 低级驱动程序跟随通用 SCSI 支持。同样,模块仅适用于不包含根分区的设备。
下一部分将我们带回网络。期待在这里为您的特定卡以及一些其他支持(例如 ppp、slip 等)进行大量查找。如果您使用 nfs 挂载您的根设备,请编译以太网支持。
对于那些幸运到需要 ISDN 支持的人,将需要完成 ISDN 子部分。
较旧的 CD-ROM 可能需要下一部分的支持。如果您使用的是 SCSI 或 IDE CD-ROM,则可以跳过此部分。
接下来是文件系统。同样,编译您需要的内容,在大多数情况下是 ext2,并对其余部分使用模块。
接下来选择字符设备。支持非串行鼠标,如 PS/2 鼠标。查看鼠标底部。许多双按钮鼠标都是 PS/2 类型,即使它们看起来和连接起来都像串行鼠标。您几乎肯定需要串行支持(通用)作为最低要求。通用打印机支持也在此处列出。
倒数第二部分通常是最麻烦的部分:声音。从列表中仔细选择并阅读可用的帮助。确保您为您的卡选择了正确的 I/O 基地址和 IRQ。SoundBlaster 卡的 MPU I/O 基地址列为 0。这通常是 330,如果此值不正确,您的声音模块会抱怨。别担心。关于模块的好处之一是,只要内核是使用挂钩编译的,您就可以重新编译和重新安装模块。(模块不是很棒吗?)。
最后一部分包含一个问题,可能应该回答“否,内核黑客”。
保存您的配置并退出。
在某些情况下,我在 menuconfig 或 xconfig 中编辑数字以达到我知道是正确的值时遇到问题。无论出于何种原因,我都无法更改数字,或者 config 不接受该数字,告诉我它是无效的。例如,将 SoundBlaster IRQ 从 config 默认值 7 更改为 5,并将 MPU 基地址 I/O 从 0 更改为 300。如果您遇到此问题,但其他一切都进展顺利,请不要绝望。当您执行“保存”和“退出”时,您刚刚写入的文件是一个可编辑的文本文件。您可以使用您选择的文本编辑器:Emacs、vi、CrispLite、joe 等。您的配置文件位于 /usr/src/linux 目录中,名为 .config。前导点会导致文件在正常目录列表 (ls) 期间隐藏,但在指定 -a 选项时会显示。只需编辑此文件中您在配置过程中遇到问题的数字即可。接下来,键入 make dep 以将您的配置从 .config 文件传播到正确的子目录并完成设置。最后,键入 make clean 以准备最终内核构建。
我们现在准备开始构建内核。有几个选项可以完成此任务
make zImage:制作基本的压缩内核,并将其留在 /usr/src/linux/arch/i386/boot 目录中,作为 zImage。
make zlilo:将 zImage 复制到根目录(除非您编辑了顶层 Makefile)并运行 LILO。如果您选择使用此选项,您必须确保 /etc/lilo.conf 已预先配置。
make zdisk:将 zImage 写入 /dev/fd0 中的软盘(第一个软盘驱动器——DOS 中的 a: 驱动器)。您需要在启动之前将磁盘放在驱动器中。您可以通过运行 make zImage 并将映像复制到软盘 cp /usr/src/linux/arch/i386/boot/zImage /dev/fd0 来完成相同的操作。请注意,您需要使用高密度磁盘。据报道,低密度 720k 磁盘将无法启动内核。
make boot:与 zImage 选项的工作方式相同。
make bzImage:用于大型内核,操作方式与 zImage 相同。如果您需要此选项,您将会知道,因为 make 将失败并显示映像太大的消息。
make bzdisk:用于大型内核,操作方式与 zdisk 相同。如果您需要此选项,您将会知道,因为 make 将失败并显示映像太大的消息。
还有其他 make 选项可用,但它们是专门的,并且此处未涵盖。此外,如果您需要专门的支持,例如 RAM 磁盘或 SMP,请阅读相应的文档并相应地编辑 /usr/src/linux 中的 Makefile(也称为顶层 Makefile)。由于我上面讨论的所有选项基本上都与 zImage 选项相同,因此本文的其余部分将讨论 make zImage——这是构建内核的最简单方法。
对于那些希望加快进程并且不会做其他事情(例如配置其他应用程序)的人,我建议您查看 make 的手册页并尝试使用 -j 选项(可能限制为 5)以及 -l 选项。
如果您在配置过程中选择了模块,您将需要发出命令
make modules make modules_install
将模块放在其默认位置 /lib/modules/2.0.x/ 中,x 是内核次版本号。如果您已经有此子目录,并且它具有 block、net、scsi、cdrom 等子目录,您可能需要删除 2.0.x 及其下方的所有内容,除非您安装了一些专有模块,在这种情况下不要删除它。安装模块后,将创建并填充子目录。
您可以轻松地组合最后三个命令
make zImage; make modules; make modules_install
然后在所有磁盘搅动完成后返回。;(分号)字符分隔一行上的顺序命令,并按顺序执行每个命令,这样您就不必仅仅为了发出下一个命令而等待。
构建内核并安装模块后,我们还有一些项目需要处理。首先,将您的内核复制到根目录(或 /boot/ 或 /etc/,如果您愿意)
cp /usr/src/linux/arch/i386/boot/zImage /zImage
您还应该将 /usr/src/linux/System.map 文件复制到与内核映像相同的目录。然后更改 (cd) 到 /etc 目录以配置 LILO。这是一个非常重要的步骤。如果我们不安装指向新内核的指针,它将无法启动。通常,安装内核称为 vmlinuz。老式的 Unix 用户会认出这个名称的构造。“z”后缀表示映像已压缩。“v”和“m”也具有重要意义,分别表示“虚拟”和“粘性”,并且与内存和磁盘管理有关。我建议您保留 vmlinuz 内核,因为您知道它可以工作。
编辑 /etc/lilo.conf 文件以添加您的新内核。使用从 image=/vmlinuz 行到下一个 image= 行或结尾的行。复制您看到的内容,然后将第一行更改为 image=/zImage(假设您的内核位于根目录中),并为 label= 选择不同的名称。文件中的第一个映像是默认映像,其他映像必须在命令行上指定才能启动它们。保存文件并键入
lilo
您现在将看到内核标签,第一个标签将带有一个星号。如果您没有看到您为新内核提供的标签,或者 LILO 终止并出现错误,您将需要重做 /etc/lilo.conf 中的工作(请参阅 LILO 手册页)。
我们几乎准备好重新启动。此时,如果您知道您的系统只需重新启动一次即可正常运行,您可能需要发出命令
depmod -a 2.0.x
其中 x 是您刚刚构建的内核的次版本号。此命令创建某些模块需要的依赖项文件。您还需要确保您没有直接启动到 xdm。对于 Red Hat 类型系统,这意味着确保 /etc/inittab 文件没有默认运行级别 5,或者您记得在启动时将运行级别传递给 LILO。对于 Debian 系统,您可以只键入
mv /etc/init.d/xdm /etc/init.d/xdm.orig现在,稍后将其移回。
使用以下命令重新启动您的机器
shutdown -r now
虽然键入 reboot 或按 ctrl+alt+del 键组合通常有效,但我建议不要使用其中任何一个。在某些情况下,文件系统将无法正确卸载,并且可能会损坏打开的文件。在 LILO 提示符下,如果您需要启动旧内核或传递一些启动参数,并且您没有看到 boot: 提示符,您可以尝试按 shift 或 ctrl 键,boot: 提示符应该会出现。一旦您有了它,请按 tab 以查看可用的内核标签。键入标签,并可选择输入任何启动参数。但是,通常,默认内核应在 /etc/lilo.conf 文件中指定的超时时间间隔后自动启动。在启动期间,您可能会看到一些包含以下内容错误消息:SIOCADDR 或类似内容。这些通常表明模块(通常是网络模块)未加载。我们稍后会处理这个问题。如果您收到错误“VFS,无法挂载根”,则您没有将正确的磁盘或文件系统支持编译到内核中。
由于每个发行版处理来自 /etc/inittab 的守护程序启动的方式不同,因此本文很难涵盖您的启动可能未顺利进行的所有可能原因以及原因。但是,我可以告诉您从哪里开始查找。
首先,运行 depmod -a 以确保您有一个最新的模块依赖项文件(它将在相应的子目录中创建)。如果您收到一连串关于未解决依赖项的错误,则模块子目录中存在旧模块,并且您没有启用“模块版本”配置内核。这不是致命错误。您编译和安装的模块是好的。检查 /etc/conf.modules 文件,并确保任何指向 /lib/modules 的行都已完成
/lib/modules/`uname -r`/xx
(注意:uname -r 两侧的重音符位于美国键盘上键盘左上角的 Tab 键上方)。
确保 kerneld 正在运行,并且它在启动过程中很早就加载。如果是这样,则系统不需要显式加载模块,kerneld 将处理它。小心不要在第一个 rc 脚本中过早调用 kerneld。如果 kerneld 在系统知道其主机名之前被调用,kerneld 将停止启动过程,强制通过复位按钮或电源开关进行硬重启。如果您遇到这种情况,您可以重新启动,将 -b 参数传递给 LILO,这会阻止 init 执行任何 rc 脚本。接下来,查看 /etc/rc.d/ 中的 rc、rc.sysinit 和 rc.modules 文件。一个或多个可能指向一个目录,例如 /etc/modules/`uname -r`/`uname -v`,其中包含启动模块列表。您可以将旧文件复制到新目录;
mkdir /etc/modules/`uname -r` ; cp /etc/modules/2.0.xx/g#1 Thu 3 Sep 1997.\ default /etc/modules/`uname -r`/\ `uname -v`.default""
您的系统的模块文件几乎肯定会有不同的日期。您的系统也可能使用或不使用默认扩展名。请密切注意以上示例中重音符和双引号的使用,因为在正确的位置都需要它们。一旦您找到了系统的密钥,您应该能够重新启动进入正常运行的系统。如果您遇到进一步的问题,获取快速专家建议的最佳地点是专门针对您的特定发行版的邮件列表。那些成功运行特定发行版的人通常乐于帮助新手解决他们可能遇到的问题。为什么?因为当他们是新手时,他们也遇到了同样的难题,并在许多问题上获得了帮助。在列表上潜伏几天,如果您的问题没有被其他人问到,请自己提出。首先检查邮件列表存档(如果有)。这些存档包含常见问题解答 (FAQ)。
David Bandel 是一名计算机网络顾问,专门从事 Linux,但他也勉强使用 Windows 和那些“真正的”Unix 机器,如 DEC 5000 和 Suns。当他不工作时,他可以黑掉自己的系统,或者在飞机上从 2,500 英尺的高度欣赏西雅图的景色。他欢迎您的评论、批评、俏皮话,并将很乐意进一步混淆这个问题。您可以通过电子邮件 dbandel@ix.netcom.com 或蜗牛邮件 c/o Linux Journal 与他联系。