配置、编译和安装自定义 Linux 内核

gol*_*cks 39 compiling linux-kernel

我想尝试使用我的发行版提供的内核以外的内核——或者来自其他地方,或者是我定制的。这是困难还是危险?

我从哪里开始?

gol*_*cks 53

构建自定义内核可能很耗时——主要是在配置中,因为现代计算机可以在几分钟内完成构建——但是如果您保留当前的工作内核并确保离开它,这并不是特别危险作为通过引导加载程序的选项(请参阅下面的第 6 步)。这样,如果你的新的不起作用,你可以重新启动旧的。

在以下说明中,源代码树中的路径采用形式[src]/whatever,其中[src]是您将源代码安装到的目录,例如/usr/src/linux-3.13.3. 您可能想要做这些事情,su root因为源树在写权限方面应该保持安全(它应该由 root 拥有)。

虽然有些步骤是可选的,但您无论如何都应该阅读它们,因为它们包含理解过程其余部分所需的信息。

  1. 下载并解压源 tarball。

    这些可以从kernel.org 获得。最新版本列在首页上,但如果您查看/pub/目录内部,您会发现一个归档文件一直追溯到 1.0 版。除非您有特殊原因,否则最好选择“最新稳定版”。在撰写本文时,这是一个 74 MB 的tar.xz文件。

    下载 tarball 后,您需要将其解压缩到某处。正常的地方是在/usr/src。将文件放在那里,然后:

    tar -xJf linux-X.X.X.tar.xz
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,个别发行版通常建议您使用它们的源包之一,而不是香草树。 这包含发行版特定的补丁,这对您来说可能重要也可能无关紧要。它还将匹配用于编译一些用户空间工具的内核包含头文件,尽管它们很可能是相同的。

    在 15 年多的构建自定义内核(主要是在 Fedora/Debian/Ubuntu 上)中,我从未在使用 vanilla 1源时遇到问题。然而,这样做并没有太大的区别,除了如果您想要绝对最新的内核,您的发行版可能还没有打包它。 所以最安全的方法仍然是使用发行版包,它应该安装到/usr/src. 我更喜欢最新的稳定版,所以我可以在它推出到发行版之前充当豚鼠:)

  2. 从基本配置开始 [可选]。

    您不必这样做——您可以直接进入并从头开始创建配置。但是,如果您以前从未这样做过,请期待大量的反复试验。这也意味着必须通读大多数选项(有数百个)。更好的选择是使用您现有的配置(如果可用)。如果您使用了发行版源包,它可能已经包含一个[src]/.config文件,因此您可以使用它。否则,请检查/proc/config.gz. 这是 2.6 内核中添加的可选功能。如果存在,将其复制到源树的顶层和gunzip -c config.gz > .config.

如果它不存在,可能是因为这个选项被配置为一个模块。尝试sudo modprobe configs,然后再次检查/proc目录config.gz

发行版配置不是很理想,因为它包含几乎所有可能的硬件驱动程序。这对内核的功能没有多大影响,因为它们是模块,并且其中的大多数永远不会被使用,但是它非常显着地增加了构建所需的时间。它也很尴尬,因为它需要一个 initramfs 来包含某些核心模块(参见下面的第 4 步)。但是,它可能是比默认值更好的起点。

