内核架构概览
Linux 内核是一个宏内核(Monolithic Kernel)设计,但通过模块化实现了一定程度的微内核特性。本章将深入探讨 Linux 内核的整体架构。
内核架构层次
┌─────────────────────────────────────────────────────┐
│ 用户空间 (User Space) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │应用程序 │ │系统工具 │ │Shell │ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ │
└────────┼─────────────┼─────────────┼────────────────┘
│ │ │
系统调用接口 (System Call Interface)
│ │ │
┌────────┼─────────────┼─────────────┼────────────────┐
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 虚拟文件系统 (VFS) │ │
│ └───────┬──────────────────────────────────────┘ │
│ │ │
│ ┌───────┴──────┬──────────┬──────────┬─────────┐ │
│ │ 进程调度 │ 内存管理│ 网络协议│ 设备驱动│ │
│ │ Scheduler │ MM │ Stack │ Drivers │ │
│ └──────────────┴──────────┴──────────┴─────────┘ │
│ │
│ 内核空间 (Kernel Space) │
└──────────────────────┬───────────────────────────────┘
│
硬件层 (Hardware)
主要子系统
1. 进程管理子系统
核心职责:
- 进程创建和销毁
- 进程调度(CFS - Completely Fair Scheduler)
- 进程间通信(IPC)
- 信号处理
核心概念:
进程描述符(task_struct)是内核中最重要的数据结构之一,它包含了进程的完整信息:
- 进程状态:运行、就绪、睡眠、停止等状态
- 进程标识:PID(进程ID)和 TGID(线程组ID)
- 调度信息:优先级、调度策略、时间片
- 内存空间:虚拟地址空间描述符
- 文件系统:当前工作目录、根目录
- 打开文件:文件描述符表
- 进程关系:父进程、子进程、兄弟进程
2. 内存管理子系统
核心功能:
- 虚拟内存管理
- 物理内存分配(Buddy 算法、Slab 分配器)
- 页面回收(Page Reclaim)
- 交换机制(Swap)
- 内存映射(mmap)
内存布局:
用户空间内存布局(64 位系统):
0x0000000000000000 ┌─────────────────┐
│ Text Segment │ 代码段
├─────────────────┤
│ Data Segment │ 数据段
├─────────────────┤
│ BSS Segment │ 未初始化数据
├─────────────────┤
│ Heap │ 堆(向上增长)
│ ↓ │
├─────────────────┤
│ │
│ Memory Map │ 内存映射区
│ │
├─────────────────┤
│ ↑ │
│ Stack │ 栈(向下增长)
0x00007FFFFFFFFFFF └─────────────────┘
内核空间内存布局:
0xFFFF800000000000 ┌─────────────────┐
│ Direct Map │ 直接映射物理内存
├─────────────────┤
│ vmalloc │ vmalloc 区域
├─────────────────┤
│ Kernel Text │ 内核代码段
├─────────────────┤
│ Kernel Data │ 内核数据段
├─────────────────┤
│ Modules │ 内核模块
0xFFFFFFFFFFFFFFFF └─────────────────┘
3. 虚拟文件系统(VFS)
设计思想:
- 提供统一的文件操作接口
- 支持多种文件系统(Ext4、XFS、Btrfs、NFS 等)
- 实现 dentry cache 和 inode cache
VFS 对象模型:
// 超级块对象(描述文件系统)
struct super_block {
struct list_head s_list;
dev_t s_dev;
unsigned long s_blocksize;
struct file_system_type *s_type;
const struct super_operations *s_op;
struct dentry *s_root;
};
// inode 对象(描述文件)
struct inode {
umode_t i_mode;
uid_t i_uid;
gid_t i_gid;
loff_t i_size;
struct timespec i_atime;
struct timespec i_mtime;
struct timespec i_ctime;
const struct inode_operations *i_op;
const struct file_operations *i_fop;
};
// dentry 对象(目录项)
struct dentry {
struct dentry *d_parent;
struct qstr d_name;
struct inode *d_inode;
const struct dentry_operations *d_op;
struct super_block *d_sb;
};
// file 对象(打开的文件)
struct file {
struct path f_path;
const struct file_operations *f_op;
loff_t f_pos;
fmode_t f_mode;
};
4. 网络协议栈
层次结构:
应用层
↓
套接字层 (Socket Layer)
↓
传输层 (TCP/UDP/SCTP)
↓
网络层 (IP/ICMP/IGMP)
↓
链路层 (Ethernet/ARP)
↓
网络设备驱动 (Device Driver)
↓
硬件 (NIC)
核心数据结构:
// Socket 缓冲区
struct sk_buff {
struct sk_buff *next;
struct sk_buff *prev;
struct sock *sk;
struct net_device *dev;
unsigned int len;
unsigned int data_len;
unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end;
};
// 网络设备
struct net_device {
char name[IFNAMSIZ];
unsigned long state;
struct net_device_stats stats;
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops;
unsigned int mtu;
unsigned char dev_addr[MAX_ADDR_LEN];
};
5. 设备驱动框架
设备模型:
Bus (总线)
├── Device (设备)
│ ├── Driver (驱动)
│ └── Platform Device
└── Class (设备类)
├── Character Device (字符设备)
├── Block Device (块设备)
└── Network Device (网络设备)
字符设备驱动框架:
// 文件操作结构
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
};
// 字符设备注册
int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops);
内核配置选项
查看当前内核配置:
# 查看当前运行内核的配置
cat /boot/config-$(uname -r)
# 或者(如果支持)
zcat /proc/config.gz
# 查看已加载的内核模块
lsmod
# 查看内核参数
sysctl -a
# 修改内核参数(临时)
sysctl -w net.ipv4.ip_forward=1
# 修改内核参数(永久)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
内核版本演进
版本命名规则:
主版本.次版本.修订版本[-发布版本]
例如:5.15.0-91-generic
5 - 主版本
15 - 次版本
0 - 修订版本
91 - 发布版本
generic - 发行版标识
重要版本里程碑:
- Linux 2.6 (2003):引入 NPTL、O(1) 调度器
- Linux 3.0 (2011):版本号重置,改进电源管理
- Linux 4.0 (2015):实时内核补丁、Live Patching
- Linux 5.0 (2019):改进 Energy Aware Scheduling
- Linux 6.0 (2022):Rust 语言支持初步引入
内核源码结构
linux/
├── arch/ # 架构相关代码(x86、ARM、MIPS 等)
├── block/ # 块设备层
├── crypto/ # 加密 API
├── Documentation/ # 文档
├── drivers/ # 设备驱动
│ ├── char/ # 字符设备
│ ├── block/ # 块设备
│ ├── net/ # 网络设备
│ └── ...
├── fs/ # 文件系统
│ ├── ext4/ # Ext4 文件系统
│ ├── btrfs/ # Btrfs 文件系统
│ └── ...
├── include/ # 头文件
│ └── linux/ # 内核头文件
├── init/ # 初始化代码
├── ipc/ # 进程间通信
├── kernel/ # 核心子系统
│ ├── sched/ # 调度器
│ ├── time/ # 时间管理
│ └── ...
├── lib/ # 库函数
├── mm/ # 内存管理
├── net/ # 网络协议栈
│ ├── ipv4/ # IPv4
│ ├── ipv6/ # IPv6
│ └── ...
├── scripts/ # 编译脚本
├── security/ # 安全模块(SELinux、AppArmor)
└── tools/ # 内核工具
实践:探索内核信息
#!/bin/bash
# kernel-info.sh - 内核信息收集脚本
echo "======================================"
echo "Linux 内核信息汇总"
echo "======================================"
# 内核版本
echo ""
echo "1. 内核版本:"
uname -a
# CPU 架构
echo ""
echo "2. CPU 架构:"
lscpu | grep "Architecture\|CPU(s)\|Model name"
# 内存信息
echo ""
echo "3. 内存信息:"
free -h
# 内核编译时间
echo ""
echo "4. 内核编译信息:"
cat /proc/version
# 命令行参数
echo ""
echo "5. 内核启动参数:"
cat /proc/cmdline
# 加载的模块数量
echo ""
echo "6. 已加载模块数:"
lsmod | wc -l
# 进程数
echo ""
echo "7. 当前进程数:"
ps aux | wc -l
# 系统运行时间
echo ""
echo "8. 系统运行时间:"
uptime
# 内核消息
echo ""
echo "9. 最近的内核消息(最后 10 条):"
dmesg | tail -10
echo ""
echo "======================================"
关键概念总结
1. 内核空间 vs 用户空间
- 内核空间拥有最高权限(Ring 0)
- 用户空间权限受限(Ring 3)
- 通过系统调用接口通信
2. 宏内核 vs 微内核
- Linux 采用宏内核设计
- 所有核心服务运行在内核空间
- 通过模块化实现灵活性
3. 抢占式多任务
- 内核可以抢占用户进程
- 内核可以抢占其他内核任务(CONFIG_PREEMPT)
4. SMP(对称多处理)
- 支持多 CPU/多核心
- 自旋锁、信号量等同步机制
下一步:学习 启动流程详解 章节。