Lec 09 进程
Lec 09 process
本内容版权归上海交通大学并行与分布式系统研究所所有
使用者可以将全部或部分本内容免费用于非商业用途
使用者在使用全部或部分本内容时请注明来源
资料来自上海交通大学并行与分布式系统研究所+材料名字
对于不遵守此声明或者其他违法使用本内容者,将依法保留追究权
本内容的发布采用 Creative Commons Attribution 4.0 License
完整文本
回顾
分时复用有限的CPU资源
- 分时复用CPU
- 让多个应用程序轮流使用处理器核心
- 何时切换:操作系统决定
- 运行时间片(例如100ms)
- 时间片:每个程序每次最长连续运行时间。
- 高频切换:看起来是多个应用“同时”执行
应用程序和进程
- 通常一个应用程序对应一个进程
- 在shell中输入可执行文件的名称
- shell创建新进程,新进程执行可执行文件
- 在图形界面双击应用图标
- 在shell中输入可执行文件的名称
- 多进程程序:应用程序可以自己创建新进程
- 创建新进程,在新进程只能够运行其他应用程序或者运行与自己一样的程序。
进程状态数据
- 操作系统提供给进程的抽象用于管理应用程序
- 进程标识号,(process ID,PID)
- 运行状态
- 处理器上下文
- 地址空间
- 打开文件
处理器上下文
- 操作系统为每个进程维护处理器上下文
- 包含回复进程执行需要的状态
- 进程A执行到main函数任意一条指令的时候,切换到进程B执行,一段时间后再一次切换回进程A执行。
- 需要保存以下状态:PC寄存器值,栈寄存器值,通用寄存器值,状态寄存器值。
1 进程的表示:PCB
进程:运行中的程序
-
进程是计算机程序运行时的抽象
- 静态部分:程序运行需要的代码和数据
- 动态部分:程序运行期间的状态(程序计数器,栈,堆)
-
进程具有独立的虚拟地址空间
- 每个进程都具有“独占全部内存”的假象
- 内核中同样包含内核栈,内核代码,数据。
如何表示进程:进程控制块
-
每个进程都对应一个元数据,称为进程控制块PCB。
- 进程控制块存储在内核态,因为它由内核管理,不应被用户态的程序访问
独立的虚拟地址空间是进程的标志性特征
独立的执行上下文表明进程具有独立的执行能力。
- 进程控制块存储在内核态,因为它由内核管理,不应被用户态的程序访问
-
进程控制块内应该保存:
- 对立的虚拟地址空间
- 独立的处理器上下文
- 内核栈
内核栈和用户栈
-
应用需要内核栈
- 进程在内核中依然需要执行代码,有读写临时数据的需求。
- 进程在用户态和内核态的数据应该相互隔离,增强安全性。
-
AArch64实现:两个栈指针寄存器
- SP_EL1, SP_EL0
- 进程进入内核后,自动完成栈寄存器切换。
- x86直邮一个栈寄存器,需要保存恢复。
2 进程的创建
如何实现进程的创建?
- 进程包含:
- 用户视角:代码,数据,堆栈
- 内核视角:PCB,虚拟地址空间,上下文
- 创建进程就是创建和初始化以上内容的过程
进程创建1:PCB相关初始化
- PCB及其包含的内容都需要创建以及初始化。
- PCB本身数据结构的分配
- 初始化PCB:虚拟内存
- 创建和初始化vmspace数据结构
- 分配一个物理页作为顶级页表
- 内核栈:分配物理页,作为进程内核栈
- 处理器上下文在应用运行前才进行初始化。
进程创建2:可执行文件的加载
- 可执行文件具有固定的存储格式
- 以ELF(Executable and Linkable Format)为例:
- 程序头部表可以获取需要的段所在的位置
- 通常只有代码段和数据端需要被加载(loadable)
- 加载即从ELF文件中映射到虚拟地址空间的过程
进程创建3:准备运行环境
- 在返回用户态之前,还需要为进程准备运行所需要的环境
- 分配用户栈(分配物理内存,映射到虚拟地址空间)
- 准备程序运行时的环境
- main函数:
int main(int argc, char *argv[], char *envp[])
- main函数:
进程创建4:处理器上下文初始化
- 为什么直到最后才初始化处理器上下文?
- 其包含的内容直到前序操作完成才确定。
- SP:用户栈分配后才确定地址
- PC(保存在ELR_EL1):加载ELF后才了解到入口地址。
- 大部分的寄存器初始值可以直接赋予0
- 其包含的内容直到前序操作完成才确定。
3 进程退出,等待
Version 1: 销毁PCB及其所有内容
- 销毁PCB以及内部所有内容。
- 告知内核选择其他进程执行。
- 假设内核使用进程列表维护所有进程
- 仍然调用schedule,让其他进程执行,自己在while循环中等待。
缺陷:
- 信息太少,ls进程退出时的返回值,shell进程无法获取。
改进-1: 为进程添加退出状态支持
- 分别修改PCB和process_exit的实现。
改进-2: 修改process_waitpid
- 如果进程已经设置为退出,则记录其退出状态并回收。
- 进程资源的回收操作从exit移到了waitpid。
改进-3: 安全性,限制进程等待的范围
- 目标:只有创建进程的程序才能监控进程
- 实现:引入父(创建者)子(被创建者)进程概念
- 进程之间的创建关系构建了进程树
- 第一个进程(树根)通常由内核主动创建。
关于process_waitpid的疑问
- 编程时,我们并没有强制创建者调用waitpid
- 如果shell不调用waitpid,会出现什么情况呢
- ls进程退出,但是没有销毁,称为zombie(僵尸)进程
- 解决方案:init进程代为管理并回收资源。
4 进程的状态
进程的睡眠需求
- 等待其他事件:进入进程睡眠。轮询方式查看时间,没有到达规定的时间则继续等待。
进程的五种典型执行状态
- 新生(new): 刚刚调用process_create
- 就绪(ready): 随时准备执行(但是暂时没有执行)
- 运行(running): 正在执行
- 僵尸(zombie): 退出但未回收
- 终止(terminated): 退出且被回收
调度
- 目的:选出下一个可以执行 的进程
- 可以执行=就绪(ready)
5 案例分析:Linux进程创建
fork()
-
语义:为调用进程创建一个一模一样的新进程
- 调用进程为父进程,新进程为子进程
- 接口简单,无需任何参数
-
fork后的两个进程均为独立进程
- 拥有不同的进程id
- 可以并行执行,互不干扰(除非使用特定的接口)
- 父进程和子进程会共享部分数据结构(内存、文件等)
-
通过返回值来判断父进程/子进程。0(子进程)非0(父进程)
-
父子进程执行的顺序由调度策略决定。
-
将父进程的PCB拷贝一份,实现比较简单
优缺点分析
-
优点:
- 接口简介,(过去)实现简单
- 创建进程和执行进程解耦,提高了灵活度。
-
缺点:
- 创建拷贝的复杂度和PCB复杂度相关。
- 完全拷贝过于粗暴(不如clone)
- 性能差,可扩展性差。(不如vfork和spawn)
- 不可组合性。(例如:fork()+pthread())
fork的替代接口
-
vfork:类似于fork,但是父子进程共享同一个地址空间
-
优点:映射无需拷贝,性能更好
-
缺点:
- 只能用在fork+exec场景中
- 共享地址空间存在安全问题
- 写时拷贝提供了vfork的优点给fork。
-
posix_spawn:相当于fork+exec
-
优点:可扩展性,性能较好
-
缺点:不如fork灵活。
-
clone:fork进阶版,可以选择性不拷贝内存
- 优点:高度可控,可以按照需求调整
- 缺点:接口复杂,选择性拷贝容易出错。
6 ChCore微内核进程管理
PCB解耦设计
- 内核态:Cap_group(能立组)
- 将资源(进程,内核栈,虚拟地址空间)均抽象成为对象
- 访问对象的凭证成为能力,而进程时分配和管理资源的基本单位。
- 用户态:proc
- 除内核中的资源(如vmspace)均移动到用户态管理
ChCore进程创建
- 逻辑和process_state相似,但使用微内核风格,很多功能都在用户态完成。
7 Chcore 进程切换
五个步骤
- 进出内核的五个步骤
- 进程1进入内核态
- 进程1处理器上下文保存
- 进程上下文切换
- 进程2处理器上下文恢复
- 进程2返回用户态
处理器上下文和进程上下文
- 处理器上下文:用于保存切换时的寄存器状态(硬件),每个PCB中均有保存。
- 进程上下文:表示目前操作系统正在以哪个进程的身份运行(软件),通常使用一个指向PCB的全局指针表示。
切换节点位于所有调用schedule的地方。告知内核选择下一个执行的进程,涉及到进程的切换。
进程切换全过程
1. p0进入内核态
硬件完成部分寄存器保存,PC和PSTATE分别保存到ELR_EL1和SPSR_EL1
2. 上下文保存
将处理器中的寄存器值保存到处理器上下文对应的位置
3. 切换
- 虚拟地址空间切换
- 设置页表相关的寄存器(TTBR0_EL1)
- 使用PCB中保存的页表基地址赋值给TTBR0_EL1
- 内核栈切换
- 设置内核中的栈寄存器SP_EL1
- 使用PCB中保存的内核栈顶地址赋值给SP_EL1
- 进程上下文切换
- 设置cur_proc为之后要执行的进程(p1)
- 表明操作系统将以p1的身份运行。
4. p1处理器上下文恢复
- 从处理器上下文中加载各个寄存器的值,放入对应的寄存器中。
- 硬件自动恢复部分寄存器,将ELR_EL1和SPSR_EL1中的值自动保存到PC和PSTATE中。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库