在计算机领域,内核是处理与硬件通信和一般系统协调的底层软件。除了内置于计算机主板中的一些初始固件外,当你启动计算机时,内核会提供对硬盘、屏幕、键盘和网卡的感知。内核的任务还包括确保每个组件获得相同的(或多或少的)时间,以便你的图形、音频、文件系统和网络都能平稳运行,即使它们是同时运行的。
然而,对硬件支持的探索仍在进行中,因为发布的硬件越多,内核必须在其代码中采用的东西就越多,才能使硬件按预期工作。很难获得准确的数字,但 Linux 内核无疑是硬件兼容性最好的内核之一。Linux 运行着无数的计算机和手机,用于业余爱好者和工业用途的片上系统 (SoC) 板,RAID 卡,缝纫机等等。
早在 20 世纪(甚至在 21 世纪的早期),Linux 用户期望在购买非常新的硬件时,需要下载最新的内核源代码、编译并安装它,以便获得对该设备的支持,这并非不合理。然而,最近,你很难找到一个编译自己的内核的 Linux 用户,除非是为了乐趣或通过高度专业化的定制硬件来获利。通常,现在不需要自己编译 Linux 内核。
以下是原因,以及当你需要时如何编译内核的快速教程。
更新你现有的内核
无论你拥有一台带有全新显卡或 WiFi 芯片组的全新笔记本电脑,还是刚刚买了一台新打印机,你的操作系统(称为 GNU+Linux 或简称为 Linux,这也是内核的名称)都需要一个驱动程序来打开与该新组件(显卡、WiFi 芯片、打印机或任何东西)的通信通道。有时,当你插入一个新设备并且你的计算机似乎确认了它时,可能会产生误导。但不要被它迷惑了。有时这是你所需要的全部,但其他时候,你的操作系统只是使用通用协议来探测连接的设备。
例如,你的计算机可能能够识别你的新网络打印机,但有时这仅仅是因为打印机中的网卡被编程为向网络识别自己,以便它可以获得 DHCP 地址。这并不一定意味着你的计算机知道向打印机发送哪些指令来生成一页打印文本。事实上,你可能会争辩说,计算机甚至不真正“知道”该设备是打印机;它可能只是显示网络上有一个特定地址的设备,并且该设备用字符序列 *p-r-i-n-t-e-r* 标识自己。人类语言的惯例对计算机来说毫无意义;它需要的是一个驱动程序。
内核开发人员、硬件制造商、支持技术人员和爱好者都知道,新的硬件正在不断发布。他们中的许多人贡献驱动程序,直接提交给内核开发团队,以便将其包含在 Linux 中。例如,Nvidia 显卡驱动程序通常写入 Nouveau 内核模块中,并且由于 Nvidia 显卡很常见,因此该代码通常包含在为通用用途分发的任何内核中(例如,当你下载 Fedora 或 Ubuntu 时获得的内核)。在 Nvidia 不太常见的地方,例如在嵌入式系统中,通常会排除 Nouveau 模块。许多其他设备都存在类似的模块:打印机受益于 Foomatic 和 CUPS,无线网卡具有 b43, ath9k, wl 模块,等等。
发行版倾向于在其 Linux 内核构建中尽可能多地包含内容,因为他们希望你能够连接设备并立即开始使用它,而无需安装驱动程序。在大多数情况下,这就是发生的事情,尤其是现在许多设备供应商正在资助其销售硬件的 Linux 驱动程序开发,并将这些驱动程序直接提交给内核团队进行通用分发。
但是,有时你运行的是六个月前安装的内核,以及一周前刚刚上市的令人兴奋的新设备。在这种情况下,你的内核可能没有该设备的驱动程序。好消息是,通常该设备的驱动程序可能存在于最新版本的内核中,这意味着你所要做的就是更新你正在运行的内容。
通常,这是通过包管理器完成的。例如,在 RHEL、CentOS 和 Fedora 上
$ sudo dnf update kernel
在 Debian 和 Ubuntu 上,首先获取你当前的内核版本
$ uname -r
4.4.186
搜索更新的版本
$ sudo apt update
$ sudo apt search linux-image
安装你找到的最新版本。在此示例中,最新可用版本为 5.2.4
$ sudo apt install linux-image-5.2.4
内核升级后,你必须重启(除非你使用 kpatch 或 kgraft)。然后,如果你需要的设备驱动程序在最新的内核中,你的硬件将按预期工作。
安装内核模块
有时,发行版并不期望其用户经常使用某个设备(或者至少没有多到需要将该设备驱动程序包含在 Linux 内核中)。Linux 采用模块化驱动程序方法,因此发行版可以发布单独的驱动程序包,这些包可以由内核加载,即使驱动程序没有编译到内核本身中。这很有用,但当驱动程序未包含在内核中但需要在启动期间使用时,或者当内核在模块化驱动程序下更新时,它可能会变得复杂。第一个问题通过 initrd(初始 RAM 磁盘)解决,这超出了本文的范围,第二个问题由名为 kmod 的系统解决。
kmod 系统确保在更新内核时,也会更新与其一起安装的所有模块化驱动程序。如果你手动安装驱动程序,你将错过 kmod 提供的自动化,因此你应尽可能选择 kmod 包。例如,虽然 Nvidia 驱动程序作为 Nouveau 驱动程序内置于内核中,但官方 Nvidia 驱动程序仅由 Nvidia 分发。你可以通过访问网站、下载 .run 文件并运行它提供的 shell 脚本来手动安装 Nvidia 品牌的驱动程序,但是每次安装新内核后都必须重复相同的过程,因为没有任何东西告诉你的包管理器你手动安装了内核驱动程序。由于 Nvidia 驱动你的图形,手动更新 Nvidia 驱动程序通常意味着你必须从终端执行更新,因为你没有功能正常的图形驱动程序就无法使用图形。

