24.1 编译前的任务:认识核心与取得核心源代码

一般使用者不需要编译核心。只有在:新硬件驱动未进入当前核心、嵌入式系统精简、特定功能需求、学习核心原理时才需要。

24.1.1 什么是核心(Kernel)

核心就是系统上的一个文件/boot/vmlinuz-xxx),包含驱动所有硬件的侦测程序与驱动模块。

开机流程中:BIOS → MBR(loader) → 载入核心到内存 → 核心侦测硬件 → 挂载根目录 → 载入核心模块 → 调用 systemd 启动服务。

核心模块 (kernel module)

概念说明
为什么需要模块硬件更新太快,如果每次新硬件都要重编整个核心太麻烦
模块是什么将不常用的驱动程序独立出核心,编译成 .ko 文件,系统运行时动态载入
模块位置/lib/modules/$(uname -r)/kernel/

驱动程序开发是硬件厂商的责任——厂商要提供消费者能用的驱动,无论是 Windows 还是 Linux。

24.1.2 更新核心的目的

核心编译的重点:你的 Linux 要做什么? 不必要的功能就别编译进去——越精简越稳定。

编译核心的时机

场景说明
新功能需求新核心才有的功能(如新版 iptables、新主板芯片组支持)
核心太过臃肿追求稳定性——移除不需要的功能
硬件搭配稳定性原核心针对 Intel CPU 优化,AMD 可能需要重编;新硬件无驱动
嵌入式系统需要小而美的精简核心(如树莓派、香蕉派)
性能优化针对特定 CPU 优化,但效益不大

💡 如果系统已运行很久没问题,也不增加冷门硬件 → 不需要重编核心。distribution 的默认核心已经很适合一般使用。

24.1.3 核心的版本

CentOS 7 使用 3.10.x 长期维护版。升级建议:

  • 使用长期维护版本的最新版(如 3.10.89),而非主线最新版(如 4.2.1)
  • 跨版本升级(如 3.10→4.x)可能造成软件兼容性问题,后果自负

鸟哥曾为 VGA PCI passthrough 将 CentOS 7.1 的 3.10.x 升级到 4.2.3——有特殊需求时可以,但要自行承担风险。

24.1.4 核心源代码的取得方式

来源说明地址
CentOS SRPM含默认设置值,编译难度低http://vault.centos.org/
kernel.org 最新稳定版支持新硬件,但无 distro 默认值http://www.kernel.org/
patch 升级从旧版逐版打补丁升级kernel.org 的 patch 文件

💡 推荐使用 distribution 的 SRPM——保留原默认设置,在此基础上微调即可。

24.1.5 核心源代码的解压缩/安装/观察

tar -Jxvf linux-3.10.89.tar.xz -C /usr/src/kernels/
cd /usr/src/kernels/linux-3.10.89

源代码目录结构

目录内容目录内容
arch/CPU 架构(x86, x86_64…)kernel/核心程序、调度、信号
block/区块设备、文件系统lib/函数库
crypto/加密技术(md5, des)mm/内存管理、swap
Documentation/核心说明文档net/网络协定、防火墙
drivers/硬件驱动程序security/SELinux 等安全设置
firmware/旧硬件固件sound/音效模块
fs/文件系统(vfat, nfs…)virt/KVM 虚拟化
include/头文件(header)

24.2 核心编译的前处理与核心功能选择

24.2.1 硬件环境检视与核心功能要求

编译前必须了解自己的硬件和需求。查看硬件:

cat /proc/cpuinfo     # CPU 信息
lspci                 # PCI 设备(网卡、显卡等)
lsusb                 # USB 设备

24.2.2 保持干净源代码:make mrproper

命令作用使用时机
make mrproper清除所有编译残留 + 配置文件首次编译前
make clean仅清除目标文件(.o),保留配置文件重复编译时

⚠️ make mrproper 会删除 .config!如果已用 cp /boot/config-xxx .config 复制了配置文件,不要再执行它。

24.2.3 开始挑选核心功能:make XXconfig

命令说明
make menuconfig最常用——文字模式类图形界面,不需 X Window
make oldconfig使用已有 .config 为默认值,只列出新功能选项(升级用)
make xconfigQt 图形界面(需 KDE)
make gconfigGtk 图形界面(需 GNOME)
make config逐条问答式(最古老,不推荐)

