内核

来自 Arch Linux 中文维基

根据维基百科:

Linux 内核是一种开源的类 Unix 操作系统宏内核。

Arch Linux 基于 Linux 内核。除了最新的稳定内核之外,还有许多各种各样的 Linux 内核可供选择。本文列出了仓库中提供的一些选择,并对它们简要介绍。本文还介绍了一些可用的内核补丁。文章的最后总览了自行编译内核的方法,并包含各种方法的链接。

内核包安装/usr/lib/modules/ 路径下,并随后用于生成储存在 /boot/ 中的可执行镜像。[1] 为了能够启动到内核,需要正确配置启动加载器

官方支持的内核[编辑 | 编辑源代码]

官方支持的内核可以得到来自论坛错误报告的社区支持。

  • Stable — 原版的 Linux 内核和模块,采用了一些补丁。
https://www.kernel.org/ || linux
  • Hardened — 注重安全的 Linux 内核,采用一系列加固补丁以缓解内核和用户空间漏洞。和 linux 相比,它启用了上游更多的内核加固功能。
https://github.com/anthraxx/linux-hardened || linux-hardened
  • Longterm — 受长期支持(Long Term Support)的 Linux 内核和模块。这提供了最新的长期支持(LTS)内核,并且被认为比默认内核“更稳定”。但是,它有时会使用较旧的驱动程序,这些驱动程序可能与较新的硬件不兼容,并且可能缺少较新的内核版本的某些功能。LTS内核没有固定的发布周期,但通常对于桌面版每3年更新一次,对于服务器每5年更新一次。
https://www.kernel.org/ || linux-lts
  • Realtime kernel — 由Ingo Molnar领导的一小群核心开发人员维护。这个补丁允许几乎所有的内核被抢占,除了少数非常小的代码区域(“原始自旋锁关键区域”)。这是通过将大多数内核自旋锁替换为支持优先级继承的互斥锁,以及将所有中断和软件中断移动到内核线程来实现的
https://wiki.linuxfoundation.org/realtime/start || linux-rt, linux-rt-lts
  • Zen Kernel — 一些内核黑客合作的结果,提供了最适合日常使用的内核。可在 https://liquorix.net 上找到一些细节(他们为 Debian 提供基于 Zen 的内核二进制文件)。
https://github.com/zen-kernel/zen-kernel || linux-zen

编译[编辑 | 编辑源代码]

可通过以下方式编译内核:

Arch 构建系统
充分利用已有的高质量的 linux PKGBUILD 且受益于包管理
传统方式
需要手动下载内核源代码包,然后在自己的主目录里以普通用户的身份编译。
警告:
  • 使用自定义内核可能会引起各种稳定性和可靠性问题,包括数据丢失。强烈建议操作前进行备份
  • Arch Linux 仅对#官方支持的内核提供官方支持。当使用非官方支持的内核时,务必在请求支持时提及这一点。
提示:
  • 提高系统速度的最佳方法是首先根据架构和处理器类型定制内核配置。
  • 可以通过不包含对你没有用的内容来缩小内核的大小(也因此减少构建时间)。例如,对蓝牙、video4linux、1000Mbit以太网等的支持。
Arch 内核包的 config 文件位于 Arch 软件包的源文件中(例如:linux 链接到的 [2])。如果启用了 CONFIG_IKCONFIG_PROC 内核选项,当前运行的内核的 config 文件也可能位于 /proc/config.gz

也可以通过Unofficial user repositories获取一些列出的软件包的二进制版本。

kernel.org 内核[编辑 | 编辑源代码]

  • Git — 使用Linus Torvalds Git存储库中的源代码构建的Linux内核和模块
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git || linux-gitAUR
  • Mainline — 内核中引入了所有新功能,每2-3个月发布一次
https://www.kernel.org/ || linux-mainlineAUR
  • Next — 具有待合并到下一个主线版本的功能的前沿内核
