
【免费下载链接】x16-PRosSimple 16 bit (real mode) operating system writen in NASM from scratch项目地址https://gitcode.com/gh_mirrors/x1/x16-PRos点击查看免费下载x16-PRos 是一个从零用 NASM 编写的 16 位实模式操作系统它的内核里藏着一个非常精巧的合作式多任务调度器仅用 8 个任务槽、16 字节的槽结构就实现了任务的创建、上下文切换、睡眠/唤醒与协程让出。这篇文章带你读懂这套调度器的核心源码看看一个极简的多任务是如何在 x86 实模式下跑起来的。一、为什么是合作式多任务现代操作系统靠硬件中断抢占CPU而 x16-PRos 的调度器 src/kernel/features/sched.asm 走的是另一条路任务自愿让出 CPU。任务主动调用INT 0x23 AH0x13让出执行权协程让出任务调用AH0x14睡眠若干 BIOS 时钟滴答约 55 ms/滴答任务等待键盘时AH0x16内核也会替它自动让出。没有抢占意味着代码极其简单——整个调度器不到 700 行汇编代价是一个死循环且从不让出的任务会饿死所有其他任务这对新手理解协作的代价是一堂绝佳的课。二、8 个任务槽调度器的最小单元调度器的心脏是一张固定大小的任务表定义在 sched.asm 的数据段TASK_SLOT_COUNT equ 8 ; 共 8 个任务槽 TASK_SLOT_SIZE equ 16 ; 每个槽 16 字节槽位用途0永远保留给内核KERNEL标记为TASK_F_KERNEL不可被杀死、永不释放1 ~ 7供前台/后台任务使用由BG命令或程序间调用分配每个槽的 16 字节结构紧凑得令人惊讶偏移见 sched.asm 头部注释TASK_STATE1 字节free / ready / running / sleeping / waiting 五态TASK_FLAGS1 字节bit0后台任务bit7内核任务TASK_SS/TASK_SP4 字节任务自己的栈段和栈顶——上下文切换的精髓TASK_WAKE_LO/HI4 字节睡眠任务的唤醒时刻来自 32 位 BIOS 滴答计数器TASK_PARENT1 字节前台任务的父任务用于子任务退出后唤醒父任务三、上下文切换30 字节的协程魔法实模式下没有页表切换任务的本质就是换栈。看 sched_yield 的核心套路把当前任务的SS、SP存回任务槽状态置为ready调用sched_pick_next按轮转顺序round-robin找到下一个就绪任务cli关中断从目标槽恢复SS/SPsti开中断popa恢复寄存器iret从压入的返回地址处跳回目标任务。由于切换路径上压过一整套pusha寄存器组所有 CPU 寄存器都被完整保存——任务下次被调度时寄存器、栈、程序流原样恢复。这就是协程让出的全部秘密没有保存区域拷贝、没有页表切换只有换栈。任务退出时走 ple_task_done 着陆点程序retf落到这里它压好返回帧后跳入sched_exit由后者释放任务内存mem_free、把槽位标记为 free再切换到下一个就绪任务若没有其他任务则回落到内核槽。创建任务时sched_task_create_from_ple 会在任务自己的栈段里伪造一个30 字节的初始栈帧寄存器、FLAGS0x0202打开中断、入口CS:IP外加一个指向ple_task_done的远返回指针——任务结束时retf恰好落回内核。sched_pick_next里还藏着一个防御性检查跳过TASK_BASE_SEG0的僵尸槽避免iret跳到垃圾地址。四、睡眠、唤醒与父任务等待睡眠sched_sleep 读取0040:006C处的 32 位滴答计数器加上CX个滴答得到唤醒时刻存入任务槽。内核槽0 号调用睡眠会自动退化为普通让出内核永远不会阻塞自己。唤醒sched_wake_sleepers 在每次选任务时扫描全部槽位到期者从sleeping翻转为ready。由于用的是 32 位计数器比较跨越午夜也不会出错。父任务等待前台启动程序时sched_dispatch 会把父任务置为waiting子任务退出sched_exit时若父任务还在waiting则把它唤醒为ready——这就是程序跑完自动回到终端的机制。五、动手体验BG、PS 与 KILL系统 APIINT 0x23在 src/kernel/features/api/api_sys.asm 中统一分发与任务调度直接相关的函数码函数码功能0x10/0x11前台 / 后台执行 PLE 程序返回任务 ID0x12终止当前任务不返回0x13协程让出0x14睡眠 N 个滴答0x15获取当前任务 ID0x16读键等待期间自动让出0x17/0x19查询任务槽 / 读取任务名0x18按 ID 杀死任务在终端里输入BG CLOCK.PLE即可体验内核的 bg_command 调用ple_execute_bg创建后台任务后立即返回打印 Background task started: id N而后台任务在之后的每次让出中轮流执行。随后你可以用两个工具观察和管控任务表PS.BINprograms/ps.asm列出每个槽的任务名、ID 与内存基地址KILL idprograms/kill.asm调用AH0x18终止指定任务内核会拒绝杀死 0 号内核槽、当前任务或空闲槽。六、小结与延伸阅读x16-PRos 的调度器用 8 个槽、16 字节/槽、一次换栈就搭起了完整的多任务框架是学习协程调度、上下文切换原理的绝佳范本。建议按以下路径继续深挖调度器源码src/kernel/features/sched.asm系统 API 完整文档docs/API.mdINT 0x23 - System API 一节PLE 加载与着陆逻辑src/kernel/features/ple/ple.asm版本记录中多任务的介绍docs/changes/v1.0.txt内核整体架构ASCII 分层图src/kernel/README.TXT读懂这份不到 700 行的调度器你会对多任务三个字产生一种全新的敬畏与亲切感。赞分享【免费下载链接】x16-PRosSimple 16 bit (real mode) operating system writen in NASM from scratch项目地址https://gitcode.com/gh_mirrors/x1/x16-PRos点击查看免费下载相关推荐TobudOS调度器源码深度剖析PendSV汇编如何实现微秒级任务上下文切换TobudOS调度器源码深度剖析PendSV汇编如何实现微秒级任务上下文切换 TobudOS 是开放原子开源基金会孵化、面向物联网终端的轻量级实时操作系统RHermes 中的 boost.context基于 fiber 的协作式多任务上下文切换原理与集成实践Hermes 中的 boost.context基于 fiber 的协作式多任务上下文切换原理与集成实践 导读 boost.context 是一个为 C 提语言运行时编译器解释器JIT编译内存管理移动开发QtScrcpy 实战指南3 分钟连上手机免 Root 安卓投屏与键鼠控制全解QtScrcpy 实战指南3 分钟连上手机免 Root 安卓投屏与键鼠控制全解 手机屏太小投屏方案又太重 6 英寸屏幕上盯代码、看日志眼睛遭罪自研桌面应用音视频上一篇百万级虚拟消费者社会Oransim的IPF群体生成与Soul LLM人格智能体完全教程下一篇官方文档教不了你的224个坑kotlin-footguns生产事故战报清单创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考