第一部分 虚拟化
4.抽象:进程
抽象进程:时分共享
进程:在运行的程序
机器状态:程序在运行时可以读取和更新的内容:内存(地址空间)、寄存器(ProgramCounter,stackpointer)
也可以访问持久设备
进程API:create,destroy,wait(等待进程停止运行),miscellanous control(暂停一段时间再恢复),statu
进程创建
进程状态
数据结构
其他状态:initial,final
5.进程API
fork():子进程从fork()系统调用返回,获得的返回值是0。而父进程获得的返回值是子进程的PID。
输出顺序不确定
地址空间不共享,但复制一份fork处的地址空间
画进程创建图
wait():
等待子进程运行结束才返回 wait(NULL)
exec():
子进程调用execvp()替换代码。给定可执行程序的名称及所需参数,exec会从可执行程序中加载代码和静态数据,并用它覆写代码段和静态数据,堆栈和其他空间也会被初始化。
成功调用永远不返回
fork和exec的分离设计?
shell可以在fork之后exec之前运行代码,给新程序运行前改变环境
unix管道也是类似方式实现
kill可发送信号:睡眠、终止……
6.机制:受限直接执行
时分共享CPU来虚拟化CPU
挑战:性能,控制权
基本技巧:直接执行(快速)
问题1:操作需要受限
采用受保护的控制权转移:用户模式(不能完全访问硬件资源),内核模式 提供陷入内核,从陷阱返回到用户模式程序的说明,以及指令告诉陷阱表的位置
特权操作
执行系统调用,必须执行特殊的陷阱指令,该指令跳入内核并将级别升到内核模式
完成后,操作系统调用从陷阱返回指令,特权级别降低回到用户模式
执行陷阱时,硬件需要确保存储足够多调用者寄存器,以便正确返回程序 ->x86:寄存器会被存到每个进程的内核栈上
C过程调用其实是汇编代码调用系统调用
陷阱表(内核启动时设置,内核模式下执行)
LDE受限直接执行协议
问题2:实现切换进程
需要操作系统在cpu中运行才能实现切换
启动时钟(特权操作,),通知硬件那些代码在发生时间中断时运行。
中断后需要保存上下文,类似陷入内核
上下文切换
切换上下文:为当前正在执行的进程保存一些寄存器的值(到他的内核栈),并为即将执行的进程恢复一些寄存器的值(从内核栈)
并发:禁止处理中断时发生中断
7.进程调度:介绍
性能: 周转时间:T完成-T到达
公平:和性能矛盾
FIFO:护航效应
SJF(shortest job first):现代都是抢占式程序+上下文切换。但这里仍考虑非抢占式,后到的短任务会等待长任务完成
STCF(shortest time-to-completion first):每当新工作进入系统,确定剩余工作和新工作中剩余时间最少的,并调度。
交互性度量标准:响应时间:T首次运行-T到达时间
RR(时间切片)轮转:时间片长度必须是时钟周期的倍数
时间片长度越短,响应时间越好,但是上下文切换成本会影响整体性能。所以需要权衡时间片长度,使其摊销
周转时间很差,RR延申了每个工作
结合IO(重叠)
8.调度:多级反馈队列
MLFQ
不需要先验知识,而是通过观察工作的运行来给出优先级。短时间交互工作能获得SJF/STCF的全局性能,对长工作也能保持公平
巫毒常量:每次提升全部进程优先级的时间间隔。太短,交互性工作找不到合适的CPU时间比例,太长,长工作会饿死
9.调度:比例份额
彩票数代表所占份额