https://www.kernel.org/doc/man-pages/linux-next.html || linux-next-gitAUR
  • DRM — 带有前沿 GPU 驱动程序的 Linux 内核。
https://cgit.freedesktop.org/drm/ || linux-drm-tip-gitAURlinux-drm-next-gitAUR
  • Longterm 4.9 — 长期支持 (LTS) Linux 4.9版本的内核和模块
https://www.kernel.org/ || linux-lts49AUR
  • Longterm 4.14 — 长期支持 (LTS) Linux 4.14版本的内核和模块
https://www.kernel.org/ || linux-lts414AUR
  • Longterm 4.19 — 长期支持 (LTS) Linux 4.19版本的内核和模块
https://www.kernel.org/ || linux-lts419AUR
  • Longterm 5.4 — 长期支持 (LTS) Linux 5.4版本的内核和模块
https://www.kernel.org/ || linux-lts54AUR
  • Longterm 5.10 — 长期支持 (LTS) Linux 5.10版本的内核和模块
https://www.kernel.org/ || linux-lts510AUR

非官方内核[编辑 | 编辑源代码]

  • linux-lily — 本站站长 Lilydjwg 使用的内核,包含 cjktty、Android binder 和默认 BBR。这是一个较少更新的内核包,可以通过添加 archlinuxcn 仓库来安装。
https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/linux-lily || linux-lilyCNRepo
  • Ck — 包含Con Kolivas设计的补丁,旨在提高系统响应能力,尤其是桌面,但它们同时也适用于任何工作负载 。
http://ck.kolivas.org/ || linux-ckAUR
  • Clear — 英特尔 Clear Linux 项目的补丁,提供性能和安全优化。
https://github.com/clearlinux-pkgs/linux || linux-clearAUR
  • GalliumOS — 带有 Chromebook 的 GalliumOS 补丁的 Linux 内核和模块。
https://github.com/GalliumOS/linux || linux-galliumosAUR
https://www.fsfla.org/ikiwiki/selibre/linux-libre/ || linux-libreAUR
  • Liquorix — 使用面向 Debian 的配置和 Zen 内核源代码构建的用于替换的内核。 专为桌面、多媒体和游戏工作负载而设计,它通常用作 Debian Linux 性能替代内核。 Damentz 是 Liquorix 补丁集的维护者,也是 Zen 补丁集的开发者。
https://liquorix.net || linux-lqxAUR
  • pf-kernel — 提供了一些没有合并到内核主线中的很棒的功能。 由内核工程师维护。 如果包含的新内核补丁的端未正式发布,则补丁集提供并支持新内核的补丁端。 当前最突出的 linux-pf 补丁是 UKSM。
https://pfkernel.natalenko.name || 软件包如下:
  • tkg — 具有特定 PDS 和 Project C / BMQ CPU 调度程序相关补丁集选择器(库存 CFS 也是一个选项)的自定义 Linux 内核,并添加了一些调整以实现良好的交互性/性能平衡,旨在获得最佳游戏体验。 维护者是 Etienne Juvigny (Tk-Glitch)
https://github.com/Frogging-Family/linux-tkg || not packaged? search in AUR
  • VFIO — Linux 内核和 Alex Williamson(acs override和i915)编写的一些修补程序,能够在某些机器上使用 KVM 进行 PCI 直通。
https://lwn.net/Articles/499240/ || linux-vfioAUR, linux-vfio-ltsAUR
  • XanMod — 旨在充分利用高性能工作站、游戏台式机、媒体中心和其他方面的优势,旨在提供更坚如磐石、响应速度更快、更流畅的桌面体验。此内核使用 MUQS 调度程序、BFQ I/O 调度程序、UKSM 实时内存重复数据消除, TCP BBR 拥塞控制、x86-64 高级指令集支持和其他默认更改。
https://xanmod.org/ || linux-xanmodAUR

疑难解答[编辑 | 编辑源代码]

