本节摘要:操作系统是特权架构的第一个真正客户——它用机器模式固件初始化裸机、在监督模式搭起进程世界、靠时钟中断获得心跳、用页表机制实现虚拟内存。本节沿"按下电源到第一个用户进程"的主线走完启动链条,再看上下文切换与时钟中断的硬件依赖,最后盘点运行时环境里那些不起眼却不可缺的部件。
你按下开发板的电源键。看似一瞬间的"开机",对处理器来说是一段漫长的接力:复位释放,程序计数器指向固化在芯片里的入口,机器模式从这里出发——此时没有内存初始化、没有外设配置、没有时钟校准,世界一片蛮荒。固件(可能是引导固件,也可能是安全监视器这类监管程序)在机器模式里干最脏的活:初始化内存控制器、枚举与配置外设、装配设备树(描述硬件拓扑的数据结构,交给后续软件的"机器说明书")、设置物理内存保护,然后按设计把机器模式的部分职责委托给监督模式,跳进操作系统的内核入口。内核继续接力:建立页表与虚拟内存、初始化调度器与中断控制器、挂载根文件系统,最后创建第一个用户进程。从此,机器模式退居幕后处理最底层的陷入与中断,监督模式维持秩序,用户进程们在笼子里各自奔跑。
这条链条上每一棒的交接都调用第五章的机制:委托是控制状态寄存器的配置、跳转靠档案袋、系统调用是环境调用指令触发的受控陷入。特权架构的三章内容,在这条启动链上全部得到验收——这也是为什么内核移植是检验一颗核"系统级成熟度"的试金石。
操作系统的时间感来自时钟中断:机器定时器按设定时刻触发中断,内核借机收回控制权,决定下一个上处理器的进程。没有这记心跳,一个死循环的用户进程就能永久霸占机器——时钟中断因此是操作系统权威的物理保障。
上下文切换是心跳驱动的常规手术,流程值得背熟:定时器中断到来,硬件自动记账并跳入内核入口(5.2 的旅程);内核先保存被中断进程的完整现场——通用寄存器入栈、程序计数器与状态已在档案袋里;从调度队列选出下一个进程;恢复它的现场;执行返回指令切回用户态。整套手术的开销由第五章的中断延迟加软件现场搬运构成,调度器的设计目标之一就是把手术做得又快又稳——现代内核还会按需保存(只存这次真用到的浮点寄存器)来瘦身。
页表管理是内核对第四章机制的日常调用:进程创建时分配页表框架、缺页异常时按需填入映射、进程退出时回收。缺页处理是"异常也能是好事"的最佳例证——它不是错误,而是内核与硬件合演的按需装载协议:访存触发缺页异常,内核从后备存储调入页面、更新页表、返回重试,那条"失败"的指令重新执行并成功。虚拟内存的灵活性(换页、共享、写时复制)全部建立在这套异常协议之上。
裸跑在操作系统之上的程序,脚下还垫着一层"运行时":入口代码清零全局区、拷贝初始化数据、设好栈指针才跳进主函数;标准库提供系统调用的封装与缓冲;链接脚本(描述程序各段落在内存哪里的规则文件)定义了地址布局。嵌入式开发者对这层地板感知最强——交叉编译时一个链接脚本的段地址错误,程序就会在完全不着边际的地方崩溃。理解运行时的意义在于把"程序"从一个抽象名词还原成一堆具体部件的组装体:指令、数据、栈、库、内核服务,各就各位。
主线内核对 RISC-V 的支持已经相当成熟:虚拟内存方案、原子操作、对称多处理启动、性能计数器接口都已进入通用代码路径。对核设计师而言,这份数据点值得记下——你的核要跑主线内核,特权架构实现必须经得起这份最挑剔的验收;反过来,能顺畅跑起主流发行版的核,其系统级成熟度就有了公认背书。
单核的启动链已经讲完;多一颗核,故事多一截。规范的做法是"主核唤醒从核":主核(通常是零号)先完成全部初始化,然后按核间软件中断或自定义的唤醒机制,把从核从等待地址处拉起——从核各自完成自己的最小初始化(页表已在,大部分配置共享),登记进调度队列开始接活。这里有两个设计要点:其一,硬件资源描述必须让每个核都读得到(设备树通常放在共享内存,各核各自解析);其二,从核的入口约定与栈空间要预先分配好——从核被拉起时世界已经运转,它没有"从头初始化一切"的权利。多核启动是固件面试与内核移植 bug 的双料高发区,机制理清后再看代码会顺畅得多。
核间通信的原语也顺手梳理:核间中断(一个核给另一个核发"软中断",内核调度器跨核唤醒任务就用它)、共享内存加原子操作(数据面的主力,配合 4.5 的获取释放语义保证顺序)、以及构成完整工具箱。注意一致性子系统的前提——没有 4.4 那套协议兜底,这些原语在多份缓存副本面前全都不可靠。多核软件栈的每一层,都站在本册第四章的地基上。
问:机器模式固件可以一直留着吗,还是尽早退出? 看产品形态。需要安全监视器(虚拟化、安全分区)的产品,机器模式的监管程序常驻运行,监督模式之下的世界都归它管;普通产品启动完成后固件退出舞台,机器模式只在极少数未委托事件时短暂出场。常驻监管换来隔离能力,退出换来简单——又是一次定位驱动的取舍。
问:为什么我的内核起不来,卡在第一条页表切换之后? 经典三嫌疑:页表位数与固件设置的翻译模式不一致(翻译走了错误级数)、页表项的权限位与内核预期的访问类型不符(取指被拒)、地址翻译缓冲没被正确冲刷(旧映射残留)。对照 4.1 的翻译路径逐段排查,通常半小时内能定位。
⚠️ 常见坑:内核移植卡死在启动早期,九成出在三处——设备树与实际硬件不符(内核按错误的说明书配置机器)、固件委托配置不完整(某类陷入没人接)、页表位数与固件设置的翻译模式不一致。排查顺序按这三处走,比盲目单步跟踪快得多。
软件的世界搭好了,最后一节解决"看不见就改不了"的问题——仿真、调试与性能观测工具箱。