这里详细解析Linux内核的总体架构,并对每个核心模块进行深入的剖析。Linux内核是宏内核架构的典范,但采用了模块化设计,使其兼具高性能和可扩展性。
一、Linux内核总体架构全景
架构层次图
┌─────────────────────────────────────────────────────────────────────┐
│ 用户空间 (Userspace) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Shell │ │ 应用软件 │ │ 库函数 │ │ 运行时 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ 系统调用接口 (System Call Interface) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ POSIX系统调用 │ Linux特有调用 │ 架构相关调用 │ 虚拟系统调用 │ │
│ └─────────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ 内核空间 (Kernel Space) │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ 进程管理 │ │ 内存管理 │ │ 虚拟文件 │ │ 网络栈 │ │
│ │ 子系统 │ │ 子系统 │ │ 系统(VFS) │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │调度器 │ │ │ │分配器 │ │ │ │ 文件 │ │ │ │TCP/IP │ │ │
│ │ │ │ │ │ │伙伴 │ │ │ │ 系统 │ │ │ │协议栈 │ │ │
│ │ │CFS │ │ │ │系统 │ │ │ │ Ext4 │ │ │ │ │ │ │
│ │ │实时 │ │ │ │Slab │ │ │ │ XFS │ │ │ │ │ │ │
│ │ │调度器 │ │ │ │ │ │ │ │ Btrfs │ │ │ │ │ │ │
│ └─┴───────┘ └─┴───────┘ └─┴───────┘ └─┴───────┘ │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ 设备驱动 │ │ IPC │ │ 安全模块 │ │ 内核模块 │ │
│ │ 模型 │ │ 子系统 │ │ │ │ 机制 │ │
│ │ │ │ │ │ │ │ │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │字符 │ │ │ │信号 │ │ │ │SELinux│ │ │ │模块 │ │ │
│ │ │设备 │ │ │ │信号量 │ │ │ │AppArm │ │ │ │加载 │ │ │
│ │ │块设备 │ │ │ │共享 │ │ │ │ │ │ │ │卸载 │ │ │
│ │ │网络 │ │ │ │内存 │ │ │ │ │ │ │ │ │ │ │
│ │ │设备 │ │ │ │消息 │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │队列 │ │ │ │ │ │ │ │ │ │ │
│ └─┴───────┘ └─┴───────┘ └─┴───────┘ └─┴───────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 硬件抽象层 (Hardware Abstraction Layer) │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │中断 │ │时钟 │ │DMA │ │I/O │ │电源 │ │ │
│ │ │管理 │ │管理 │ │管理 │ │端口 │ │管理 │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │
│ └──┴──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │ │
├─────────────────────────────────────────────────────────────────────┤
│ 硬件平台 (Hardware Platform) │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │CPU │ │内存 │ │磁盘 │ │网卡 │ │其他 │ │
│ │ │ │ │ │ │ │ │ │外设 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
└─────────────────────────────────────────────────────────────────────┘
二、核心子系统详细解析
1. 进程管理子系统
功能:负责进程的创建、调度、同步和通信。
进程调度架构
// 调度器层次结构
struct sched_class {
const struct sched_class *next; // 调度类链表
// 任务入队
void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
// 任务出队
void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
// 任务切换
void (*put_prev_task) (struct rq *rq, struct task_struct *p);
struct task_struct * (*pick_next_task) (struct rq *rq);
// 时钟中断处理
void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
// 任务唤醒
void (*task_woken) (struct rq *this_rq, struct task_struct *task);
// 任务迁移
void (*set_cpus_allowed)(struct task_struct *p, const struct cpumask *newmask);
// 任务切换上下文
void (*switched_from) (struct rq *this_rq, struct task_struct *task);
void (*switched_to) (struct rq *this_rq, struct task_struct *task);
};
三种调度器实现
1. CFS调度器(完全公平调度器)
// kernel/sched/fair.c
// 核心算法:红黑树管理虚拟运行时间
struct cfs_rq {
struct load_weight load; // 队列权重
unsigned int nr_running; // 运行任务数
u64 min_vruntime; // 最小虚拟运行时间
// 红黑树根节点
struct rb_root_cached tasks_timeline;
// 当前运行任务
struct sched_entity *curr;
struct sched_entity *next;
struct sched_entity *last;
// 统计信息
unsigned long h_nr_running; // 层次运行任务数
};
// 虚拟运行时间计算
static void update_curr(struct cfs_rq *cfs_rq) {
struct sched_entity *curr = cfs_rq->curr;
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
if (unlikely(!curr))
return;
// 计算实际运行时间
delta_exec = now - curr->exec_start;
if (unlikely((s64)delta_exec <= 0))
return;
curr->exec_start = now;
// 更新虚拟运行时间
curr->vruntime += calc_delta_fair(delta_exec, curr);
// 更新cfs_rq的最小虚拟运行时间
if (entity_before(curr, cfs_rq->min_vruntime))
cfs_rq->min_vruntime = curr->vruntime;
}
2. 实时调度器
// kernel/sched/rt.c
// 实时调度类定义
const struct sched_class rt_sched_class = {
.next = &fair_sched_class,
.enqueue_task = enqueue_task_rt,
.dequeue_task = dequeue_task_rt,
.yield_task = yield_task_rt,
.check_preempt_curr = check_preempt_curr_rt,
.pick_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
.set_cpus_allowed = set_cpus_allowed_rt,
.task_tick = task_tick_rt,
.get_rr_interval = get_rr_interval_rt,
.prio_changed = prio_changed_rt,
.switched_to = switched_to_rt,
};
3. Deadline调度器
// kernel/sched/deadline.c
// 截止时间调度策略
struct sched_dl_entity {
struct rb_node rb_node; // 红黑树节点
u64 dl_runtime; // 运行时间预算
u64 dl_deadline; // 相对截止时间
u64 dl_period; // 周期
u64 dl_bw; // 带宽
u64 dl_density; // 密度
// 运行队列
struct hrtimer dl_timer; // 高分辨率定时器
struct hrtimer inactive_timer; // 非活跃定时器
};
进程状态转换
// 进程状态定义
#define TASK_RUNNING 0x0000
#define TASK_INTERRUPTIBLE 0x0001
#define TASK_UNINTERRUPTIBLE 0x0002
#define __TASK_STOPPED 0x0004
#define __TASK_TRACED 0x0008
#define EXIT_DEAD 0x0010
#define EXIT_ZOMBIE 0x0020
#define TASK_PARKED 0x0040
#define TASK_DEAD 0x0080
#define TASK_WAKEKILL 0x0100
#define TASK_WAKING 0x0200
#define TASK_NOLOAD 0x0400
#define TASK_NEW 0x0800
#define TASK_STATE_MAX 0x1000
// 状态转换函数
static void __set_task_state(struct task_struct *tsk, int state) {
set_mb(tsk->state, state);
}
2. 内存管理子系统
功能:管理物理和虚拟内存,包括分配、回收、映射等。
三层内存模型
┌─────────────────────────────────────────────┐
│ 物理内存架构 │
├─────────────────────────────────────────────┤
│ 节点0 (Node 0) 节点1 (Node 1) ... │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 区域0 DMA │ │ 区域0 DMA │ │
│ │ 区域1 DMA32│ │ 区域1 DMA32│ │
│ │ 区域2 普通 │ │ 区域2 普通 │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────┘
物理内存管理算法
1. 伙伴系统(Buddy System)
// mm/page_alloc.c
// 伙伴系统空闲区域管理
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};
// 内存区域定义
struct zone {
// 水线
unsigned long watermark[NR_WMARK];
// 伙伴系统空闲列表
struct free_area free_area[MAX_ORDER];
// 每CPU页面缓存
struct per_cpu_pageset __percpu *pageset;
// 统计信息
atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
// 页回收
unsigned long flags;
// 内存紧缩
spinlock_t lock;
};
2. SLAB分配器
// mm/slab.c
// SLAB缓存结构
struct kmem_cache {
// 每CPU缓存
struct array_cache __percpu *cpu_cache;
// 节点缓存
struct kmem_cache_node *node[MAX_NUMNODES];
// 对象大小和对齐
unsigned int size;
unsigned int align;
// 构造函数/析构函数
void (*ctor)(void *);
// 标志
slab_flags_t flags;
// 统计
unsigned int num;
unsigned int gfporder;
// 着色
unsigned int colour;
unsigned int colour_off;
};
3. SLUB分配器(默认)
// mm/slub.c
// SLUB缓存结构
struct kmem_cache {
struct kmem_cache_cpu __percpu *cpu_slab;
unsigned long flags;
unsigned long min_partial;
int size; // 对象大小
int object_size; // 实际对象大小
int offset; // 空闲指针偏移
int cpu_partial; // 每CPU部分空闲对象数
struct kmem_cache_order_objects oo;
struct kmem_cache_order_objects max;
struct kmem_cache_order_objects min;
gfp_t allocflags; // 分配标志
int refcount;
void (*ctor)(void *);
int inuse; // 实际使用大小
int align; // 对齐
int reserved; // 保留字节
const char *name; // 名称
struct list_head list; // 缓存链表
int remote_node_defrag_ratio;
struct kmem_cache_node *node[MAX_NUMNODES];
};
虚拟内存管理
1. 页表管理
// 四级页表结构(x86_64)
typedef struct { unsigned long p4d; } p4d_t;
typedef struct { unsigned long pud; } pud_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pte; } pte_t;
// 页表项标志
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
#define _PAGE_USER 0x004
#define _PAGE_PWT 0x008
#define _PAGE_PCD 0x010
#define _PAGE_ACCESSED 0x020
#define _PAGE_DIRTY 0x040
#define _PAGE_PSE 0x080
#define _PAGE_GLOBAL 0x100
#define _PAGE_NX 0x8000000000000000ULL
2. 虚拟内存区域(VMA)管理
// mm_types.h
struct vm_area_struct {
// 内存区域边界
unsigned long vm_start;
unsigned long vm_end;
// 链接结构
struct mm_struct *vm_mm;
pgprot_t vm_page_prot;
unsigned long vm_flags;
// 红黑树节点
struct rb_node vm_rb;
// 文件映射
struct file *vm_file;
unsigned long vm_pgoff;
// 匿名映射
struct anon_vma *anon_vma;
struct list_head anon_vma_chain;
// 操作函数
const struct vm_operations_struct *vm_ops;
// 名称
const char *vm_name;
};
3. 虚拟文件系统(VFS)
功能:为不同文件系统提供统一的抽象接口。
VFS核心数据结构
// 超级块结构
struct super_block {
// 超级块操作
const struct super_operations *s_op;
// 文件系统类型
struct file_system_type *s_type;
// 根目录
struct dentry *s_root;
// 活动inode链表
struct list_head s_inodes;
// 块大小
unsigned long s_blocksize;
// 最大文件大小
loff_t s_maxbytes;
// 文件系统特定信息
void *s_fs_info;
// 引用计数
atomic_t s_count;
};
文件系统操作抽象
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 *);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);
void (*show_fdinfo)(struct seq_file *m, struct file *f);
};
文件系统类型
1. Ext4文件系统
// fs/ext4/ext4.h
// Ext4超级块
struct ext4_super_block {
__le32 s_inodes_count; // inode总数
__le32 s_blocks_count_lo; // 块总数
__le32 s_r_blocks_count_lo; // 保留块数
__le32 s_free_blocks_count_lo; // 空闲块数
__le32 s_free_inodes_count; // 空闲inode数
__le32 s_first_data_block; // 第一个数据块
__le32 s_log_block_size; // 块大小
__le32 s_log_cluster_size; // 簇大小
__le32 s_blocks_per_group; // 每组块数
__le32 s_clusters_per_group; // 每组簇数
__le32 s_inodes_per_group; // 每组inode数
__le32 s_mtime; // 挂载时间
__le32 s_wtime; // 写时间
__le16 s_mnt_count; // 挂载计数
__le16 s_max_mnt_count; // 最大挂载计数
__le16 s_magic; // 魔术字
__le16 s_state; // 文件系统状态
__le16 s_errors; // 错误处理
__le16 s_minor_rev_level; // 次版本
__le32 s_lastcheck; // 最后检查时间
__le32 s_checkinterval; // 检查间隔
__le32 s_creator_os; // 创建者OS
__le32 s_rev_level; // 版本级别
__le16 s_def_resuid; // 默认保留用户ID
__le16 s_def_resgid; // 默认保留组ID
// ... 更多字段
};
2. Btrfs文件系统
// fs/btrfs/ctree.h
// Btrfs超级块
struct btrfs_super_block {
__le64 bytenr; // 物理地址
__le64 flags; // 标志
__u8 csum[BTRFS_CSUM_SIZE]; // 校验和
__u8 fsid[BTRFS_FSID_SIZE]; // 文件系统ID
__le64 magic; // 魔术字
__le64 generation; // 代
__le64 root; // 根地址
__le64 chunk_root; // 块树根
__le64 log_root; // 日志根
__le64 log_root_transid; // 日志根事务ID
__le64 total_bytes; // 总字节数
__le64 bytes_used; // 已用字节数
__le64 root_dir_objectid; // 根目录对象ID
__le64 num_devices; // 设备数
__le32 sectorsize; // 扇区大小
__le32 nodesize; // 节点大小
__le32 leafsize; // 叶大小
__le32 stripesize; // 条带大小
__le32 sys_chunk_array_size; // 系统块数组大小
__le64 chunk_root_generation; // 块树根代
__le64 compat_flags; // 兼容标志
__le64 compat_ro_flags; // 只读兼容标志
__le64 incompat_flags; // 不兼容标志
__le16 csum_type; // 校验和类型
__u8 root_level; // 根级别
__u8 chunk_root_level; // 块树根级别
__u8 log_root_level; // 日志根级别
struct btrfs_dev_item dev_item; // 设备项
__le64 cache_generation; // 缓存代
__le64 uuid_tree_generation; // UUID树代
__le64 reserved[30]; // 保留
__u8 metadata_uuid[BTRFS_FSID_SIZE]; // 元数据UUID
};
4. 网络子系统
功能:实现各种网络协议,提供网络通信能力。
网络协议栈架构
┌─────────────────────────────────────────┐
│ 应用程序层 (Application) │
├─────────────────────────────────────────┤
│ 套接字层 (Socket Layer) │
├─────────────────────────────────────────┤
│ 传输层 (Transport Layer) │
│ TCP UDP SCTP │
├─────────────────────────────────────────┤
│ 网络层 (Network Layer) │
│ IPv4 IPv6 ICMP │
├─────────────────────────────────────────┤
│ 数据链路层 (Data Link Layer) │
│ 以太网 WiFi PPP │
├─────────────────────────────────────────┤
│ 物理层 (Physical Layer) │
└─────────────────────────────────────────┘
套接字缓冲区(sk_buff)
// include/linux/skbuff.h
struct sk_buff {
// 链表管理
union {
struct {
struct sk_buff *next;
struct sk_buff *prev;
union {
struct net_device *dev;
unsigned long dev_scratch;
};
};
struct rb_node rbnode; // 用于快速路径
};
// 缓冲区指针
unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end;
// 长度信息
unsigned int len;
unsigned int data_len;
__u16 mac_len;
__u16 hdr_len;
// 协议信息
__be16 protocol;
__u16 transport_header;
__u16 network_header;
__u16 mac_header;
// 校验和
__wsum csum;
__u32 csum_start;
__u32 csum_offset;
// 拥塞控制
__u32 priority;
__u16 queue_mapping;
__u8 pfmemalloc:1;
__u8 ignore_df:1;
__u8 cloned:1;
__u8 ip_summed:2;
__u8 nohdr:1;
__u8 nfctinfo:3;
__u8 pkt_type:3;
__u8 ipvs_property:1;
__u8 inner_protocol_type:1;
__u8 remcsum_offload:1;
// 时间戳
__u32 tstamp;
// 所有者
struct sock *sk;
struct nf_conntrack *nfct;
// 安全
struct sec_path *sp;
// 扩展头
char cb[48] __aligned(8);
unsigned long _skb_refdst;
void (*destructor)(struct sk_buff *skb);
};
TCP协议实现
// net/ipv4/tcp.c
// TCP控制块
struct tcp_sock {
// 继承inet_connection_sock
struct inet_connection_sock inet_conn;
// 发送序列号
u32 snd_una; // 最早未确认序列号
u32 snd_nxt; // 下一个发送序列号
u32 snd_up; // 紧急指针
u32 snd_wl1; // 窗口更新段序列号
u32 snd_wl2; // 窗口更新段确认号
u32 iss; // 初始发送序列号
u32 irs; // 初始接收序列号
// 接收序列号
u32 rcv_nxt; // 下一个期望序列号
u32 rcv_wup; // 窗口更新前一个rcv_nxt
u32 copied_seq; // 已拷贝到用户空间的序列号
// 窗口
u32 snd_wnd; // 发送窗口
u32 snd_cwnd; // 拥塞窗口
u32 snd_ssthresh; // 慢启动阈值
u32 rcv_wnd; // 接收窗口
// 定时器
unsigned long retrans_stamp; // 重传时间戳
u32 retrans_out; // 重传输出段数
u32 undo_marker; // 撤销标记
int undo_retrans; // 撤销重传计数
// 状态
u32 syn_retries; // SYN重试次数
u32 tcp_header_len; // TCP头部长度
u32 mss_cache; // 缓存的MSS
// 拥塞控制
u32 snd_cwnd_cnt; // 拥塞窗口计数
u32 snd_cwnd_clamp; // 拥塞窗口钳制
u32 snd_cwnd_used; // 使用的拥塞窗口
u32 snd_cwnd_stamp; // 拥塞窗口时间戳
// 接收缓冲区
u32 rcv_ssthresh; // 接收慢启动阈值
u32 rcv_rtt_last_tsecr;
u32 rcv_rtt_est_seq;
u32 rcv_rtt_est_res;
// 时间戳
u32 tsoffset; // 时间戳偏移
// 扩展选项
u32 ts_recent; // 最近时间戳
u32 ts_recent_stamp; // 最近时间戳时间
// 选择性确认
struct tcp_sack_block duplicate_sack[1]; // 重复SACK
struct tcp_sack_block selective_acks[4]; // 选择性确认
u8 num_sacks; // SACK数量
u8 dup_ack_counter; // 重复ACK计数
// 快速重传/恢复
u32 prior_ssthresh; // 先前慢启动阈值
u32 lost_out; // 丢失段数
u32 retrans_out; // 重传段数
u32 fackets_out; // FACK输出段数
// 状态标志
u16 advmss; // 通告MSS
u8 reordering; // 重排序等级
u8 nonagle; // Nagle算法控制
u8 thin_lto; // 薄流超时
u8 thin_dupack; // 薄重复ACK
u8 repair; // 修复模式
u8 do_early_retrans; // 早期重传
u8 syn_data; // SYN携带数据
u8 syn_fastopen; // 快速打开SYN
u8 syn_data_acked; // SYN数据已确认
u8 is_cwnd_limited; // 拥塞窗口受限
// 高精度定时器
u32 tcp_mstamp; // 最近接收段时间戳
u32 srtt_us; // 平滑RTT(微秒)
u32 mdev_us; // 平均偏差
u32 mdev_max_us; // 最大平均偏差
u32 rttvar_us; // RTT方差
// 拥塞控制算法
struct tcp_congestion_ops *ca_ops;
u32 prior_cwnd; // 先前拥塞窗口
u32 high_seq; // 高序列号
u32 snd_limited; // 发送受限
};
5. 设备驱动模型
功能:统一设备管理框架,支持热插拔、电源管理等。
设备模型核心
// 设备结构
struct device {
struct device *parent; // 父设备
struct device_private *p; // 私有数据
struct kobject kobj; // kobject
const char *init_name; // 初始名称
const struct device_type *type; // 设备类型
struct mutex mutex; // 互斥锁
struct bus_type *bus; // 总线类型
struct device_driver *driver; // 设备驱动
void *platform_data; // 平台数据
void *driver_data; // 驱动数据
struct device_node *of_node; // 设备树节点
struct fwnode_handle *fwnode; // 固件节点
dev_t devt; // 设备号
u32 id; // 设备ID
spinlock_t devres_lock;
struct list_head devres_head;
struct class *class; // 设备类
const struct attribute_group **groups; // 属性组
void (*release)(struct device *dev); // 释放函数
struct iommu_group *iommu_group; // IOMMU组
bool offline_disabled:1; // 禁止离线
bool offline:1; // 离线状态
};
总线-设备-驱动模型
// 总线类型
struct bus_type {
const char *name; // 总线名称
const char *dev_name; // 设备名称
struct device *dev_root; // 根设备
const struct attribute_group **bus_groups; // 总线属性组
const struct attribute_group **dev_groups; // 设备属性组
const struct attribute_group **drv_groups; // 驱动属性组
int (*match)(struct device *dev, struct device_driver *drv); // 匹配函数
int (*uevent)(struct device *dev, struct kobj_uevent_env *env); // 热插拔事件
int (*probe)(struct device *dev); // 探测函数
int (*remove)(struct device *dev); // 移除函数
void (*shutdown)(struct device *dev); // 关闭函数
int (*online)(struct device *dev); // 上线函数
int (*offline)(struct device *dev); // 下线函数
int (*suspend)(struct device *dev, pm_message_t state); // 挂起函数
int (*resume)(struct device *dev); // 恢复函数
const struct dev_pm_ops *pm; // 电源管理操作
struct iommu_ops *iommu_ops; // IOMMU操作
struct subsys_private *p; // 私有数据
struct lock_class_key lock_key; // 锁类键
};
6. 中断子系统
功能:处理硬件中断,提供中断控制器抽象。
中断描述符
// 中断描述符
struct irq_desc {
struct irq_common_data irq_common_data; // 通用数据
struct irq_data irq_data; // 中断数据
unsigned int __percpu *kstat_irqs; // 统计
irq_flow_handler_t handle_irq; // 中断处理函数
struct irqaction *action; // 中断动作
unsigned int status_use_accessors; // 状态
unsigned int core_internal_state__do_not_mess_with_it; // 核心内部状态
unsigned int depth; // 深度
unsigned int wake_depth; // 唤醒深度
unsigned int irq_count; // 中断计数
unsigned long last_unhandled; // 最后未处理
unsigned int irqs_unhandled; // 未处理中断数
raw_spinlock_t lock; // 自旋锁
struct cpumask *percpu_enabled; // 每CPU启用
const struct cpumask *percpu_affinity; // 每CPU亲和性
struct rcuwait wait_for_threads; // 线程等待
};
中断控制器
// 中断控制器芯片
struct irq_chip {
struct device *parent_device; // 父设备
const char *name; // 名称
unsigned int (*irq_startup)(struct irq_data *data); // 启动
void (*irq_shutdown)(struct irq_data *data); // 关闭
void (*irq_enable)(struct irq_data *data); // 启用
void (*irq_disable)(struct irq_data *data); // 禁用
void (*irq_ack)(struct irq_data *data); // 确认
void (*irq_mask)(struct irq_data *data); // 掩码
void (*irq_mask_ack)(struct irq_data *data); // 掩码并确认
void (*irq_unmask)(struct irq_data *data); // 取消掩码
void (*irq_eoi)(struct irq_data *data); // 中断结束
int (*irq_set_affinity)(struct irq_data *data, // 设置亲和性
const struct cpumask *dest, bool force);
int (*irq_retrigger)(struct irq_data *data); // 重触发
int (*irq_set_type)(struct irq_data *data, unsigned int flow_type); // 设置类型
int (*irq_set_wake)(struct irq_data *data, unsigned int on); // 设置唤醒
void (*irq_bus_lock)(struct irq_data *data); // 总线锁
void (*irq_bus_sync_unlock)(struct irq_data *data); // 总线同步解锁
void (*irq_cpu_online)(struct irq_data *data); // CPU上线
void (*irq_cpu_offline)(struct irq_data *data); // CPU下线
void (*irq_suspend)(struct irq_data *data); // 挂起
void (*irq_resume)(struct irq_data *data); // 恢复
void (*irq_pm_shutdown)(struct irq_data *data); // 电源管理关闭
void (*irq_calc_mask)(struct irq_data *data); // 计算掩码
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); // 打印芯片
int (*irq_request_resources)(struct irq_data *data); // 请求资源
void (*irq_release_resources)(struct irq_data *data); // 释放资源
unsigned long flags; // 标志
};
三、内核关键算法实现
1. 调度器算法
// CFS调度器pick_next_task算法
static struct task_struct *
pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) {
struct cfs_rq *cfs_rq = &rq->cfs;
struct sched_entity *se;
struct task_struct *p;
// 如果没有任务,返回idle
if (!cfs_rq->nr_running)
return NULL;
// 如果设置了跳过标志,直接返回
if (prev && prev->sched_class == &fair_sched_class &&
rq->cfs.skip == prev)
goto simple;
// 从红黑树中选择最小vruntime的任务
se = pick_next_entity(cfs_rq, NULL);
p = task_of(se);
// 如果选择的是idle任务,返回NULL
if (p == rq->idle)
return NULL;
simple:
// 简单情况:只有一个任务
if (cfs_rq->nr_running == 1) {
se = __pick_first_entity(cfs_rq);
p = task_of(se);
if (p != rq->idle)
goto found;
return NULL;
}
// 设置跳过标志
rq->cfs.skip = NULL;
found:
// 更新统计数据
update_stats_wait_start(cfs_rq, se);
return p;
}
2. 伙伴系统算法
// 伙伴系统内存分配
static struct page *__rmqueue(struct zone *zone, unsigned int order,
int migratetype, unsigned int alloc_flags) {
struct page *page;
retry_reserve:
// 首先尝试从指定迁移类型的空闲列表中分配
page = __rmqueue_smallest(zone, order, migratetype);
if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
// 如果失败,尝试从备选迁移类型分配
page = __rmqueue_fallback(zone, order, migratetype);
// 如果还是失败,使用保留页
if (!page && alloc_flags & ALLOC_NO_WATERMARKS) {
migratetype = MIGRATE_RESERVE;
goto retry_reserve;
}
}
trace_mm_page_alloc_zone_locked(page, order, migratetype);
return page;
}
// 从最小order开始搜索
static struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
int migratetype) {
unsigned int current_order;
struct free_area *area;
struct page *page;
// 从请求的order开始,向上搜索
for (current_order = order; current_order < MAX_ORDER; ++current_order) {
area = &(zone->free_area[current_order]);
page = list_first_entry_or_null(&area->free_list[migratetype],
struct page, lru);
if (!page)
continue;
// 从空闲列表中删除
list_del(&page->lru);
rmv_page_order(page);
area->nr_free--;
// 扩展页面(如果需要分裂)
expand(zone, page, order, current_order, area, migratetype);
set_pcppage_migratetype(page, migratetype);
return page;
}
return NULL;
}
3. TCP拥塞控制算法
// CUBIC拥塞控制算法
static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked) {
u32 delta, bic_target, max_cnt;
u64 offs;
u32 t = ca->delay_min >> 3; // 最小延迟
// 重置计数
ca->ack_cnt += acked;
if (ca->last_cwnd == cwnd &&
(s32)(tcp_jiffies32 - ca->last_time) <= HZ / 32)
return;
ca->last_cwnd = cwnd;
ca->last_time = tcp_jiffies32;
if (ca->epoch_start == 0) { // 新周期开始
ca->epoch_start = tcp_jiffies32;
ca->ack_cnt = acked;
ca->tcp_cwnd = cwnd;
if (ca->last_max_cwnd <= cwnd) {
ca->bic_K = 0;
ca->bic_origin_point = cwnd;
} else {
// 计算新的K值
ca->bic_K = cubic_root(cube_factor
* (ca->last_max_cwnd - cwnd));
ca->bic_origin_point = ca->last_max_cwnd;
}
}
// 计算目标窗口
t = (s32)(tcp_jiffies32 - ca->epoch_start);
t += msecs_to_jiffies(ca->delay_min >> 3);
offs = (t * t * t) << 3;
bic_target = ca->bic_origin_point + (offs >> 10);
if (bic_target < cwnd) { // 凸区域
ca->cnt = cwnd / (cwnd - bic_target);
} else { // 凹区域
ca->cnt = 100 * cwnd;
}
// 限制cnt增长过快
if (ca->cnt > 2)
ca->cnt = 2;
}
四、内核模块机制
模块加载机制
// 模块结构
struct module {
enum module_state state; // 模块状态
struct list_head list; // 模块链表
char name[MODULE_NAME_LEN]; // 模块名称
// 版本控制
struct module_version_attribute *version_attrs;
const char *version;
const char *srcversion;
// 符号表
const struct kernel_symbol *syms;
const unsigned long *crcs;
unsigned int num_syms;
// GPL符号
const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs;
unsigned int num_gpl_syms;
// 异常表
const struct exception_table_entry *extable;
unsigned int num_exentries;
// 初始化/退出函数
int (*init)(void);
void *module_init;
void *module_core;
unsigned int init_size, core_size;
unsigned int init_text_size, core_text_size;
unsigned int init_ro_size, core_ro_size;
unsigned int init_data_size, core_data_size;
// 权限
const struct kernel_param *kp;
unsigned int num_kp;
// 签名
bool sig_ok;
bool async_probe_requested;
// 符号查找
bool using_gplonly_symbols;
// 异常处理
struct exception_table_entry *extable;
unsigned int num_exentries;
// 模块引用
struct module *refptr;
// 内核对象
struct kobject kobj;
// 许可证
const char *license;
// 损坏标志
unsigned int taints;
// 每CPU数据
void *percpu;
unsigned int percpu_size;
// 驱动程序数据
char *args;
// 核心模块标志
bool core_kernel;
};
五、内核启动流程
启动阶段
// 内核启动主函数
asmlinkage __visible void __init start_kernel(void) {
char *command_line;
char *after_dashes;
// 1. 早期初始化
set_task_stack_end_magic(&init_task);
smp_setup_processor_id();
debug_objects_early_init();
// 2. 陷阱和中断初始化
boot_cpu_init();
page_address_init();
pr_notice("%s", linux_banner);
setup_arch(&command_line);
// 3. 内存初始化
mm_init_cpumask(&init_mm);
setup_command_line(command_line);
setup_nr_cpu_ids();
setup_per_cpu_areas();
smp_prepare_boot_cpu();
// 4. 构建内存区域列表
build_all_zonelists(NULL);
page_alloc_init();
// 5. 解析命令行参数
pr_notice("Kernel command line: %s\n", boot_command_line);
parse_early_param();
after_dashes = parse_args("Booting kernel",
static_command_line, __start___param,
__stop___param - __start___param,
-1, -1, NULL, &unknown_bootoption);
// 6. 初始化跳转标签
jump_label_init();
// 7. 设置控制台
console_init();
// 8. 锁定验证
lockdep_init();
// 9. 内存管理初始化
mem_encrypt_init();
setup_per_cpu_pageset();
numa_policy_init();
if (late_time_init)
late_time_init();
// 10. 调度器初始化
sched_init();
// 11. RCU初始化
rcu_init();
// 12. 跟踪和性能监控
trace_init();
// 13. 上下文跟踪
context_tracking_init();
// 14. 随机数生成器
random_init(command_line);
// 15. 定时器初始化
time_init();
timekeeping_init();
// 16. 性能事件
perf_event_init();
// 17. 分析
profile_init();
call_function_init();
WARN(!irqs_disabled(),
"Interrupts were enabled *very* early, fixing it\n");
local_irq_disable();
// 18. 中断初始化
early_boot_irqs_disabled = false;
local_irq_enable();
// 19. 控制台初始化完成
console_init();
// 20. 延迟初始化
if (panic_later)
panic("Too many boot %s vars at `%s'", panic_later,
panic_param);
// 21. 虚拟文件系统缓存
vfs_caches_init_early();
// 22. 排序异常表
sort_main_extable();
// 23. 陷阱初始化
trap_init();
mm_init();
// 24. 调度器时钟初始化
sched_init_smp();
// 25. 初始化工作队列
workqueue_init_early();
// 26. RCU调度初始化
rcu_init_sched();
// 27. 跟踪调度器
trace_sched_switch_init();
// 28. 软中断初始化
softirq_init();
timekeeping_init();
time_init();
// 29. 性能计数器
perf_trace_init();
profile_init();
// 30. 控制台初始化完成
console_init();
// 31. 延迟初始化
if (panic_later)
panic("Too many boot %s vars at `%s'", panic_later,
panic_param);
// 32. 虚拟文件系统缓存
vfs_caches_init();
// 33. 缓冲区缓存初始化
buffer_init();
// 34. 密钥管理
key_init();
security_init();
dbg_late_init();
vfs_caches_init();
signals_init();
// 35. 页缓存初始化
pagecache_init();
// 36. 信号初始化
signals_init();
// 37. 进程初始化
proc_root_init();
nsfs_init();
// 38. 控制组初始化
cgroup_init();
// 39. 延迟ACPI初始化
acpi_early_init();
// 40. 文件系统初始化
sched_init_smp();
// 41. 创建init进程
rest_init();
}
六、内核设计模式
1. 分层架构模式
- 硬件抽象层:屏蔽硬件差异
- 核心服务层:提供基本服务
- 系统接口层:向用户空间提供接口
2. 模块化设计模式
- 编译时模块化:通过条件编译选择功能
- 运行时模块化:通过内核模块动态加载
3. 面向对象设计模式
- 封装:通过结构体和函数指针实现
- 继承:通过结构体嵌入实现
- 多态:通过函数指针表实现
4. 发布-订阅模式
- 通知链:用于内核事件通知
- 观察者模式:用于文件系统变化通知
七、总结
Linux内核架构体现了宏内核的优化和模块化设计的完美结合:
- 进程管理:多调度器策略,支持实时和公平调度
- 内存管理:复杂的伙伴系统和slab分配器,优化内存使用
- 文件系统:统一的VFS抽象,支持多种文件系统
- 网络栈:完整的TCP/IP实现,支持各种网络协议
- 设备驱动:统一的设备模型,支持热插拔
- 安全机制:多种安全模块,支持强制访问控制
- 模块化:支持运行时模块加载,提高灵活性
Linux内核的持续演进展示了开源协作的威力,其架构设计已成为操作系统设计的典范。