附录 D 内核配置 (Kernel Configuration)

      +

      核心结论

      • Linux 内核功能按需编译:每个内核子系统可在编译时 =y / =m / =n;可减少内核二进制大小、节省内存、避免不需要的代码进入漏洞评估面。

      • 配置工具make menuconfig(curses 风格)、make xconfig(Qt 图形)、make config(文本问答);结果写入 .config 文件。

      • .config 文件格式CONFIG_NAME=value 行;# CONFIG_NAME is not set 表示未启用;可用 menuconfig 的 / 搜索直接定位。

      • 运行内核可看 /proc/config.gz:压缩的 .config 信息;zcat /proc/config.gz | grep CONFIG_X 查当前已编译配置。

      • 模块化(=m)的优点:功能不在内核体积,但可按需 modprobe 加载;副作用少、升级不需重编。

      • TLPI 不指明 menu 路径——menu 层级随内核版本变化;只要知道名字 + menuconfig / 搜索就能找到。

      附录主旨

      本附录概述 Linux 内核编译配置机制。读者需掌握:(1) .config 文件内容如何与 menuconfig/xconfig 交互;(2) CONFIG_NAME 行 / # not set 行格式;(3) CONFIG_NAME=y/m/n 各代表的编译结果;(4) /proc/config.gz 让运行系统也保留 build-time 配置。这些对解决「某功能是否启用」类问题(如 epoll、inotify、pty max)至关重要。

      一、核心概念

      本附录围绕 4 个核心概念:编译选项 y/m/n、三种配置工具、.config 格式、运行内核查配置。

      概念 定义 + 重要性 实现提示

      编译选项三态

      =y:功能编入内核镜像(vmlinux);=m:独立模块,可 modprobe 加载;=n# not set:不编译。

      §D;如 CONFIG_UNIX98_PTYS=y 直接编译;CONFIG_BLK_DEV_FD=m 后模块化。

      配置工具(menu/x/config)

      make menuconfig(ncurse)、make xconfig(Qt 图)、make gconfig(GTK)、make config(文本 CLI)。

      §D;改完 Save 后写入 .config;之后 make 启动编译。

      .config 格式

      CONFIG_NAME=value 行(y/m/n/数字/字符串);# CONFIG_NAME is not set 注释行代表未启用;# 开头为注释。

      §D;可用 grep CONFIG_X config 看具体值。

      运行内核查配置

      /proc/config.gz 显示该内核编译时用的 .config(需 CONFIG_IKCONFIG=y + CONFIG_IKCONFIG_PROC=y)。

      §D;`zcat /proc/config.gz

      二、详细笔记

      D.1 配置文件流程

      What:编译内核的标准流程(高层):

      tar xvf linux-6.6.tar.xz
      cd linux-6.6
      make menuconfig        # 选择配置
      make -j$(nproc)        # 编译
      sudo make modules_install
      sudo make install

      Why:(1) TLPI 描述功能时常引用 CONFIG_* 名称——理解 .config 是配置入口的关键;(2) 调试需要时可能重编启用 CONFIG_xxx。

      How:在 menuconfig 主菜单按 / 进入搜索模式,输入如 INOTIFY → 找到选项描述与路径。

      When:(1) 想启用某功能但发行版默认不开;(2) 想关某功能减少 attack surface。

      Example:CentOS / RHEL 默认 CONFIG_UNIX98_PTYS=n → ssh server 不能分配 pty → 编辑 /etc/sshd_config 不行,得重编或换 distro。

      D.2 y / m / n 与模块管理

      WhatCONFIG_FOO=y 编入 vmlinux;CONFIG_FOO=m 生成 foo.ko,可按需 modprobe foo 加载;CONFIG_FOO 不存在则不编译。

      Why:(1) 现代发行版默认大量 =m 模块,节约常驻内存;(2) 核心 / 启动必需的功能必须 =y(如 root fs、disk 驱动);(3) 编译失败时精确到具体选项。

      How

      类别 常用选项 典型选择

      启动必需

      CONFIG_SATA_AHCI=y, CONFIG_EXT4_FS=y

      一定 y

      文件系统

      CONFIG_NTFS_FS=m

      按需加载

      网络协议

      CONFIG_IPV6=m

      现代偏好 y

      安全

      CONFIG_SECURITY_APPARMOR=m

      发行版默认 m

      调试

      CONFIG_DEBUG_KERNEL=y

      开发用

      性能追踪

      CONFIG_FTRACE=y

      perf 用户

      用户态 API

      CONFIG_EPOLL=y, CONFIG_INOTIFY=y

      When:(1) 嵌入式系统极度裁剪——绝大多数 m/n;(2) 普通服务器:核心 y、副功能 m。

      Example/lib/modules/$(uname -r)/ 列出当前内核的所有模块——modinfo e1000e 看驱动信息。

      D.3 /proc/config.gz:运行内核的 build-time 配置

      What:内核编译时启用 CONFIG_IKCONFIG=y + CONFIG_IKCONFIG_PROC=y → /proc/config.gz 提供 gzip(.config);运行中查询已编译功能。

      Why:(1) 现场不重新编译可知道功能是否在内;(2) 调试不在系统上重现 bug 时知道对方内核配置。

      How

      zcat /proc/config.gz | grep -E 'CONFIG_(EPOLL|INOTIFY|EVENTFD|SECCOMP|NAMESPACES)'

      When:(1) 排查「为什么我 exec 不成功」类问题,先确认 CONFIG_xxx 在当前内核;(2) TLPI 多处引用,本附录给出兜底查询方法。

      ExampleCONFIG_USER_NS 限制能否建 user namespace;CONFIG_CGROUP_* 决定有哪些 cgroup 子系统可用。

      D.4 间接配置路径(如 /proc/sys)

      What:很多内核选项不仅有 .config / module 开关;运行时可通过 /proc/sys/ 调整参数(如 pty/maxtcp_ecn)。

      Why:与 .config 静态编译选项不同,/proc/sys 暴露运行时可调的运行时参数。

      How

      sysctl kernel.pty.max       # 动态查
      sysctl -w kernel.pty.max=8192
      cat /proc/sys/kernel/pty/max

      When:(1) 调 socket 缓存、文件数限制;(2) 调 pty 数量;(3) 调 TCP 拥塞控制算法。

      Example:TLPI 9 章 CAP_NET_BIND_SERVICE 与 capabilities 配合 /proc/sys/kernel/yama/ptrace_scope 等。

      D.5 进一步:编译 / 调试 / 升级

      What:典型编译内核的后续步骤:

      make -j$(nproc) bzImage modules
      sudo make modules_install install
      sudo update-grub          # Debian/Ubuntu
      sudo grub2-mkconfig -o /boot/grub2/grub.cfg   # RHEL
      sudo reboot

      Why:TLPI 不强求编译内核,但排除某个功能未启用问题时常需重编。

      How

      步骤 目的 工具

      make mrproper

      清旧 .config + 缓存

      make

      make defconfig

      使用 arch 默认

      make

      make olddefconfig

      移植旧 .config

      make

      make localmodconfig

      仅编译当前 loaded modules

      make

      make modules_install

      装到 /lib/modules/$(uname -r)

      When:(1) 升级内核;(2) 定制功能性关闭;(3) 加 patch 后重编。

      Examplemake localmodconfig 仅编译当前 loaded modules,最小化编译时间但避免新硬件无驱动。

      三、关键图表

      TLPI 引用的关键 CONFIG 选项
      选项 功能 默认

      CONFIG_UNIX98_PTYS

      /dev/ptmx/dev/pts/N

      大多 y(2.6.4+ 移到 /proc/sys/kernel/pty/max)

      CONFIG_LEGACY_PTYS

      BSD 风格 pty

      默认 n(2.6.4+)

      CONFIG_EPOLL

      epoll 系统调用

      y

      CONFIG_INOTIFY

      inotify 文件系统监听

      y

      CONFIG_EVENTFD

      eventfd 系统调用

      y

      CONFIG_TIMERFD

      timerfd 系统调用

      y

      CONFIG_SIGNALFD

      signalfd 系统调用

      y

      CONFIG_NETLINK

      netlink 套接字

      y

      CONFIG_SYSVIPC

      SysV IPC

      y

      CONFIG_FILE_LOCKING

      文件锁(flock/fcntl)

      y

      CONFIG_CGROUPS

      cgroup 子系统

      y

      CONFIG_NAMESPACES

      namespace(user/net/…​)

      y

      CONFIG_SECCOMP

      seccomp 系统调用过滤

      y

      .config 语法
      格式 含义 例子

      CONFIG_X=y

      编入内核

      CONFIG_EPOLL=y

      CONFIG_X=m

      编译为模块

      CONFIG_BLK_DEV_FD=m

      CONFIG_X=string

      字符串值

      CONFIG_DEFAULT_HOSTNAME="localhost"

      CONFIG_X=42

      数值

      CONFIG_HZ=250

      # CONFIG_X is not set

      未启用

      注释行

      # …​

      注释

      信息行

      四、思维导图

      mindmap
        root((附录 D kernel 配置))
          编译选项
            y 编入
            m 模块
            n not set
            string 数字
          配置工具
            menuconfig ncurses
            xconfig Qt
            gconfig GTK
            config 文本
          config 文件
            CONFIG NAME value
            not set 注释
            menuconfig 生成
            旧版本兼容
          运行查配置
            proc config gz
            ikconfig y
            zcat 查询
          运行时参数
            proc sys
            sysctl 修改
            持久化 etc sysctl
          编译流程
            mrproper
            defconfig
            olddefconfig
            localmodconfig
            modules_install

      五、重点与易错点

      1. TLPI 引用 CONFIG_xxx 时常用 /proc/config.gz | grep 查运行内核是否启用——比改 menuconfig 重编高效。

      2. module =m=y 区别:模块可按需 modprobe 节省内存;启动必需功能必须 y。

      3. menuconfig 按 / 搜索——不必死记路径;版本间菜单变化大。

      4. localmodconfig 减少编译时间——只编译当前 loaded 的模块,避免冗余;但加新硬件时需重新编译。

      5. 重编内核不会自动生效——必须 make install + 重启;旧内核仍可用 GRUB 选。

      6. 发行版内核常禁 CONFIG_IKCONFIG=y——/proc/config.gz 可能为空;只能用 /proc/version/proc/sys/ 间接推断。

      7. CONFIG_UNIX98_PTYS 自 2.6.4 起被替代——通过 /proc/sys/kernel/pty/max 控制,参数非编时选项。

      8. modprobe 加载模块/etc/modprobe.d/ 控制系统启动时加载;modprobe -r foo 卸载。

      9. CONFIG_xxx 模块化的副作用——内核升级后可能要求重编模块(dkms 自动维护)。

      10. 改 .config 后务必 make olddefconfig——避免新内核新增选项被设为 n 而 missing。

      11. CONFIG_PREEMPT / CONFIG_PREEMPT_RT——影响调度延迟;桌面选 PREEMPT_VOLUNTARY、实时系统选 PREEMPT_RT(需打 patch)。

      12. CONFIG_CGROUP_xyz——多个子系统分别编译;CONFIG_CGROUP_SCHED/CPUSET/…​;cat /proc/cgroups 查启用列表。

      13. CONFIG_SECCOMP 是现代容器 / firefox 沙箱的基础——常被加严配合 seccomp filter (BPF)。

      14. CONFIG_USER_NS 必需——Docker/k8s 必备;用户 namespace 提供非 root 容器隔离。

      15. CONFIG_DEBUG_KERNEL / CONFIG_DEBUG_INFO 启用会让内核 + 应用大很多——生产前关闭节省内存。

      16. 跨章衔接:本章被第 9 章 capabilities / 第 33 章线程 / 第 46 章 SysV IPC / 第 50 章 mmap / 第 53 章 POSIX semaphore / 第 62 章 terminal / 第 64 章 pty 等多章引用,是 TLPI 系统编程中「功能是否启用」的兜底检查。