Linux内核是模块化、分层设计的典范。每个模块负责一类核心功能,彼此协作,构成了强大的操作系统内核。本文将:
下面我们以进程管理、内存管理、文件系统、设备驱动、网络协议栈、系统调用接口为重点,进行原理与代码解析。
核心原理:
task_struct
保存所有进程信息。关键结构体(include/linux/sched.h
):
struct task_struct {
volatile long state; // 进程状态(运行、睡眠等)
void *stack; // 内核栈指针
struct mm_struct *mm; // 进程内存描述符
pid_t pid; // 进程ID
struct list_head tasks; // 链表:所有进程
// ... 还有很多成员
};
进程创建流程(kernel/fork.c
):
// fork()系统调用最终调用do_fork()
long do_fork(unsigned long clone_flags, unsigned long stack_start,
unsigned long stack_size, int __user *parent_tidptr,
int __user *child_tidptr, unsigned long tls)
{
struct task_struct *p;
// 1. 分配task_struct
p = copy_process(clone_flags, stack_start, stack_size,
parent_tidptr, child_tidptr, tls);
// 2. 将新进程加入进程链表
if (likely(p))
wake_up_new_task(p);
// 3. 返回子进程PID
return p ? p->pid : error_code;
}
注释说明:
copy_process()
复制父进程的描述符、内存映射等,创建新的进程。wake_up_new_task()
将新进程加入调度队列。核心原理:
关键结构体(include/linux/mm_types.h
):
struct mm_struct {
struct vm_area_struct *mmap; // 虚拟内存区域链表
unsigned long start_code, end_code; // 代码段
unsigned long start_stack; // 栈
pgd_t *pgd; // 页全局目录
// ...
};
内存分配流程(伙伴系统,mm/page_alloc.c
):
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
{
// 1. 查找合适的空闲内存块
struct page *page = __alloc_pages(gfp_mask, order, ...);
// 2. 如果没有合适块,尝试回收/交换
// 3. 返回分配的page结构
return page;
}
注释说明:
核心原理:
struct file
描述。file_operations
提供统一操作接口。关键结构体(include/linux/fs.h
):
struct file_operations {
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
// ... 还有很多
};
文件读取流程(fs/read_write.c
):
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
// 1. 检查权限、锁定文件
// 2. 调用具体文件系统的read实现
if (file->f_op->read)
return file->f_op->read(file, buf, count, pos);
// 3. 错误处理
}
注释说明:
核心原理:
字符设备注册流程(drivers/char/
):
static struct file_operations my_fops = {
.read = my_read,
.write = my_write,
// ...
};
static int __init my_init(void)
{
int major = register_chrdev(0, "mydev", &my_fops);
// major为主设备号,动态分配
return 0;
}
注释说明:
register_chrdev
向内核注册一个字符设备。my_fops
结构体的函数实现。核心原理:
socket数据收发流程(net/socket.c
):
SYSCALL_DEFINE3(sendto, int, fd, void __user *, buf, size_t, len)
{
struct socket *sock = sockfd_lookup(fd, &err);
// 1. 检查参数、查找socket
// 2. 调用对应协议族的发送函数
return sock->ops->sendmsg(sock, &msg, len);
}
注释说明:
sendmsg
由协议栈不同层实现(如TCP、UDP等)。核心原理:
系统调用表(arch/x86/entry/syscalls/syscall_64.tbl
):
0 common read sys_read
1 common write sys_write
2 common open sys_open
...
系统调用入口示例(arch/x86/entry/common.c
):
asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count)
{
return ksys_read(fd, buf, count);
}
注释说明:
asmlinkage
保证参数从内存栈读取。ksys_read
为真正实现,最终调用VFS和驱动。Linux内核模块结构清晰、分工明确。各模块通过抽象和接口协作,实现了高效、稳定、可扩展的操作系统。理解其模块划分、核心原理和关键代码实现,是深入Linux内核开发与调优的基础。
如需对某个模块做更细致的行级源码讲解(如进程调度、内存管理、网络协议等),欢迎进一步提问!