Operating Systems

虚拟化

进程

操作系统通过虚拟化(virtualizing)CPU 来提供这种假象。通过让一个进程只运行一个时间片,然后切换到其他进程,操作系统提供了存在多个虚拟 CPU 的假象。这就是时分共享(time sharing)CPU 技术,允许用户如愿运行多个并发进程。潜在的开销就是性能损失, 因为如果 CPU 必须共享,每个进程的运行会慢一点 。

操作系统为正在运行的程序提供的抽象,就是所谓的进程(process)。

创建

操作系统必须包含一些创建新进程的方法。

第一件事是将代码和所有静态数据(例如初始化变量)加 载(load)到内存中,加载到进程的地址空间中。

必须为程序的运行时栈(run-time stack 或 stack)分配一些内存。

API:fork() 返回0为子进程,否则为父进程。

exec() 运行不同的程序。

销毁

由于存在创建进程的接口,因此系统还提供了一个强制销毁进程的接口。

等待

有时等待进程停止运行是有用的,因此经常提供某种等待接口。

API:wait() waitpid()

其他控制

大多数操作系统提供某种方法来暂停进程(停止运行一段时间),然后恢复(继续运行)。

状态

例如运行了多 长时间,或者处于什么状态。

受限直接执行

操作系统需要以某种方式让许多任务共享物理 CPU,让它们看起来像是同时运行。

存在一些挑战:

  • 第一个是性能:如何在不增加系统 开销的情况下实现虚拟化?
  • 第二个是控制权:如何有效地运行进程,同时保留对 CPU 的控制?

为了使程序尽可能快地运行,操作系统开发人员想出了一种技术——称之为受限的直接执行(limited direct execution)。这个概念的“直接执行”部分很简单:只需直接在 CPU 上运行程序即可。

问题

为了良好的执行性能需要直接执行,为了防止恶意或有缺陷的程序影响到其他程序的执行需要加以限制。

受到限制的程序如何执行受限的操作

硬件通过提供不同的执行模式来协助操作系统。在用户模式(user mode)下,应用程序不能完全访问硬件资源。在内核模式(kernel mode)下,操作系统可以访问机器的全部资源。还提供了陷入(trap) 内核和从陷阱返回(return-from-trap)到用户模式程序的特别说明,以及一些指令,让操作系统告诉硬件陷阱表(trap table)在内存中的位置。

内核小心地向用户程序暴露某些关键功能,例如访问文件系统、创建和销毁进程、与其他进程通信,以及分配更多的内存。

要执行系统调用,程序必须执行特殊的陷阱(trap)指令。该指令同时跳入内核并将特权级别提升到内核模式。一旦进入内核,系统就可以执行任何需要的特权操作(如果允许),从而为调用进程执行所需的工作。完成后,操作系统调用一个特殊的从陷阱返回 (return-from-trap)指令,回到用户态。

陷阱如何知道在 OS 内运行哪些代码?内核通过在启动时设置陷阱表(trap table)来实现,告诉硬件在发生某些异常事件时要运行哪些代码。

在进程之间切换

如果操作系统没有在 CPU 上运行,那么操作系统显然没有办法采取行动。

如何重获 CPU 的控制权?

  • 协作方式:等待系统调用,等待程序主动放弃,但是存在风险(恶意程序、无限循环)。
  • 非协作方式:操作系统进行控制,利用时钟中断重新获得控制权。
  • 保存和恢复上下文:如果决定进行切换,OS 就会执行一些底层代码,即所谓的上下文切换(context switch)。操作系统要做的就是为当前正在执行的进程保存一些寄存器的值(例如,到它的内核栈),并为即将执行的进程恢复一些寄存器的值(从它的内核栈)。

进程调度

调度指标

T 周转时间= T 完成时间 − T 到达时间

T 响应时间= T 首次运行−T 到达时间

先进先出(FIFO)

先进先出(First In First Out 或 FIFO)调度,有时候也称为先到先服务(First Come First Served 或 FCFS)。它很简单,而且易于实现。

一些耗时较少的潜在资源消费者被排在重量级的资源消费者之后,就会导致平均调度时间太长。

最短任务优先(SJF)

最短任务优先(Shortest Job First,SJF),先运行最短的任务,然后是次短的任务,如此下去。

但是我们无法对任务进行预知,并且对执行时间长的任务不公平。

