尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Linux 0.11 源码解读:从 5 个关键函数看进程创建与切换的实现
Linux 0.11 源码解读从 5 个关键函数看进程创建与切换的实现在操作系统的核心机制中进程管理无疑是最为精妙的设计之一。当我们翻开 Linux 0.11 的源码这个发布于1991年的经典版本就像打开了一本关于计算机科学的活教材。今天我们将深入五个关键函数——fork()、copy_process、schedule、switch_to和sys_pause通过代码级的分析揭示进程创建与切换的实现奥秘。1. fork()用户视角的进程创建入口fork()是 Unix/Linux 系统中最著名的系统调用之一它创造了分身术般的编程体验。在用户空间我们看到的只是一个简单的函数调用pid_t pid fork(); if (pid 0) { // 子进程代码 } else { // 父进程代码 }但在内核层面这个简单的调用背后隐藏着复杂的机制。Linux 0.11 中fork()的实现始于sys_fork函数在kernel/system_call.s中_sys_fork: call _find_empty_process testl %eax,%eax js 1f push %gs pushl %esi pushl %edi pushl %ebp pushl %eax call _copy_process addl $20,%esp 1: ret这段汇编代码揭示了fork()的核心流程调用find_empty_process寻找空闲的进程槽检查返回值进程号是否有效保存关键寄存器状态调用copy_process完成实际的进程复制清理栈空间并返回提示Linux 0.11 中进程控制块PCB使用固定大小的数组NR_TASKS默认为64而非现代Linux中的动态分配方式。2. copy_process进程复制的核心实现copy_process函数位于kernel/fork.c是进程创建的核心它完成了以下关键操作int copy_process(int nr, long ebp, long edi, long esi, long gs, long none, long ebx, long ecx, long edx, long fs, long es, long ds, long eip, long cs, long eflags, long esp, long ss) { struct task_struct *p; // 分配任务结构体内存 p (struct task_struct *) get_free_page(); // 复制父进程任务结构 *p *current; // 设置子进程特定属性 p-state TASK_UNINTERRUPTIBLE; p-pid last_pid; p-counter p-priority; // 复制页表 copy_mem(nr, p); // 设置内核栈 set_tss_desc(nr, (p-tss)); set_ldt_desc(nr, (p-ldt)); // 修改子进程返回值为0区分父子进程 p-tss.eax 0; // 设置就绪状态 p-state TASK_RUNNING; return last_pid; }这个函数中几个关键点值得注意内存分配使用get_free_page获取一页内存4KB作为子进程的 task_struct结构复制直接通过*p *current复制父进程的整个任务结构返回值处理通过修改子进程的tss.eax实现父子进程返回不同值内存管理copy_mem负责复制页表实现写时复制COW机制注意Linux 0.11 还没有实现现代Linux中的写时复制优化这里的页表复制是立即完成的。3. schedule进程调度的决策中心进程切换的核心是调度器Linux 0.11 的schedule函数位于kernel/sched.c实现了一个简单但高效的时间片轮转调度算法void schedule(void) { int i, next, c; struct task_struct ** p; // 遍历所有任务寻找就绪任务中counter最大的 while (1) { c -1; next 0; for (p LAST_TASK; p FIRST_TASK; --p) { if (!*p || (*p)-state ! TASK_RUNNING) continue; if ((*p)-counter c) { c (*p)-counter; next i; } } // 找到可运行任务则跳出循环 if (c) break; // 所有任务时间片用完重新分配时间片 for (p LAST_TASK; p FIRST_TASK; --p) if (*p) (*p)-counter ((*p)-counter 1) (*p)-priority; } // 切换到选中的任务 switch_to(next); }调度算法的核心逻辑可以总结为遍历任务数组寻找counter值最大的就绪任务如果所有就绪任务的counter都为0则重新计算时间片新时间片 原时间片/2 priority调用switch_to执行任务切换这种设计实现了优先级调度高优先级任务获得更多CPU时间时间片轮转保证公平性防止任务饥饿动态调整长时间运行的任务优先级会逐渐降低4. switch_to上下文切换的底层实现实际的进程上下文切换发生在switch_to宏中定义于include/linux/sched.h#define switch_to(n) {\ struct {long a,b;} __tmp; \ __asm__(cmpl %%ecx,_current\n\t \ je 1f\n\t \ xchgl %%ecx,_current\n\t \ movw %%dx,%1\n\t \ ljmp %0\n\t \ cmpl %%ecx,_last_task_used_math\n\t \ jne 1f\n\t \ clts\n \ 1: \ ::m (*__tmp.a),m (*__tmp.b), \ d (_TSS(n)),c ((long) task[n])); \ }这段内联汇编完成了以下关键操作检查目标进程是否是当前进程如果是则无需切换更新current指针指向新进程使用ljmp指令跳转到新进程的TSS描述符处理浮点运算状态如果上一个使用协处理器的是目标进程上下文切换的核心是CPU状态的保存与恢复这包括通用寄存器通过任务状态段TSS自动保存/恢复段寄存器包括CS、DS等程序计数器EIP栈指针ESP提示现代Linux已不再使用硬件任务切换TSS而是采用软件上下文切换以提升性能。5. sys_pause主动让出CPU的系统调用sys_pause是进程主动让出CPU的系统调用实现int sys_pause(void) { current-state TASK_INTERRUPTIBLE; schedule(); return 0; }这个简单函数展示了Linux调度的一个重要特性——协作式调度。进程可以通过将自己状态设置为非运行状态这里是可中断等待并调用调度器来主动放弃CPU。这种机制被用于等待信号signal实现sleep类函数等待资源可用进程状态转换的全景图结合这五个关键函数我们可以描绘出Linux 0.11中进程状态转换的全景新建 (fork) → 就绪 (TASK_RUNNING) ↑ ↓ | 被调度选中 (schedule) | ↓ | 运行中 (switch_to) | ↓ | 主动放弃CPU (sys_pause) | ↓ └─── 等待 (TASK_INTERRUPTIBLE/UNINTERRUPTIBLE)这个简单的状态机模型支撑起了整个Linux的进程管理机制。与现代Linux相比0.11版本缺少实时进程支持多核调度CFS完全公平调度器更丰富的进程状态如停止状态但正是这种简洁性使得Linux 0.11成为学习操作系统原理的绝佳教材。通过这五个函数的分析我们不仅理解了进程创建与切换的机制也看到了操作系统设计中的一些基本思想资源复用通过fork实现进程复制时间片轮转公平分配CPU时间优先级调度重要任务获得更多资源状态隔离通过上下文切换实现进程保护在实际项目开发中理解这些底层机制有助于我们更合理地设计多进程/多线程应用优化进程创建开销如使用进程池理解各种调度策略的影响调试复杂的并发问题
RELATED

相关推荐

Few-shot 示例的动态选择:根据 query 语义自动匹配最相关的 prompt 示例

Few-shot 示例的动态选择:根据 query 语义自动匹配最相关的 prompt 示例

Few-shot 示例的动态选择:根据 query 语义自动匹配最相关的 prompt 示例 一、深度引言与场景痛点 大家好,我是赵咕咕。 你给模型写了一个 Few-shot prompt,里面放了3个示例——一个关于代码审查、一个关于文档生成、一个关于数据分析。结果用…

📅 2026/9/12 2:40:07
Alfred vs Raycast 深度对比:2024年Mac效率工具选型指南

Alfred vs Raycast 深度对比:2024年Mac效率工具选型指南

Alfred vs Raycast 深度对比:2024年Mac效率工具选型指南在追求极致效率的Mac用户群体中,两大生产力工具Alfred和Raycast的争论从未停歇。本文将从实际使用场景出发,通过详尽的量化测试和功能拆解,帮助开发者和效率爱好者做出明智选…

📅 2026/8/8 10:08:15
154、VFL 不对称焦点损失的 YOLOv11 代码:对正负样本采用不同降权策略的 IoU-Aware 设计

154、VFL 不对称焦点损失的 YOLOv11 代码:对正负样本采用不同降权策略的 IoU-Aware 设计

154、VFL 不对称焦点损失的 YOLOv11 代码:对正负样本采用不同降权策略的 IoU-Aware 设计 从一次诡异的mAP抖动说起 去年年底帮一个自动驾驶项目调YOLOv11的检测头,客户反馈说夜间场景下小目标召回率突然掉了8个点。我翻了两天日志,发现罪魁祸首是正负样本的loss权重分配—…

📅 2026/7/12 1:00:53
MORE NEWS

更多资讯

📰

CORE API 接入指南:用 scientific-agent-skills 的 paper-lookup 技能解锁开放获取全文检索

CORE API 接入指南:用 scientific-agent-skills 的 paper-lookup 技能解锁开放获取全文检索 【免费下载链接】scientific-agent-skills Turn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. …

📰

Label Studio Interface 详情页完全指南:预览、版本管理与项目关联

Label Studio Interface 详情页完全指南:预览、版本管理与项目关联 【免费下载链接】label-studio Label Studio is a multi-type data labeling and annotation tool with standardized output format 项目地址: https://gitcode.com/GitHub_Trending/la/label-s…

📰

STM32 SPI驱动AD7172:从Flash例程迁移到24位ADC的完整实践

简介:ALIENTEK MINISTM32 实验20 SPI实验配套资料包,聚焦STM32通过SPI总线驱动AD7172双通道16位ADC的完整实现,属于嵌入式驱动开发与工业采集类应用的基础实战资源,适合需要学习STM32外设通信与驱动代码编写的工程师。资料包共168…

📰

小米的问题从来不在舆情:产品、品牌、组织与用户的底层逻辑解析

1. 先把结论摆出来:舆论场上的嘈杂,掩盖不了真问题的沉默 小米这几年给我的感觉,特别像一位各方面都挺努力的同学,成绩单也不算差,但每次考试总在几道关键大题上丢分。外界习惯性把这丢分归结为“心态不好”——也就是…

📰

OI-wiki 计算几何扫描线算法全解:矩形面积并、二维数点与 B 维正交范围

OI-wiki 计算几何扫描线算法全解:矩形面积并、二维数点与 B 维正交范围 【免费下载链接】OI-wiki :star2: Wiki of OI / ICPC for everyone. (某大型游戏线上攻略,内含炫酷算术魔法) 项目地址: https://gitcode.com/GitHub_Tren…

📰

校园奶茶店微信小程序毕业设计:从登录支付到订单管理的全流程实践

校园奶茶店这种选题,在计算机毕业设计里属于典型的“小切口、全流程”项目。小程序端要处理点单、购物车、订单状态,管理端要维护商品库存、统计销量,中间还夹着微信登录、支付回调、消息通知这类绕不开的第三方对接。很多同学做完这个项目&a…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