请注意,配置选项会从一个内核版本转移到下一个内核版本,并且当您运行make config以下程序之一时,您.config将首先被解析和更新以匹配新版本。如果配置来自一个非常旧的版本,这可能会导致奇怪的结果,所以在进行配置时要注意。AFAIK 它根本无法正常工作(使用较新版本的配置)。

  1. 创造一个时代.config

    [src]/.config是用于配置内核的文本文件。 不要直接编辑这个文件。更改选项通常不是将 a 替换为YanN等的简单问题;通常有一组相互依赖和分支的可能性。相反,您想使用内核 makefile 中的配置目标之一(意思是,make _____从顶级源目录在命令行上输入):

    • make config是最基本的,但可能不符合大多数人的口味。这是一系列问题——很多问题——如果你改变主意,你必须重新开始。

    • make oldconfig就像make config除了,如果您已经有.config以前版本的一个,将跳过与新选项有关的问题以外的问题。仍然可能有很多这些,其中大部分与您无关,所以我不推荐它。

    • make menuconfig是我(我认为大多数其他人)的首选方法。它构建并执行一个 TUI 界面(将在终端上工作的彩色菜单)。这要求您-dev安装了 ncurses的包。除了可以通过以下方式访问的搜索之外,它是不言自明的/;F1“帮助”提供了当前选项的解释。有一个替代版本,make nconfig具有一些额外的功能,其中 F2 "syminfo" 相当于 menuconfig 的 F1。

    • make xconfig是一个完整的 GUI 界面。这需要安装 Qtqmake-dev包,同样,它是一个编译和构建的程序。如果您以前没有使用过这些,那可能需要大量下载。我更喜欢menuconfigGUI 版本的原因是,在前者中使用连续屏幕显示选项层次结构,而在后者中使用类似手风琴的打开方式。

    您应该(但不必)做的第一件事是添加一个“本地版本”字符串(在General Setup 下)。原因在下面的#5 中提到。

    “迷宫”是描述选项层次结构的好方法,详细了解它远远超出了像这样的问答的范围。如果您想坐下来完成所有事情,请留出数小时。Greg Kroah-Hartman(Linux 内核的长期领导开发人员)有一本关于内核的免费在线书籍(请参阅下面的参考资料),其中包含有关配置的一章,尽管它是在 2006 年编写的。我的建议是从一个合理的基础开始从您当前的发行版内核(按照 #2),然后通过它并取消选中您知道不需要的所有内容。您可能还想将一些“模块”选项更改为“内置”,这将我们带到下一点......

  2. 关于initramfs[可选]

    “initramfs”是内核中内置和/或在启动时加载的压缩文件系统。它的主要目的是包含内核在访问/lib/modules根文件系统中的模块之前需要的模块——例如,包含该文件系统的设备的驱动程序。发行版总是部分地使用这些,因为驱动程序是相互不兼容的,因此不能全部内置到内核中。相反,适合当前系统的那些是从initramfs.

    这很有效并且不代表任何缺点,但是在构建自己的内核时它可能是不必要的复杂化。2 问题 是,如果您不使用 initramfs,则需要确保根文件系统(及其所在设备)的驱动程序已内置到内核中。 在 中menuconfig,这是M(= 模块)选项和*(= 内置)选项之间的区别。如果您没有做到这一点,系统将在引导过程的早期失败。因此,例如,如果您有一个 SATA 硬盘和一个 ext4 根文件系统,那么您需要内置驱动程序。[如果有人能想到任何其他必须具备的东西,请发表评论,我会在这里合并]。

    如果确实要使用initramfs,则必须在“常规设置”中选择适当的选项。有一个骨架引导到创建一个内置于内核[src]/Documentation/filesystems/ramfs-rootfs-initramfs.txt,但要注意的是,发行版不这样做; 他们使用外部 gzipped cpio 文件。但是,该文档确实包含了关于应该放入什么内容的讨论initramfs(请参阅“initramfs 的内容”)。

  3. 构建并安装内核。

    下一步很容易。要制作内核,只需make[src]目录中运行即可。如果您使用的是多核系统,则可以添加-j N以加快速度,其中N是您要专用的内核数 + 1。没有testcheck。完成后,您可以make modules。在快速盒子上,所有这些都应该花费 < 10 分钟。

    如果一切顺利,make INSTALL_MOD_STRIP=1 modules_install. 这将创建一个/lib/modules与内核版本号以及步骤 3 中提到的“本地版本”字符串(如果有)相匹配的目录。如果您没有使用“本地版本”字符串,请注意您是否已经拥有与您依赖的版本相同的内核,因为这些模块将替换那些。3 INSTALL_MOD_STRIP=1是可选的,意义见这里

    然后您可以make install将内核安装到默认位置。不过,我的建议是自己做,以确保现有文件不会被覆盖。查找[src]/arch/[ARCH]/boot名为bzImage4的文件,如果您使用的是 x86 或 x86-64 机器(如果您使用其他机器,[ARCH]则查找x86其他文件)。将其复制/boot并重命名为更具体和信息量更大的内容(无关紧要)。对 做同样的事情[src]/System.map,但根据以下方案重命名:

    System.map-[VERSION]
    
    Run Code Online (Sandbox Code Playgroud)

    这里,[VERSION]完全相同一样在目录中的名称/lib/modules通过创建make modules_install,其中包括“本地版”字符串,如System.map-3.13.3-mykernel

  4. 配置 GRUB 2 引导加载程序。

    如果您没有使用grub(大多数 linux 桌面用户都在使用),这显然不适用于您。您应该有一个内容/etc/grub.d/40_custom不多的文件。如果不是,则创建它由 root 拥有并且chmod 755(它必须是可执行的)。对此添加:

    menuentry 'My new kernel, or whatever' {
        set root='hd0,1'
        linux /boot/[name-of-kernel] root=/dev/sda1 [other kernel options]
    }
    
    Run Code Online (Sandbox Code Playgroud)

    如果您使用的是 initramfs,您还应该有最后一行initrd /path/to/initramfs。当心set root=线路。该示例假定 grub 安装在第一个硬盘驱动器 (hd0,1) 的第一个分区上。如果您有多个驱动器,您可能希望改用分区 UUID 并将该行替换为:

        search --no-floppy --fs-uuid --set=root [the UUID of the partition]
    
    Run Code Online (Sandbox Code Playgroud)

    除非 grub 不在您的根文件系统上,否则这也应该对应于行中的root=指令,该指令linux指示您的根文件系统(带有/sbin/init和 的那个/lib/modules)。它的 UUID 版本是root=UUID=[the UUID].

    您可以查看现有/boot/grub2/grub.cfg设备以获取有关设备名称的线索。这是grub 2 下此类的简要指南。一旦您感到高兴,就运行grub2-mkconfig -o /boot/grub2/grub.cfg(但grub.cfg首先备份您当前的)。然后您可能想要编辑该文件并将您的条目移至顶部。它应该仍然包含旧的(运行)内核的列表,和你的发行版可能有其复制为自动将新内核的条目的机制(因为它是在发现/boot; Fedora的做到这一点,因此,使用不同的冠军,menuentry是一个好主意)。如果一切顺利,您可以稍后将其删除。

    您也可以直接将其menuentry插入grub.cfg,但某些发行版会在其内核更新时覆盖它(而 using/etc/grub.d/将保持其合并)。

    就是这样。您现在需要做的就是重新启动。如果它不起作用,请尝试从屏幕输出中推断出问题,重新启动并选择旧内核,然后返回到第 3 步(使用.config您已有的内核并对其进行调整)。在尝试之间make clean(或make mrproper)可能是个好主意,但请确保先复制[src]/.config到某个备份,因为这会被删除。 这有助于确保构建过程中使用的对象不会过时。

  5. 关于内核头文件等。阿尔。

    有一件事你应该做很可能是符号链接(ln -s -i/lib/modules/X.X.X/source,并/lib/modules/X.X.X/build/usr/src其中源树(记住这)目录。这是必要的,以便一些用户空间工具(和第三方驱动程序安装程序)可以访问正在运行的内核的源代码。

    与此相关的问题是 中的.h文件/usr/include等。这些变化非常缓慢,并且向后兼容。你有两个选择:

    • 保留发行版使用的那些。如果您定期更新整个系统,发行版无论如何都会定期安装新系统,因此这是“最省事”的选项。

    • 使用make headers_install.

    由于它们是向后兼容的(意味着“使用旧内核头文件针对 C 库构建的程序应该在新内核上运行”),因此您不必对此太挑剔。如果你建立一个定制的内核,并保持了一段时间,在这段时间内发行版更新的“内核头文件”包到一个唯一的潜在问题将是新的比用于构建您的内核版本,有原来是一些不兼容(仅适用于随后从源代码编译的软件)。

参考

以下是一些资源:

  • [src]/README 包括构建和安装的简要指南。

  • [src]/Documentation目录包含许多可能有助于配置的信息。

  • Greg KH 的《Linux Kernel in a Nutshell》一书(作为一系列 PDF 免费提供)的大部分内容都围绕着构建内核展开。

  • Grub 2 有一个在线手册


1. “Vanilla”是指在 kernel.org 上找到的原始、纯正的官方来源。大多数发行版都采用这个香草源并添加一些小的自定义。

2. 请注意,在某些情况下需要 initramfs,因为需要一些用户空间来安装根文件系统——例如,如果它是加密的,或者分布在复杂的 RAID 阵列中。

3. 如果您没有构建它们,它不会删除已经存在的模块,但是,这意味着您可以稍后通过简单地修改配置并make modules_install再次运行来添加模块。请注意,构建某些模块可能需要更改内核本身,在这种情况下,您还必须更换内核。您将能够判断何时尝试使用modprobe插入模块。

4. 如果您使用了非标准的压缩选项,则此文件的名称可能有所不同。我不确定所有的可能性是什么。

  • 赞成。你可能想添加一个关于 `localmodconfig` 和类似 `streamline_config.pl` 脚本的工具;从现有设置开始工作的有用方法... (3认同)
  • @derobert:这就引出了一个问题,即“几乎总是”Linux 被用于运行企业服务器。我关于 `initramfs` 的观点是,如果您*不需要*使用一个,则不必使用,这简化了过程。无论如何,我添加了关于加密根 fs 等的脚注。 (2认同)