Ubuntu/Debian 中的自定义内核 - 如何、何时以及为何
因此,您决定尝试一下您听到其他人谈论的事情,称为“编译自定义内核”。如果您将此作为一种爱好,或者因为您想学习一项新技能,那么很好 - 请继续阅读。
然而,在开始之前,我们将尝试解释何时出现这种需求以及如何处理。请注意,这是一个广泛的主题,需要的空间比我们在这里提供的要多得多。您将学习基础知识、您需要什么、该做什么以及您将实现什么。
如欲了解更多信息,像往常一样,Google 是您的朋友;此外,驻留在内核源代码树中的文档将回答很多问题。因此,让我们从头开始,最后一点:如果需要,我们将发布更多与其他发行版的内核编译相关的文章。
第一种情况是当您需要比您的发行版提供的内核更新的内核时,尤其是当您运行稳定的发行版(例如 Debian stable、CentOS)时,因为您的内核不支持您需要的某些功能/驱动程序,或者只是因为您觉得你想尝试最新最好的。
但是警告:如果您想运行前沿内核,请确保它将与系统的其他关键组件(例如 glibc)兼容,请记住,更新意味着测试更少,并且(可能) 更加不稳定;您的发行版的内核维护人员通常会很好地将一些新功能向后移植到较旧的、更稳定的内核,因此请确保您确实需要前沿技术。我们的建议是不要在生产系统上使用这些内核(长期内核在这里例外)。如前所述,相信您的发行版的维护者。
第二种情况是,您感觉正在运行一个臃肿的内核,其中有很多不需要的组件。虽然内核仅加载与现有硬件匹配的模块,但较小的内核内存占用通常有助于提高速度和缩短启动时间。
# lspci -vv
# lsusb
# hwinfo
# cat /proc/cpuinfo
以上命令可以帮助您更好地了解您的硬件。写下您发现的内容,并确保以 root 身份运行上面的 ls* 命令,以获取更多信息。
另一种情况是您想通过在系统上运行最新版本来帮助测试内核。与上面相同的警告也适用:在测试系统上执行此操作,与上游保持联系,以防发现错误(lkml.org 是主要内核邮件列表 - 高流量),并在询问信息时尝试尽可能提供帮助.这一点怎么强调都不为过:阅读文档,要么是因为您发现自己处于不利的境地,想要报告错误,要么只是有疑问。
接下来,您可能想成为街区中的酷孩子并运行最新和最好的,也许浏览一下源代码(前提是您对此感兴趣并且您有一些 C 和 ASM 知识),甚至提交补丁。如果您的发行版尚未提供更新的内核软件包,您可能需要首先查看,例如,如果您相应地更改您的sources.list,您可以在测试系统上安装来自 Debian 实验版的内核。再次强调,如果您偶然发现错误,请与维护人员合作。
在我们进一步深入研究这个有点神秘的主题之前,我们应该明确一些基本术语(呃);这对于理解内核测试和编译的关键部分至关重要。
内核 - 操作系统的核心,负责管理硬件资源(I/O、网络、CPU、内存……)。基本上,它是操作系统的重要部分,负责所有肮脏的工作。用户程序与内核进行通信,通过充当用户空间(见下文)和内核/硬件之间中介的系统库请求 CPU 时间或其他资源。内核可以是单片内核和微内核(如果您有兴趣,请参阅 Wikipedia.org 上的内核范围设计方法了解更多信息。微内核(如 Minix)使用将内核与内核其余部分分开的设计方案,并且其余部分分为组件,每个组件执行特定的操作:I/O、网络等。单片内核(Linux、BSD、Solaris),顾名思义,在一个单元中包含大部分内核,具有额外的功能(例如驱动程序) )由模块提供。还有混合内核,即两者的组合,一个很好的例子是 Windows 内核。
用户区-操作系统中不属于内核的所有内容(库、应用程序)都被认为是用户区的一部分。这名字就这么明显了
模块 - 如前所述,内核模块是一个二进制软件,基本上“教”内核如何与硬件“对话”或提供某些功能(例如 nfs)
编译器 - 编译器是一个应用程序,它基本上采用从 kernel.org 下载的书面代码,并将其转换为二进制文件。 Linux 发行版中的编译器称为“gcc”,代表 GNU 编译器集合,它还需要构建软件所必需的组件:binutils 中的实用程序,如汇编器 (as) 或库归档器 (ar)。在 Debian 系统上,或者Ubuntu,可以通过安装并运行apt-file来查找文件属于哪个包。说到这里,让我们看看我们需要安装哪些软件包才能成功构建内核。
vanilla kernel -这是上游内核使用的名称,可以在 kernel.org 上找到,因此没有特定于发行版的补丁。
请注意,每当您在本文档中看到以提示符 ‘$’ 开头的命令时,这意味着该命令必须以普通的日常用户身份运行;每当您看到 ‘#’ 提示符时,这意味着该命令将以 root 身份运行(我们使用 sudo,但这不是强制性的)。除非另有指定,否则当前目录是保存源代码树的目录,在本例中为 linux-2.6。
gcc——当然编译器是必不可少的
binutils – 该软件包包含链接器、汇编器和其他对于编译用 C 编写的程序至关重要的实用程序。
gcc-doc – gcc 的手册和信息页面。如果你想弄脏并修改一些编译标志,这很有用。如果您想编写或编译 C 软件包,无论如何很有用。
gdb – GNU 调试器。不是强制性的,但如果出现问题很有用。 Gdb-doc 也会有帮助。
libreadline5-dev – 用于使用基于 ncurses 的内核配置接口。您可以使用其他接口(见下文)。
make – 将作为依赖项安装,但很少有话要说。请参阅手册或书籍,因为这不是一个可以在如此短的时间内轻松解释的主题。 Make 是编译 C/C++ 程序时使用的实用程序,它的作用是在 Makefile 中查找,其中包含有关构建应如何以及以什么顺序发生的规则,并尝试执行这些指令。阅读源代码树中的 Makefiles 来了解一下。
git – Git 是一个 VCS(版本控制系统),执行 cvs 或 subversion 的功能,即让您了解最新的内核树。
如果您想从您的发行版安装源代码,请使用
# apt-get install linux-source-<version>
其中
uname -r
如果您想修改现有内核(添加驱动程序、修剪等),请使用此选项。否则,你需要香草内核。您可以从 www.kernel.org 获取它(我们建议使用 wget 或curl 作为下载管理器),或者,如果您想要最新的,您将使用 git。我们建议将源代码存储在用户的主目录中,获取最新主线树的命令是(请参阅 man git ):
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6
过去,我们发现 http://linux.yyz.us/git-howto.html 上的迷你指南很有用;还可以查看 kernelnewbies.org 。上面的命令将在当前目录中创建一个名为 linux-2.6 的文件夹,稍后可以通过 cd 进入该文件夹并发出简单的命令来更新该文件夹
make clean; git pull
现在,获得源代码后,我们必须配置内核。
如果您有现有的 .config 文件(该文件包含内核构建选项 - 哪些内容包含在内,哪些内容不包含在内),请将其复制到 linux-2.6 中(从 /boot/config-
$ make oldconfig
否则,请继续阅读。如果要修改现有配置,请发出
$ make menuconfig
(建议:您可以使用 make config 来解决有关内核中选项的许多问题,或者使用 make xconfig ,它需要 qt 库,以获得更好的图形菜单),然后选择“加载备用配置文件”并按 Enter 键打开 .config ,配置文件的默认名称,或输入已保存在 linux-2.6 中的替代文件名。
之后,开始浏览菜单以进行必要的更改这里的经验法则是“如果您不知道它的作用,请不要乱搞它”,至少在您获得一些经验之前是这样。最后,从顶部菜单中选择“保存备用配置文件”,按 Enter 键输入默认名称(.config – 推荐),然后从下面选择“退出”。如果您想从头开始,请忘记“加载备用配置文件”步骤并继续。在下一次内核编译时,清理和更新树后,使用上面的“make oldconfig”来使用旧配置。好的,现在我们已经根据我们的需求定制了配置,等待构建。构建内核就像配置它一样简单(!)。只需输入 make ,输出应如下所示:
$ make
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/zconf.lex.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
CHK include/linux/version.h
UPD include/linux/version.h
CHK include/generated/utsrelease.h
UPD include/generated/utsrelease.h
CC kernel/bounds.s
GEN include/generated/bounds.h
CC arch/x86/kernel/asm-offsets.s
...
过了一段时间,根据您的机器和内核配置,它就会完成。如果你想加快速度,请使用 -jn 标志来 make,其中 n 是处理器/内核的数量 + 1。但是要小心,这可能会暴露内核或构建基础设施中的错误,因此如果出现问题,仅使用不带任何标志的 make 重试。如果在阅读 gcc 手册后(如果您仍然理智),您觉得有冒险精神并且想要修改一些特定于硬件的标志,或者想要优化代码,请使用 make 手册页来了解如何操作(主要是 COPTS 和 CFLAGS )。然而,大于 -O2 的优化是有风险的。
小心并做好破损的准备,内核可能会毫无问题地编译,但它可能会表现得很奇怪。请记住以普通用户身份输入所有命令。不需要以 root 身份进行构建,并且内核开发人员不赞成这个想法。
现在让我们安装模块:这需要以 root 身份完成,因为模块安装在 /lib 中,而普通用户在那里没有写访问权限。所以,
# make modules_install
就是这样做的,这需要在安装内核之前完成,以便模块和安装的内核同步。使用
# make install
将内核安装到/boot,然后
# depmod
并准备创建 initramfs(初始 RAM 文件系统),它是在早期启动阶段加载到 RAM 的临时文件系统,用于提供基本驱动程序和其他设施,以便安装根文件系统。更多信息可以在 Wikipedia 的 Initrd 页面找到。该任务所需的命令是 update-initramfs (每当安装新内核时也会调用该命令,由包管理器触发),它可以创建 initramfs ( -c ) 或更新现有 initramfs ( -u )。完整的命令是
# update-initramfs -c -k
该版本是“make module_install”完成后您将看到的版本(其输出的最后一行将是“DEPMOD”)。如果您想要准确且更长的版本号,那么您可以告诉开发人员什么是“git moment”您使用的,发出menuconfig后选择“常规设置”→“自动将版本信息附加到版本字符串”。我的 Ubuntu 系统上的输出如下所示:
update-initramfs: Generating /boot/initrd.img-3.1.0-rc3+
...
更新您的 Grub,以便它注意到您的新内核
# update-grub
在我的 Debian 测试机上,输出如下所示:
Generating grub.cfg ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-3.0.0-1-amd64
Found initrd image: /boot/initrd.img-3.0.0-1-amd64
Found linux image: /boot/vmlinuz-3.0.0-rc6-amd64
Found initrd image: /boot/initrd.img-3.0.0-rc6-amd64
Found linux image: /boot/vmlinuz-2.6.39-07727-gbd1bfe4
Found initrd image: /boot/initrd.img-2.6.39-07727-gbd1bfe4
Found linux image: /boot/vmlinuz-2.6.39-2-amd64
Found initrd image: /boot/initrd.img-2.6.39-2-amd64
Found linux image: /boot/vmlinuz-2.6.39-rc7-amd64
Found initrd image: /boot/initrd.img-2.6.39-rc7-amd64
Found linux image: /boot/vmlinuz-2.6.38.5
Found initrd image: /boot/initrd.img-2.6.38.5
Found linux image: /boot/vmlinuz-2.6.38.4-00001-gfaa8ee7
Found initrd image: /boot/initrd.img-2.6.38.4-00001-gfaa8ee7
Found linux image: /boot/vmlinuz-2.6.38.4
Found initrd image: /boot/initrd.img-2.6.38.4
Found linux image: /boot/vmlinuz-2.6.38-2-amd64
Found initrd image: /boot/initrd.img-2.6.38-2-amd64
Found linux image: /boot/vmlinuz-2.6.32-5-amd64
Found initrd image: /boot/initrd.img-2.6.32-5-amd64
Found memtest86+ image: /memtest86+.bin
Found memtest86+ multiboot image: /memtest86+_multiboot.bin
done
当然,你的输出看起来不会完全相同,但轮廓应该是相同的;最后,请记住:如果您愿意,请在 update-grub 之前编辑 /etc/default/grub 以更改一些选项,然后重新启动计算机以测试新内核。
当您的新内核无法使用时,最常见的情况是您无法首先启动它,或者它启动后没有一些必要的驱动程序(例如网络驱动程序)。通常,update-grub 在编写 grub 菜单文件方面做得很好,但您可能还是想检查一下。如果您通过了 grub,很可能您过于热心,并为系统删除了一个重要的驱动程序,例如与磁盘相关的部分(ATA、SATA、SCSI...),或者可能是 NFS(如果您有安装 NFS 的根)。使用 Google 和其他可能的来源(例如 IRC)启动工作内核并重新配置它。
很可能有人过去已经偶然发现了您的问题,并且您有机会找到答案。如果问题更严重,并且您确信您阅读了有关网络礼仪以及如何发布到内核邮件列表的信息,请善意地询问。那里有很多友善且乐于助人的人,但当你没有完成作业和/或浪费他们的时间时,他们往往不太友善。如果您有一个单独的 /boot,请记住它通常不是很大,并且可能很快就会被内核填满。另外 /lib/modules 往往会在/中积累大量空间,因此请确保不时进行一些清理。请记住,内核是一个复杂的软件,许多原因可能是问题的根源。如果您按照本指南没有遇到任何问题,那么您就可以进行更高级的 Linux 内核配置了。