最短完成时间优先(STCF)

向 SJF 添加抢占,称为最短完成时间优先(Shortest Time-to-Completion First,STCF)或抢占式最短作业优先(Preemptive Shortest Job First ,PSJF)调度程序。

轮转(RR)

RR 在一个时间片(time slice,有时称为调度量子,scheduling quantum)内运行一个工作,然后切换到运行队列中的下一个任务,而不是运行一个任务直到结束。它反复执行,直到所有任务完成。因此,RR 有时被称为时间切片(time-slicing)。注意,时间片长度必须是时钟中断周期的倍数。

越短,RR 在响应时间上表现越好。但是时间片太短是有问题的:突然上下文切换的成本将影响整体性能。

结合 I/O

当前正在运行的作业在 I/O 期间 不会使用 CPU,它被阻塞等待 I/O 完成。如果将 I/O 发送到硬盘驱动器,则进程可能会被阻塞几毫秒或更长时间,具体取决于驱动器当前的 I/O 负载。因此,这时调度程序应该在 CPU 上安排另一项工作。

多级反馈队列(MLFQ)

没有工作长度的先验(priori)知识,如何设计一个能同时减少响应时间和周转时间的调度程序?

多级反馈队列是用历史经验预测未来,不需要先验知识。

MLFQ 中有许多独立的队列(queue),每个队列有不同的优先级(priority level)。任何时刻,一个工作只能存在于一个队列中。MLFQ 总是优先执行较高优先级的工作(即在较 高级队列中的工作)。

  1. 如果 A 的优先级 > B 的优先级,运行 A(不运行 B)。
  2. 如果 A 的优先级 = B 的优先级,轮转运行 A 和 B。
  3. 工作进入系统时,放在最高优先级(最上层队列)。
  4. 一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次 CPU),就降低其优先级(移入低一级队列)。
  5. 经过一段时间 S,就将系统中所有工作重新加入最高优先级队列。避免饥饿问题。如果系统有“太多”交互型工作,就会不断占用 CPU,导致长工作永远无法得到 CPU(它们饿死了)。

比例配额调度

调度程序的最终目标,是确保每个工作获得一定比例的 CPU 时间,而不是优化周转时间和响应时间。

有以下优势:

  • 随机方法常常可以避免奇怪的边角情况。
  • 随机方法很轻量,几乎不需要记录任何状态。
  • 随机方法很快。
彩票调度

彩票调度最精彩的地方在于利用了随机性(randomness)。

彩票调度利用彩票货币(ticket currency)的概念。这种方式允许拥有一组彩票的用户以他们喜欢的某种货币,将彩票分给自己的不同工作。之后操作系统再自动将这种货币兑换为正确的全局彩票。操作系统利用随机数抽奖决定运行哪一个程序。

一个有用的机制是彩票转让(ticket transfer)。

彩票通胀(ticket inflation)有时也很有用。利用通胀,一个进程可以临时提升或降低自己拥有的彩票数量。

分配彩票是一个具体要考虑的问题,没有固定的答案。

步长调度

系统中的每个工作都有自己的步长,这个值与票数值成反比。每次进程运行后,让它的计数器 [称为行程(pass)值] 增加它的步长,记录它的总体进展。之后,调度程序使用进程的步长及行程值来确定调度哪个进程。基本思路很简单:当需要进行调度时,选择目前拥有最小行程值的进程,并且在运行之后将该进程的行程值增加一个步长。

进程抽象成了一个进度条,按照票数增加进度条供操作系统选择。

多处理器调度

缓存亲和度

一个进程在某个 CPU 上运行时,会在该 CPU 的缓存中维护许多状态。下次该进程在相同 CPU 上运行时,由于缓存中的数据而执行得更快。相反,在不同的 CPU 上执行,会由于需要重新加载数据而很慢(好在硬件保证的缓存一致性可以保证正确执行)。

单队列调度(SQMS)

简单地复用单处理器调度的基本架构,将所有需要调度的工作放入一个单独的队列,称之为单队列多处理器调度(Single Queue Multiprocessor Scheduling,SQMS)。

最大的优点是简单。

缺点:

  • 缺乏可扩展性(scalability)。队列需要加锁面对多个 CPU 的竞争,造成性能损失(CPU 越多,性能损失越大)。<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值