懒人方法——以 CentOS 默认配置为基础微调:

cp /boot/config-$(uname -r) .config    # 以系统当前核心配置为底
make menuconfig                          # 在此基础上微调

menuconfig 操作:方向键移动、空格键选择、Enter 进入子菜单。

符号含义
[*] / <*>编译进核心(核心功能)
<M>编译为模块(按需加载)
[ ] / < >不编译

选择原则

  • 肯定要用的 → 编译进核心
  • 可能未来会用到 → 编译成模块
  • 看不懂的 → 保留默认值,或编译成模块

24.2.4 核心功能细项选择

General setup

项目建议
Local version自定义版本后缀(如 3.10.89.vbird
Kernel compression mode选 Bzip2(压缩比高)
initramfs support必须勾选
Optimize for size桌面/服务器不用选(嵌入式才选)

Loadable module + Block layer

项目说明
Enable loadable module support必选——支持动态加载模块
Forced module unloading建议勾选——强制卸载顽固模块
I/O Scheduler建议选 Deadline 并设为核心功能(服务器场景)

CPU (Processor type and features)

项目建议
Processor familyGeneric-x86-64(除非是老硬件)
Preemption ModelServer 选 No Forced Preemption
Timer frequencyServer 选 300Hz,Desktop 选 1000Hz
KVM Guest support虚拟化相关,建议勾选

Power management

项目建议
ACPI Support桌面/服务器都选
CPU Frequency scalingDefault governor 选 ondemand

Bus options:PCI Express 支持必选,否则新显卡可能无法工作。

Executable file formats:ELF、#! scripts 必选;建议启用 32 位仿真(IA32 Emulation)以兼容旧软件。

Networking support:防火墙相关全部编译为模块。Network packet filtering framework (Netfilter) 是 iptables 的基础,必须启用。

Device Drivers——最重要的部分:

类别关键项
SATA/ATASerial ATA and Parallel ATA → 编为模块
RAID/LVMMultiple devices driver support → 必选
Network网卡驱动、Bonding、Virtio 网络 → 编为模块
Graphics桌面机需要,服务器可选
Sound桌面机需要
USBxHCI (USB3.0)、EHCI (USB2.0)、OHCI、UHCI 全部编入核心
Virtio drivers虚拟机环境很重要
VFIOVGA passthrough 用(需 KVM 虚拟化)

File systems

项目建议
ext2/ext3/ext4全选为模块
XFS必选(CentOS 7 默认)
Btrfs建议支持
Quota support选为核心功能
NTFS选为模块 + 开启写入
FAT 中文支持Default codepage=950, Default iocharset=utf8
NFS client/server选为模块
CIFS (Samba)选为模块

Security + Crypto:SELinux 保持默认;加密 API 保持默认。

Virtualization:KVM 编入核心(Intel + AMD processor support 都选)。

设置完后 Save → 文件名 .config → OK → Exit

24.3 核心的编译与安装

24.3.1 编译核心与核心模块

# 主要编译命令
make bzImage           # 编译压缩后的核心
make modules           # 编译核心模块
make -j N clean bzImage modules    # 清理 + 并行编译
  • -j N:并行编译,N = CPU 核心数。$(nproc) 自动获取
  • 编译后核心位于 arch/x86/boot/bzImage

24.3.2 实际安装模块

避免同版本冲突的方法:在 General setup → Local version 中加上自定义后缀(如 3.10.89vbird)。

make modules_install
ll /lib/modules/       # 看到 3.10.89vbird 目录

24.3.3 开始安装新核心与多重核心菜单(grub)

保留旧核心:确保新核心有问题时能用旧核心开机恢复。

# 1. 复制核心和相关文件到 /boot
cp arch/x86/boot/bzImage /boot/vmlinuz-3.10.89vbird
cp .config /boot/config-3.10.89vbird
cp System.map /boot/System.map-3.10.89vbird
gzip -c Module.symvers > /boot/symvers-3.10.89vbird.gz
restorecon -Rv /boot
 
# 2. 创建 initramfs
dracut -v /boot/initramfs-3.10.89vbird.img 3.10.89vbird
 
# 3. 重建 grub 菜单(自动检测 /boot 下所有核心)
grub2-mkconfig -o /boot/grub2/grub.cfg
 
# 4. 重启 → 选择新核心 → 验证
reboot
uname -a     # Linux ... 3.10.89vbird ...

24.4 额外(单一)核心模块编译

24.4.1 编译前注意事项

模块编译需要核心源代码/lib/modules/$(uname -r)/ 下的两个关键链接:

ls -l /lib/modules/3.10.89vbird/
# build -> /usr/src/kernels/linux-3.10.89  ← 头文件 + 编译工具
# source -> /usr/src/kernels/linux-3.10.89 ← 源代码

编译模块需要:make, gcc, kernel-devel(或核心源代码)。

24.4.2 单一模块编译

场景一:硬件厂商提供的额外驱动

# 1. 下载、解压、编译
tar -zxvf driver.tar.gz && cd driver/
make                        # 利用核心 build 链接自动找到源代码
# 产生 driver.ko
 
# 2. 安装
cp driver.ko /lib/modules/$(uname -r)/kernel/drivers/xxx/
depmod -a                   # 更新模块相依性
 
# 3. 测试载入
modprobe driver
 
# 4. 如果需要开机时载入,重做 initramfs
dracut --force -v --add-drivers driver /boot/initramfs-xxx.img $(uname -r)

场景二:用已有核心源代码补编遗漏的模块

cd /usr/src/kernels/linux-3.10.89
make menuconfig              # 勾选遗漏的功能 → 设为 <M>
make fs/ntfs/                # 只编译该目录的模块
cp fs/ntfs/ntfs.ko /lib/modules/$(uname -r)/kernel/fs/ntfs/
depmod -a

24.4.3 核心模块管理

关键认知:核心、核心模块、驱动程序模块、核心源代码、头文件是环环相扣的。核心更新后,之前自行编译的模块会失效,需重新编译。modprobe 依赖 modules.dep 解析模块相依性。

24.5 以最新核心版本编译 CentOS 7.x 的核心

使用 ELRepo 提供的 SRPM 编译最新核心(示例:升级到 4.2.3):

# 1. 下载并安装 SRPM
wget http://elrepo.org/linux/kernel/el7/SRPMS/kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm
rpm -ivh kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm
 
# 2. 下载核心源代码
cd ~/rpmbuild/SOURCES
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.2.3.tar.xz
 
# 3. 修改功能(如开启 VFIO VGA 支持)
vim config-4.2.3-x86_64
# CONFIG_VFIO_PCI_VGA is not set → 改为 CONFIG_VFIO_PCI_VGA=y
 
# 4. 修改 .spec 文件(指定本地源代码文件)
cd ../SPECS
vim kernel-ml-4.2.spec
# Source0 改为: Source0: linux-%{LKAver}.tar.xz
 
# 5. 编译打包(可能需要数小时!)
rpmbuild -bb kernel-ml-4.2.spec
# 产生: /root/rpmbuild/RPMS/x86_64/kernel-ml-4.2.3-*.rpm
 
# 6. 安装
yum install /root/rpmbuild/RPMS/x86_64/kernel-ml-4.2.3-1.el7.centos.x86_64.rpm
reboot
uname -a   # 4.2.3!

命令速查表

命令用途
uname -r查看当前核心版本
tar -Jxvf linux-xxx.tar.xz -C /usr/src/kernels/解压核心源代码
make mrproper清除所有残留 + 配置文件(首次编译前)
make clean仅清除目标文件(保留 .config)
cp /boot/config-$(uname -r) .config以当前核心配置为基础
make menuconfig文字模式菜单选择核心功能
make oldconfig升级用——只提示新功能
make -j $(nproc) bzImage编译压缩核心
make -j $(nproc) modules编译核心模块
make modules_install安装模块到 /lib/modules/
cp arch/x86/boot/bzImage /boot/vmlinuz-xxx复制核心文件
dracut -v /boot/initramfs-xxx.img 版本号创建 initramfs
grub2-mkconfig -o /boot/grub2/grub.cfg重建 grub 菜单
depmod -a更新模块相依性数据库
make fs/ntfs/仅编译 ntfs 模块
rpmbuild -bb kernel-ml.spec从 SRPM 编译打包 RPM 核心