文章目录
CPU虚拟化
一、进程:CPU虚拟化服务的对象
1.定义
运行中的程序
2.时分复用(CPU虚拟化的核心)
资源允许一个实体使用一小段时间,然后由另一个实体再用一小段时间
3.机制和策略
机制:低级方法或者协议,实现所需的功能,如何解决问题
策略:操作系统做出决定的算法,去做哪个
4.组成
地址空间(进程可以访问的内存)+寄存器+持久存储设备
5.进程创建
- 加载磁盘中的代码和静态数据到地址空间
- 为程序运行的堆栈分配内存
- 其他初始化任务,包括I/O相关任务
- 找到main程序入口
6.进程状态
- 运行:正在CPU上运行,正在执行指令
- 就绪:进程已完成准备,但是操作系统不在此时运行
- 阻塞:直到发生其他事件时才会准备运行
7.上下文切换(陷阱)
- 时钟中断
- 硬件隐式地将寄存器A存储到内核栈A
- 转向内核模式
- 处理陷阱
- 将内核寄存器A存到进程结构的内存A
- 将进程结构B恢复到寄存器B
- 从陷阱返回
- 从内核栈恢复寄存器B
- 转向用户态
8.进程API
1.fork():产生一个子进程
如果创建成功,子进程返回0,父进程返回子进程PID,都从fork的下一句开始执行;
父子进程的先后顺序不一定
2.exec(“p3.c”,myargs):系统调用
会直接执行新的代码段(加载新的数据,堆栈),放弃当前的代码段,成功调用不会返回
3.shell用户程序
- 先显示一个提示符prompt,等待用户输入命令
- 利用文件系统,找到对应可执行程序
- 调用fork创建新进程,调用exec的某个变体来执行该应用程序,调用wait等待命令完成
二、受限直接执行:CPU运行的机制
1.核心
直接在CPU上运行,提供用户态和系统态;让程序运行的大部分指令直接访问硬件,只在关键的节点(系统调用或者时钟中断)由操作系统介入。
2.系统调用的执行
- 执行特殊的陷阱指令,进入内核并将特权级别调整为内核级别,将寄存器保存到每个进程的内核栈
- 在内核下执行指令
- 调用一个特殊的从陷阱返回指令,返回用户程序并降低特权级别,从内存栈恢复寄存器
3.启动
机器启动时处于特权模式,会自由配置机器硬件,设置陷阱表,告知硬件发生某些异常事件时要运行哪些代码
- 初始化陷阱表(进入陷阱之后会告知硬件处理程序所在的位置)
- 硬件记住系统调用程序地址
- 在进程列表上创建条目
- 为程序分配内存
- 将程序加载到内存
- 根据argv设置程序栈
- 用寄存器/程序计数器填充内核栈
- 从陷阱返回
4.操作系统的CPU控制权
如果作业一直霸占CPU的时间,那么操作系统就没办法运行,也没办法对进程进行控制管理
利用时钟中断,每隔几毫秒产生一个时钟中断,操作系统的中断处理程序会获得CPU的控制权
三、进程调度
1.指标
- 周转时间:任务完成时间-任务到达时间 (1-3策略的目的)
- 响应时间:任务首次运行时间-任务到达时间
2.策略
- 先进先出(FIFO):先完成先到的任务
- 最短任务优先(SJF):当出现选择的时候,选择当前最短的任务执行直到完成
- 最短完成时间优先(STCF):当有新的任务进入系统时,会选择当前能够最早完成的任务
- 轮转(RR):设置一个时钟中断周期倍数的时间片,每次都运行时间片
3.多级反馈队列(MLFQ)
- 高优先级队列先运行,同一队列内轮转;
- 任务初入高优先级,用完时间片配额优先级下降
- 一般优先级越高的队列任务时间份额越小;
- 为了防止饥饿问题,一段时间后所有工作都会重新加入最高优先级队列。
4.彩票份额
根据不同进程对CPU的希望占用时间(对时间的不确定性正是最困难的点)来分配数据,然后生成随机数,落在那个进程数据,则执行该进程
彩票货币
不同用户可以为自己手下的进程分配彩票,彩票会进行全局数据的转换
彩票转让
允许一个进程临时将自己的彩票交给另一个进程
彩票通胀
一个进程可以临时提升或者降低自己拥有的彩票数
5.步长调度
根据不同进程所需要的CPU时间得到票数,取一个大数除以该票数得到步长,每次都选择当前累计里程最小的执行,执行之后,该进程里程增加其步长
四、多处理器调度
1.多CPU
多线程的诞生:多核的CPU能够加快运算速度,但是一个应用程序只能使用一个CPU,所以诞生了多线程的并发
多CPU的核心:缓存等资源的共享
2.缓存一致性
每个CPU下有对应的缓存,如果CPU将数据修改并保存到缓存中,由于缓存不会立刻写到内存中,因此如果该数据再次被读取,那么就会读取到原本尚未修改的数据
总线窥探:每个缓存都监听链接所有缓存和内存的总线来发现内存访问,如果数据修改,会作废本地副本或更新它
锁的必要性:即使底层存在一致性,如果没有锁,则非原子性的操作还是会出现,比如获得了数据之后,数据被删除了,仍会再次删除
3.缓存亲和度
一个进程在某个CPU上运行时,会在该CPU的缓存中维护各种状态,下一次该进程在该CPU上运行会更快,而在别的CPU上运行需要重新加载数据速度减慢
4.单队列多处理器调度(SQMS)
所有任务都放入一个队列,CPU调度处理
- 缺乏可扩展性:为了保证正确性,需要频繁的加锁,然而,锁会带来巨大的性能损失
- 缓存亲和度:每个任务都在不同CPU之间转移
5.多队列多处理器调度(MQMS)
每个队列都可以有不同的调度规则,当一个工作进入系统后,系统会依照一些启发性规则将其放入某个调度队列。每个队列分配的CPU相互独立。
负载不均:不同队列需要处理的任务量不同
工作窃取:工作量少的队列不断偷看其他队列是不是比自己的工作多,如果是,则会从目标队列“窃取”一个或多个工作。