Linux 内核概览
一、内核设计哲学
- 单体内核(Monolithic):所有功能都在内核态
- 但支持可加载模块(Loadable Kernel Module, LKM)
- Linux 不是微内核(与 Mach、QNX 不同)
二、内核版本
5.10 长期支持版(LTS)
5.15 LTS(很多发行版采用)
6.1 LTS
6.6 LTS
格式:主版本.次版本.修订版本
- 偶数次版本 = 稳定
- 奇数次版本 = 开发(早期)
三、源码结构(5.x)
linux/
├── arch/ 架构相关代码(arm, arm64, x86, riscv...)
├── block/ 块设备核心
├── crypto/ 加密算法
├── drivers/ 各种驱动
│ ├── char/
│ ├── block/
│ ├── net/
│ ├── i2c/
│ ├── spi/
│ ├── gpio/
│ ├── pinctrl/
│ ├── tty/
│ ├── usb/
│ ├── mmc/
│ └── ...
├── fs/ 文件系统(ext4, fat, proc, sysfs...)
├── include/ 头文件
├── init/ 启动代码(main.c)
├── ipc/ 进程间通信
├── kernel/ 调度、模块、信号等
├── lib/ 通用库(排序、校验和、压缩)
├── mm/ 内存管理
├── net/ 网络协议栈
├── samples/ 示例代码
├── scripts/ 构建脚本
├── security/ SELinux, apparmor
├── sound/ 音频
├── tools/ perf, bpf 等
├── usr/ initramfs 生成
├── virt/ KVM
├── Documentation/ 大量文档(必看)
├── Kconfig
├── Kbuild
├── Makefile
├── README
├── COPYING
└── MAINTAINERS
四、内核 vs 用户态
| 特性 |
用户态 |
内核态 |
| 特权级 |
低 |
高 |
| 内存访问 |
受限 |
全部 |
| 栈 |
8MB |
4-16KB |
| 调度 |
可被抢占 |
代码段可能关闭抢占 |
| 库函数 |
glibc |
内核自实现(printk, kmalloc) |
| 标准 C |
全部可用 |
部分(无 libc) |
| 浮点 |
可以 |
禁用(需特别启用) |
| 错误处理 |
errno |
返回 -ERRNO 指针 |
五、内核编译
1. 配置
# 多种方式
make defconfig # 默认
make xxxx_defconfig # 板级默认
make menuconfig # TUI 配置
make nconfig # 新的 TUI
make xconfig # Qt 配置(需 qt)
make gconfig # GTK(需 gtk)
make oldconfig # 升级旧 .config
make savedefconfig # 提取最小配置
# 配置已保存到 .config
2. 编译
make -j$(nproc)
make zImage # ARM 旧格式
make Image # ARM 未压缩
make uImage # U-Boot 格式(需安装 mkimage)
make dtbs # 编译设备树
make modules # 编译模块
make modules_install INSTALL_MOD_PATH=/path/to/rootfs
make install # 安装内核到 /boot
3. 输出
arch/arm/boot/zImage ARM 压缩内核
arch/arm/boot/dts/*.dtb 设备树二进制
vmlinux 未压缩、含符号的 ELF(调试用)
六、启动流程(ARM)
上电
↓
ROM/BOOT ROM(芯片内置)
↓
Bootloader 第一阶段(可选:固化在板载 NOR Flash)
↓
Bootloader 第二阶段(U-Boot)
↓
内核自解压 → start_kernel()
↓
setup_arch()、sched_init()、页表初始化、trap_init()
↓
rest_init() → kernel_init → 启动 init 进程
↓
挂载 rootfs
↓
执行 /sbin/init(或 /init)
↓
systemd / busybox init
↓
用户空间启动
七、内核主要子系统
| 子系统 |
位置 |
职责 |
| 进程调度 |
kernel/sched/ |
CFS、实时调度 |
| 内存管理 |
mm/ |
页表、虚拟内存 |
| VFS |
fs/ |
通用文件系统抽象 |
| 网络 |
net/ |
协议栈、设备 |
| IPC |
ipc/ |
信号量、共享内存、消息队列 |
| 设备驱动 |
drivers/ |
各种硬件 |
| 中断 |
kernel/irq/ |
中断处理 |
| 时间 |
kernel/time/ |
tick、定时器 |
| 安全 |
security/ |
SELinux、capability |
八、内核编程基础
1. 头文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h> // copy_to_user / copy_from_user
#include <linux/io.h> // ioremap / iounmap
#include <linux/slab.h> // kmalloc / kfree
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h> // device tree
2. 常用宏
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Me");
MODULE_DESCRIPTION("A demo");
MODULE_VERSION("0.1");
pr_info("hello %s\n", __func__);
pr_err("failed: %d\n", ret);
dev_err(dev, "msg"); // 自动包含设备名
dev_info(dev, "msg");
3. 内核不能用的用户态函数
// 不能用:
printf → pr_info / printk / dev_info
malloc → kmalloc / kvmalloc
free → kfree
memcpy → memcpy // 这个能用
strcpy → strscpy / strlcpy(推荐)
memset → memset
open → filp_open
sleep → msleep / ssleep / schedule_timeout
usleep → udelay / usleep_range // 短延迟
exit() → return // 模块函数
九、内核调试基础
printk → dmesg 查看
CONFIG_DYNAMIC_DEBUG=y → echo "file foo.c +p" > /sys/kernel/debug/dynamic_debug/control
CONFIG_DEBUG_KERNEL=y
CONFIG_KASAN=y:内核地址消毒
CONFIG_LOCKDEP=y:锁依赖检查
CONFIG_PROVE_LOCKING=y:锁使用证明