操作系统:CPU虚拟化

intro

线程简单理解:一个进程里可以有多个线程,线程可以看作小的进程。同一个进程下的线程共享全局变量和堆内存。

进程

创建

现代操作系统lazily执行该过程,只有到需要时才会加载数据到进程的地址空间。

API

fork

拷贝父进程,但从fork开始执行。同时fork的返回值,子进程是0,父进程为子进程的pid。

wait

延迟进程的执行,直到子进程运行完毕才返回

exec

并无创建子进程,而是将当前运行的程序替换为不同的运行程序。通过参数来重新初始化代码段、堆、栈等。

fork和exec的分开可以实现很多功能。shell:先找到可执行程序,接着fork新进程,在新进程里面exec程序,最后wait直到进程结束。比如shell的重定向。

如:$ cat hello.c > hello.txt,在运行cat之前,先打开hello.txt,关闭stdout,然后再运行,就可以实现重定向。

limited direct execution

限制操作

为了让进程可以安全地在cpu上运行,引入不同的模式:

  • user mode:行为受限
  • kernel mode:可以实现特权操作。
    执行系统调用时,会通过trap来跳入内核并切换模式。通过内核启动时设置的trap table来跳转到相应的异常处理代码

进程切换

cooperative

当应用程序结束、异常、运行时间过长,或者通过系统调用,控制权回归操作系统。(理想的程序)

timer interrupt

时钟为设备产生周期性的中断,控制权还给操作系统,让os决定接下来运行什么。

context

保存恢复上下文,即上下文切换。为当前的进程保存状态(寄存器etc),为接下来的进程恢复状态。注意与上文的中断不同,前者隐式保存用户的寄存器到该进程的内核栈,后者显示保存到该进程结构的内存(通过保存指针,来保存和恢复状态)(?)

进程调度基础

指标

对于每个进程:
周转时间 = 完成时间 - 到达时间 (性能)
响应时间 = 首次运行时间 - 到达时间(公平)

SJF

shortest job first,先运行最短时间的任务。对比FIFO的工作方式,周转时间降低。

STCF

shortest time-to-complete first,又称抢占式任务优先,每当有新工作加入系统,都会确定哪个工作的剩余时间最小,周转时间降低。

RR

轮转调度,将工作变成多个时间切片,循环执行不同工作的切片。时间片变短,响应时间越高,但相对的上下文切换的成本提高。公平和性能是一对需要权衡的因素,不可兼得。

overlap

一个工作使用I/O的时间,可以看成是独立于该工作。则另一个工作可以利用I/O运行的时间。

MLFQ

multi-level feedback queue,多级反馈队列,其维护了多个优先级不同的队列,每个工作只存在于一个队列中,不同的队列有不同的时间配额,利用反馈的信息来决定工作的优先级。下面是其规则:

  • A的优先级 > B的优先级,则运行A而不运行B
  • A的优先级 = B的优先级,则轮转运行A和B
  • 工作进入系统时,放在最高优先级的队列
  • 一旦工作用完了其在该队列的时间配额,就降低其优先级
  • 经过一段时间S,所有工作重新加入最优先队列

proportional-share

比例份额调度

lottery share

进程运行越久,其彩票越多。在每次调度决策之前,都会抽出一个数字(中奖号码),显然,彩票越多的进程,中奖概率越大,则作为下一个运行的对象。该方法运用了随机性,当运行时间足够长时,不同工作的时间比例会趋于期望。实现上,比较轻量。

和LRU替换算法进行对比,LRU在遇到重复循环序列时,性能低。而彩票调度可以避免。

stride scheduling

步长调度,算法始终选择行程值最小的工作。严格实现,在每次调度都是正确的比例。

然而以上两种方法都不常用。


操作系统:CPU虚拟化
https://pactheman123.github.io/2024/08/30/CPU虚拟化/
作者
Xiaopac
发布于
2024年8月30日
许可协议