内核 Panics[编辑 | 编辑源代码]

当Linux内核进入不可恢复的失败状态时,一个内核 Panics就会发生。这种状态的发生通常归咎于不成熟的(包含很多bug)的硬件驱动,它们导致系统死锁、不能回复响应和必须重新启动。仅仅在进入死锁前,会生成诊断信息,它包括:当机器失败发生时的 machine state 信息,一个识别这次失败的内核函数的 call trace 调用栈,和一个当前已加载的内核模块列表。幸运的是,内核 Panics在使用主线mainline版本内核的系统上并不经常发生,这些内核被官方仓库所支持。但当它们发生时,你需要知道怎么处理它们。

注意: 内核panics有时被提示为 oops 或者 kernel oops。当 panics 和 oops 作为机器失败状态的结果都发生时,一个 oops 通常不一定会导致系统死锁:有时内核通过杀死问题任务进程从 oops 中恢复并继续运行。
提示:然而可以在启动时传递内核参数 oops=panic 或者向 /proc/sys/kernel/panic_on_oops 写入 1 强制一个可恢复的 oops 引发一个 panic。如果你关心从 oops 中恢复导致的系统轻微的不稳定,这种不稳定可能会使未来的错误难于诊断,那么建议你采取上面的做法。

示例:Panic消息[编辑 | 编辑源代码]

如果一个内核panic发生在非常早的启动过程(boot process)中,你可能会在终端中看见包含 "Kernel panic - not syncing:" 的信息,但是一旦 Systemd 开始运行,内核消息通常会被捕获并写入系统日志里面。然而,当一个panic发生时,内核输出的诊断消息几乎从不被写入磁盘上的日志文件,因为在 system-journald 得到机会前,系统已经死锁了。因此,检查panic消息的唯一方式就是当它发生时,在终端上观察它(不需要求助于设置 kdump crashkernel)。你可以在启动时带有下面的内核参数,尝试在tty1上生成panic消息:

systemd.journald.forward_to_console=1 console=tty1
提示:如果panic消息因滚动太快无法检查,尝试在启动时传递 pause_on_oops=seconds 内核参数。

设想示例:坏模块[编辑 | 编辑源代码]

使用诊断消息里面的信息,我们可以很好地猜测是哪一个子系统或者模块正在导致panic。这下面的设想场景中,我们有一个panic发生在设想机器的启动过程中。特别注意加粗高亮的行:

kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 1
kernel: IP: fw_core_init+0x18/0x1000 [firewire_core] 2
kernel: PGD 718d00067
kernel: P4D 718d00067
kernel: PUD 7b3611067
kernel: PMD 0
kernel:
kernel: Oops: 0002 [#1] PREEMPT SMP
kernel: Modules linked in: firewire_core(+) crc_itu_t cfg80211 rfkill ipt_REJECT nf_reject_ipv4 nf_log_ipv4 nf_log_common xt_LOG nf_conntrack_ipv4 ... 3
kernel: CPU: 6 PID: 1438 Comm: modprobe Tainted: P           O    4.13.3-1-ARCH #1
kernel: Hardware name: Gigabyte Technology Co., Ltd. H97-D3H/H97-D3H-CF, BIOS F5 06/26/2014
kernel: task: ffff9c667abd9e00 task.stack: ffffb53b8db34000
kernel: RIP: 0010:fw_core_init+0x18/0x1000 [firewire_core]
kernel: RSP: 0018:ffffb53b8db37c68 EFLAGS: 00010246
kernel: RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
kernel: RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffffffffc16d3af4
kernel: RBP: ffffb53b8db37c70 R08: 0000000000000000 R09: ffffffffae113e95
kernel: R10: ffffe93edfdb9680 R11: 0000000000000000 R12: ffffffffc16d9000
kernel: R13: ffff9c6729bf8f60 R14: ffffffffc16d5710 R15: ffff9c6736e55840
kernel: FS:  00007f301fc80b80(0000) GS:ffff9c675dd80000(0000) knlGS:0000000000000000
kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: CR2: 0000000000000000 CR3: 00000007c6456000 CR4: 00000000001406e0
kernel: Call Trace:
kernel:  do_one_initcall+0x50/0x190 4
kernel:  ? do_init_module+0x27/0x1f2
kernel:  do_init_module+0x5f/0x1f2
kernel:  load_module+0x23f3/0x2be0
kernel:  SYSC_init_module+0x16b/0x1a0
kernel:  ? SYSC_init_module+0x16b/0x1a0
kernel:  SyS_init_module+0xe/0x10
kernel:  entry_SYSCALL_64_fastpath+0x1a/0xa5
kernel: RIP: 0033:0x7f301f3a2a0a
kernel: RSP: 002b:00007ffcabbd1998 EFLAGS: 00000246 ORIG_RAX: 00000000000000af
kernel: RAX: ffffffffffffffda RBX: 0000000000c85a48 RCX: 00007f301f3a2a0a
kernel: RDX: 000000000041aada RSI: 000000000001a738 RDI: 00007f301e7eb010
kernel: RBP: 0000000000c8a520 R08: 0000000000000001 R09: 0000000000000085
kernel: R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000c79208
kernel: R13: 0000000000c8b4d8 R14: 00007f301e7fffff R15: 0000000000000030
kernel: Code: <c7> 04 25 00 00 00 00 01 00 00 00 bb f4 ff ff ff e8 73 43 9c ec 48
kernel: RIP: fw_core_init+0x18/0x1000 [firewire_core] RSP: ffffb53b8db37c68
kernel: CR2: 0000000000000000
kernel: ---[ end trace 71f4306ea1238f17 ]---
kernel: Kernel panic - not syncing: Fatal exception 5
kernel: Kernel Offset: 0x80000000 from 0xffffffff810000000 (relocation range: 0xffffffff800000000-0xfffffffffbffffffff
kernel: ---[ end Kernel panic - not syncing: Fatal exception
  1. 表明导致 panic 的错误类型。在这个例子中,是编程时留下的bug。
  2. 表明 panic 发生在 firewire_core 模块的 fw_core_init 函数中。
  3. 表明 fw_core_init 模块是载入的最新模块。
  4. 表明 fw_core_init 函数的调用者是 do_one_initcall 函数。
  5. 表明这个 oops 消息实际上是一个内核panic,而且系统现在已经死锁。

然后我们可以推测这个panic发生在模块 firewire_core 载入时的初始化过程中。(然后我们可以推测机器的firewire硬件不兼容当前版本的firewire驱动模块,因为它包含一个编程错误,而且不得不等待新的驱动发布。)同时,使系统重新运行最简单的方式就是不允许这个模块被载入,我们可以采取下面两种方式之一做到这一点:

  • 如果这个模块是在 initramfs 执行期间被载入,则使用内核参数 rd.blacklist=firewire_core 重启。
  • 其他情况下,使用内核参数 module_blacklist=firewire_core 重启。

调试回退[编辑 | 编辑源代码]

参考General troubleshooting#Debugging regressions

尝试 linux-mainlineAUR 以检查问题是否已在上游解决。下面的 Pinned Comments 还提到了一个包含已经构建的内核的存储库,因此可能不需要花费时间手动构建它。

也可以考虑尝试使用 LTS 内核 (linux-lts) 来调试最近没有出现的问题。旧版本的 LTS 内核可以在 Arch Linux Archive 找到。

如果问题仍然存在,bisect linux-gitAUR 并在 kernel bugzilla 上报告错误。尝试不带任何补丁的“vanilla”版本以确保问题与补丁无关是很重要的。如果补丁导致了问题,请将其报告给补丁的作者。

注意: bisect 内核可能需要很多时间,因为可能需要多次重建。

参见[编辑 | 编辑源代码]