但是,如果你将 Nvidia 驱动程序安装为 kmod 包,则更新你的内核也会更新你的 Nvidia 驱动程序。在 Fedora 和相关发行版上
$ sudo dnf install kmod-nvidia
在 Debian 和相关发行版上
$ sudo apt update
$ sudo apt install nvidia-kernel-common nvidia-kernel-dkms nvidia-glx nvidia-xconfig nvidia-settings nvidia-vdpau-driver vdpau-va-driver
这只是一个示例,但如果你在现实生活中安装 Nvidia 驱动程序,你还必须将 Nouveau 驱动程序列入黑名单。有关最佳步骤,请参阅你发行版的文档。
下载并安装驱动程序
并非所有内容都包含在内核中,并且并非所有其他内容都作为内核模块提供。在某些情况下,你必须下载由硬件供应商编写和捆绑的特殊驱动程序,而在其他情况下,你拥有驱动程序,但没有配置驱动程序选项的前端。
两个常见的例子是 HP 打印机和 Wacom 插图平板电脑。如果你获得一台 HP 打印机,你可能有可以与你的打印机通信的通用驱动程序。你甚至可能可以打印。但是,通用驱动程序可能无法提供特定于你型号的专用选项,例如双面打印、整理、纸盘选择等等。HPLIP(HP Linux 成像和打印系统)提供了管理作业、调整打印选项、选择纸盘(如果适用)等的选项。
HPLIP 通常捆绑在包管理器中;只需搜索“hplip”。

同样,Wacom 平板电脑(数字艺术家的领先插图平板电脑)的驱动程序通常包含在你的内核中,但微调设置(例如压力灵敏度和按钮功能)的选项只能通过 GNOME 默认包含的图形控制面板访问,但在 KDE 上可以作为额外的包 kde-config-tablet 安装。
可能有一些边缘情况在内核中没有驱动程序,但提供驱动程序模块的 kmod 版本作为你可以通过包管理器下载和安装的 RPM 或 DEB 文件。
修补和编译你自己的内核
即使在作为 21 世纪的未来乌托邦中,也有一些供应商对开源的理解不足以提供可安装的驱动程序。有时,这些公司提供驱动程序的源代码,但期望你下载代码、修补内核、编译和手动安装。
这种分发模型与在 kmod 系统之外安装打包驱动程序具有相同的缺点:每次将内核换成新内核时,都必须手动将其重新集成到你的内核中,因此对内核的更新会破坏驱动程序。
令人高兴的是,这种情况已经变得很少见,因为 Linux 内核团队在呼吁公司与他们沟通方面做得非常出色,并且因为公司最终接受了开源不会很快消失。但是,仍然有一些新颖或超专业的设备只提供内核补丁。
正式地,对于如何编译内核以使你的包管理器参与升级系统的这一重要部分,存在特定于发行版的首选项。包管理器太多了,无法涵盖每个;例如,以下是当你在 Fedora 上使用 rpmdev 或在 Debian 上使用 build-essential 和 devscripts 等工具时幕后发生的事情。
首先,像往常一样,找出你正在运行的内核版本
$ uname -r
在大多数情况下,如果你还没有升级你的内核,那么升级内核是安全的。毕竟,你的问题可能会在最新版本中得到解决。如果你尝试过并且没有奏效,那么你应该下载你正在运行的内核的源代码。大多数发行版都为此提供了一个特殊的命令,但是要手动执行此操作,你可以在 kernel.org 上找到源代码。
你还必须下载你需要的内核的任何补丁。有时,这些补丁特定于内核版本,因此请谨慎选择。
将源代码和补丁放在 /usr/src/linux 中是传统的,或者至少在人们经常编译自己的内核时是这样的。
根据需要解压缩内核源代码和补丁文件
$ cd /usr/src/linux
$ bzip2 --decompress linux-5.2.4.tar.bz2
$ cd linux-5.2.4
$ bzip2 -d ../patch*bz2
补丁文件可能包含如何打补丁的说明,但通常它们被设计为从你的代码树的顶层执行。
$ patch -p1 < patch*example.patch
一旦内核代码被打了补丁,你可以使用你旧的配置来准备打过补丁的内核配置。
$ make oldconfig
make oldconfig 命令有两个目的:它继承你当前内核的配置,并且允许你配置由补丁引入的新选项。
你可能需要运行 make menuconfig 命令,它会启动一个基于 ncurses 的、菜单驱动的列表,其中包含你的新内核的可能选项。 菜单可能会让人不知所措,但因为它以你旧的配置为基础,所以你可以浏览菜单并禁用你知道你没有并且不期望需要的硬件的模块。 或者,如果你知道你有一些硬件并且看到它未包含在你当前的配置中,你可以选择构建它,可以作为模块或直接构建到内核中。 理论上,这没有必要,因为大概你当前的内核运行良好,只是缺少补丁,并且可能你应用的补丁已经激活了任何设备提示你打补丁所需要的所有必要选项。
接下来,编译内核及其模块。
$ make bzImage
$ make modules
这将生成一个名为 vmlinuz 的文件,它是你的可启动内核的压缩版本。 保存你的旧版本,并将新版本放在你的 /boot 目录中。
$ sudo mv /boot/vmlinuz /boot/vmlinuz.nopatch
$ sudo cat arch/x86_64/boot/bzImage > /boot/vmlinuz
$ sudo mv /boot/System.map /boot/System.map.stock
$ sudo cp System.map /boot/System.map
到目前为止,你已经打了补丁并构建了内核及其模块,你已经安装了内核,但你还没有安装任何模块。 这是最后的构建步骤。
$ sudo make modules_install
新的内核已经就位,其模块也已安装。
最后一步是更新你的引导加载程序,以便你的计算机在内核加载之前加载的部分知道在哪里找到 Linux。 GRUB 引导加载程序使这个过程相对简单。
$ sudo grub2-mkconfig
真实的编译。
当然,现在没有人运行那些手动命令了。 相反,请参考你的发行版,以获取有关使用你的发行版维护者使用的开发者工具集修改内核的说明。 此工具集可能会创建一个包含所有补丁的新可安装软件包,提醒软件包管理器进行升级,并为你更新引导加载程序。
内核
操作系统和内核是神秘的东西,但不需要太多就可以理解它们是由什么组件构建的。 下次你得到一个似乎无法在 Linux 上运行的技术时,深吸一口气,调查驱动程序的可用性,并选择阻力最小的路径。 Linux 比以往任何时候都容易,包括内核。
7 条评论