Skip to content

Commit

Permalink
add chart
Browse files Browse the repository at this point in the history
  • Loading branch information
OSLearning365 committed Dec 13, 2023
1 parent 97f52a6 commit e51fcf9
Show file tree
Hide file tree
Showing 47 changed files with 198 additions and 2 deletions.
6 changes: 6 additions & 0 deletions source/chapter4/2address-space.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

为了发挥上述硬件机制的能力,操作系统也需要升级自己的能力,更好地管理物理内存和虚拟内存,并给应用程序提供统一的虚拟内存访问接口。计算机科学家观察到这些不同硬件中的共同之处,即 CPU 访问数据和指令的内存地址是虚地址,通过硬件机制(比如 MMU +页表查询)进行地址转换,找到对应的物理地址。为此,计算机科学家提出了 **地址空间(Address Space)** 抽象,并在内核中建立虚实地址空间的映射机制,给应用程序提供一个基于地址空间的安全虚拟内存环境,让应用程序简单灵活地使用内存。

.. image:: address-general.png
:align: center
:scale: 45 %
:name: Address General
:alt: 地址空间示意图

本节将结合操作系统的发展历程回顾来介绍地址空间抽象的实现策略是如何变化的。

虚拟地址与地址空间
Expand Down
41 changes: 41 additions & 0 deletions source/chapter4/7more-as.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@

覆盖技术是指一个应用程序在执行过程中,其若干程序段分时共享同一块内存空间。覆盖技术的大致思路是编写一个应用程序,把它分为若干个功能上相对独立的程序段(函数集合),按照其逻辑执行结构,这些程序段不会同时执行。未执行的程序段先保存在存储设备上,当有关程序段的前一部分执行结束后,把后续程序段和数据调入内存,覆盖前面的程序段和数据。

.. image:: overlay-tech.png
:align: center
:scale: 45 %
:name: Overlay Technology
:alt: 覆盖技术示意图

覆盖技术需要程序员在编写应用程序时,来手动控制和管理何时进行覆盖,不同程序段的覆盖顺序,以及覆盖的具体空间位置。这虽然减少了应用程序在执行过程中对内存空间的需求,当对应用程序开发者的编程水平提出了很高的要求,而且通用性比较差。

内存交换
Expand All @@ -97,6 +103,12 @@

我们目前的操作系统还没实现这种技术,但不妨碍我们思考一下这种技术面临的问题和大致解决方法。在我们之前设计实现的批处理操作系统中,每次执行新应用时,需要把刚执行完毕的老应用所占内存空间给释放了,再把新应用的代码和数据换入到内存中。这是一种比较原始的应用之间交换地址空间(Swap Address Space)的方法。这种交换技术的方法也可进一步扩展用到多任务操作系统中,即把不常用或暂停的任务在内存中的代码和数据换出(Swap Out)存储设备上去。

.. image:: swap-tech.png
:align: center
:scale: 32 %
:name: Swap Technology
:alt: 交换技术示意图

首先是交换的时机,即何时需要发生交换?当一个任务在创建或执行过程中,如果内存不够用了,操作系统就需要执行内存交换操作。

第二个需要考虑的是交换的对象,即交换哪个任务?如果是一个刚创建的任务,在创建过程中内存不够用了,我们可以基于某种选择策略(如选择占用内存最多的那个任务)选择一个任务,把它所占用的内存换出到存储设备中,形成更多的空闲空间,直到被创建任务有足够的空间开始执行。如果是一个正在执行的当前任务动态需要更多的内存空间,操作系统有两种选择,一个选择与刚才的处理方式类似,找一个其他任务,并把其所占空间换出到存储设备中,从而满足当前任务的需要。另一个选择是把当前任务给暂停了(甚至有可能把它所占空间换出到存储设备上),然后让其他任务继续执行,并在执行完毕后,空出所占用的内存,并切换到下一个新任务执行,如果新任务在存储设备上,还需把新任务的代码和数据换入到内存中来;如果空闲内存能够满足被暂停的任务的内存分配需求,则唤醒该任务继续执行。
Expand Down Expand Up @@ -219,13 +231,25 @@ FIFO置换策略

FIFO置换策略虽然在实现上简单,但它对页访问的局部性感知不够,及时某页被多次访问,也可能由于它较早进入内存而被置换出去。

.. image:: fifo-strategy.png
:align: center
:scale: 45 %
:name: FIFO-swap-technology
:alt: FIFO置换策略示意图

LRU置换策略
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

LRU(Least Recently Used,最近使用最少)置换策略是一种基于历史来预测未来的置换策略,其基本思路是:操作系统替换的是最近最少使用的虚拟页。“最近”是一个时间维度的量,表示过去的一段时间。精确地说,过去的这段时间是从程序开始执行到当前程序产生“Page Fault”异常的时间片段。虚拟页被访问的近期性(Recency)表示页被访问到目前产生异常这段时间的长短。这段时间越长,页被访问的近期性越弱,最弱即最近使用最少;反之,近期性就强。

访存的近期性是一种历史信息,也是程序局部性的一种体现,因为越近被访问过的页,也许在不久的将来再次被访问的可能性也就越大。所以LRU置换策略是一种以历史来预测未来的启发式方法。在一般情况下,对于具有访存局部性的应用程序,LRU置换策略的效果接近最优置换策略的效果。

.. image:: lru-strategy.png
:align: center
:scale: 37 %
:name: LRU-swap-technology
:alt: LRU置换策略示意图

为了实现LRU置换策略,操作系统需要记录应用程序执行过程中的访存历史信息,这在实际实现上是一个挑战。LRU置换策略需要记录应用访问的每页的最后一次被访问的时间。这样,当一个页必须被替换时,该策略就选择最长时间没有被使用的页。
这里的难点是如何准确记录访存的时间信息。我们可以想象一下,通过扩展硬件和软件功能的软硬结合的方式来记录:

Expand Down Expand Up @@ -260,6 +284,11 @@ Clock置换策略

这种近似LRU策略类似时钟旋转的过程,所以也称为Clock(时钟,也称 Second-Chance 二次机会 )置换策略。虽然Clock置换策略不如LRU置换策略的效果好,但它比不考虑历史访问的方法要好,且在一般情况下,与LRU策略的结果对比相差不大。

.. image:: clock-strategy.png
:align: center
:scale: 32 %
:name: Clock-swap-technology
:alt: CLOCK置换策略示意图

时钟置换策略的一个小改进,是进一步额外关注内存中的页的修改情况。这样做的原因是:如果页已被修改(modified,也称 dirty),称为脏页,则在释放它之前须将它的更新内容写回交换区,这又增加了一次甚至多次缓慢的I/O写回操作。但如果它没有被修改(clean),就称为干净页,可以直接释放它,没有额外的I/O写回操作。因此,操作系统更倾向于先处理干净页,而不是脏页。

Expand All @@ -280,6 +309,12 @@ Clock置换策略

所以,工作集置换策略的目标就是动态调整工作集的内容和大小,一个任务占用的页面数接近其工作集大小,减少缺页异常次数。

.. image:: workingset-strategy.png
:align: center
:scale: 40 %
:name: Workingset-swap-technology
:alt: 工作集置换策略示意图

实现工作集置换策略的基本思路是,操作系统能及时跟踪任务执行中位于工作集中页面,然后在发生缺页异常或过了一段时间间隔时,淘汰一个不在工作集中的页面,如果缺页异常就换入位于交换区中的页。

实现工作集置换策略的调整是及时获取工作集信息。有了工作集的定义并不意味着存在一种工程上可接受的有效方法,能够在程序运行期间及时准确地计算出工作集。
Expand All @@ -305,6 +340,12 @@ Clock置换策略

要得到缺页率的精确值比较困难,主要是访存次数难以精确统计。我们可以采用一种近似的方法来表示缺页率。从上次缺页异常时间Tlast 到现在缺页异常时间Tcurrent 的时间间隔作为缺页率的当前指标。并用一个经验值Ts表示适中的缺页率。

.. image:: page-fault-rate-strategy.png
:align: center
:scale: 28 %
:name: PageFaultRate-swap-technology
:alt: 缺页率置换策略示意图

这样,缺页率置换策略的基本思路就是:在任务访存出现缺页时,首先计算从上次缺页异常时间Tlast 到现在缺页异常时间Tcurrent 的时间间隔。然后判断,如果 Tcurrent – Tlast > Ts, 则置换出在 [Tlast , Tcurrent ] 时间内没有被引用的页,并增加缺失页到工作集中;如果 Tcurrent – Tlast ≤ Ts, 则只增加缺失页到工作集中。

在上述思路描述中,
Expand Down
Binary file added source/chapter4/address-general.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/clock-strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/fifo-strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/lru-strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/overlay-tech.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/page-fault-rate-strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/swap-tech.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter4/workingset-strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions source/chapter5/2core-data-structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@

在内核中,每个进程的执行状态、资源控制等元数据均保存在一个被称为 **进程控制块** (PCB, Process Control Block) 的结构中,它是内核对进程进行管理的单位,故而是一种极其关键的内核数据结构。在内核看来,它就等价于一个进程。

.. image:: pcb.png
:align: center
:scale: 60 %
:name: pcb
:alt: 进程控制块示意图

承接前面的章节,我们仅需对任务控制块 ``TaskControlBlock`` 进行若干改动并让它直接承担进程控制块的功能:

.. code-block:: rust
Expand Down
65 changes: 65 additions & 0 deletions source/chapter5/4scheduling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@

- 当等待进程所等待的某个事件出现或等待的资源得到满足时,操作系统会把该进程转为就绪进程,并会把该进程从等待队列中移出,并放到就绪队列末尾。

.. image:: fcome-fserverd.png
:align: center
:scale: 30 %
:name: First-come First-severd
:alt: 先来先服务示意图

该调度策略的优点是简单,容易实现。对于满足1~5约束条件的执行环境,用这个调度策略的平均周转时间性能指标也很好。如果在一个在较长的时间段内,每个进程都能结束,那么公平性这个指标也是能得到保证的。

操作系统不会主动打断进程的运行。
Expand All @@ -131,8 +137,20 @@

为应对短进程不得不等长进程结束后才能运行的问题,我们可以想到一个调度的方法:优先让短进程执行。这就是最短作业优先(Shortest Job First,简称SJF)调度策略。其实上面让PB先执行的调度方法,就是采用了最短作业优先策略。

.. image:: sjf1.png
:align: center
:scale: 50 %
:name: Shortest Job First
:alt: 最短作业优先示意图

在更新约束条件2的前提下,如果我们把平均周转时间作为唯一的性能指标,那么SJF是一个最优调度算法。这可以用数学方法进行证明。如果有同学感兴趣,可以试试。

.. image:: sjf2.png
:align: center
:scale: 50 %
:name: Shortest Job First Turnaround Time
:alt: 最短作业优先周转时间示意图

虽然SJF调度策略在理论上表现很不错,但在具体实现中,需要对处于就绪队列上的进程按执行时间进行排序,这会引入一定的调度执行开销。而且如果进一步放宽约束,贴近实际情况,SJF就会显现出它的不足。如果我们放宽约束条件1:

1. 每个进程可以在不同时间到达。
Expand Down Expand Up @@ -200,6 +218,12 @@

如果操作系统分给每个运行的进程的运行时间是一个足够小的时间片(time slice,quantum),时间片一到,就抢占当前进程并切换到另外一个进程执行。这样进程以时间片为单位轮流占用处理器执行。对于交互式进程而言,就有比较大的机会在较短的时间内执行,从而有助于减少响应时间。这种调度策略称为轮转(Round-Robin,简称RR)调度,即基本思路就是从就绪队列头取出一个进程,让它运行一个时间片,然后把它放回到队列尾,再从队列头取下一个进程执行,周而复始。

.. image:: round-robin-theory.png
:align: center
:scale: 50 %
:name: Round Robin Theory
:alt: 基于时间片的轮转原理示意图

在具体实现上,需要考虑时间片的大小,一般时间片的大小会设置为时钟中断的时间间隔的整数倍。比如,时钟中断间隔为1ms,时间片可设置为10ms,两个用户发出了执行两个进程的请求,且两个进程大约同时到达,PA和PB的执行时间都为20s(即20,000ms)。如果采用轮转调度,那么进程的响应时间为:

0+10 = 10ms
Expand Down Expand Up @@ -377,6 +401,12 @@ MLFQ调度策略的关键在于如何设置优先级。一旦设置好进程的

实时的任务是由一组进程来实现,其中每个进程的行为是可预测和提前确定的。这些进程称为实时进程,它们的执行时间一般较短。支持实时任务的操作系统称为实时操作系统。

.. image:: real-time-schedule.png
:align: center
:scale: 45 %
:name: Real Time Schedule
:alt: 实时计算机系统的调度示意图

约束条件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -427,6 +457,12 @@ MLFQ调度策略的关键在于如何设置优先级。一旦设置好进程的
速率单调调度(Rate Monotonic Scheduling,RMS)算法是由刘炯朗(Chung Laung Liu)教授和James W. Layland在1973年提出的。该算法的基本思想是根据进程响应事件的执行周期的长短来设定进程的优先级,即执行周期越短的进程优先级越高。操作系统在调度过程中,选择优先级最高的就绪进程执行,高优先级的进程会抢占低优先级的进程。

.. image:: rms.png
:align: center
:scale: 50 %
:name: Rate Monotonic Scheduling
:alt: 速率单调调度示意图

该调度算法有如下的前提假设:

1. 每个周期性进程必须在其执行周期内完成,以完成对周期性事件的响应。
Expand All @@ -450,6 +486,12 @@ EDF调度

另一个典型的实时调度算法是最早截止时间优先(Earliest Deadline First,EDF)算法,其基本思想是根据进程的截止时间来确定任务的优先级。截止时间越早,其优先级就越高。如果进程的截止期相同,则处理时间短的进程优先级高。操作系统在调度过程中,选择优先级最高的就绪进程执行,高优先级的进程会抢占低优先级的进程。

.. image:: edf1.png
:align: center
:scale: 45 %
:name: Earliest Deadline First
:alt: EDF调度示意图

该调度算法有如下的前提假设:

1. 进程可以是周期性或非周期性的。
Expand All @@ -458,6 +500,11 @@ EDF调度
4. 进程可被抢占。


.. image:: edf2.png
:align: center
:scale: 50 %
:name: Earliest Deadline First Seize
:alt: EDF调度抢占示意图

EDF调度算法按照进程的截止时间的早晚来分配优先级,截止时间越近的进程优先级越高。操作系统在进行进程调度时,会根据各个进程的截止时间重新计算进程优先级,并选择优先级最高的进程执行,即操作系统总是优先运行最紧迫的进程。在不同时刻,两个周期性进程的截止时间的早晚关系可能会变化,所以EDF调度算法是一种动态优先级调度算法。

Expand Down Expand Up @@ -512,6 +559,12 @@ EDF调度算法按照进程的截止时间的早晚来分配优先级,截止

在2000年前,多处理器计算机的典型代表是少见的高端服务器和超级计算机,但到了2000年后,单靠提高处理器的频率越来越困难,而芯片的集成度还在进一步提升,所以在一个芯片上集成多个处理器核成为一种自然的选择。到目前位置,在个人计算机、以手机为代表的移动终端上,多核处理器(Multi Core)已成为一种普遍的现象,多个处理器核能够并行执行,且可以共享Cache和内存。

.. image:: multi-core-schedule.png
:align: center
:scale: 50 %
:name: Multi Core scheduling
:alt: 多处理器计算机系统的调度示意图

之前提到的调度策略/算法都是面向单处理器的,如果把这些策略和算法扩展到多处理器环境下,是否需要解决新问题?

.. note::
Expand Down Expand Up @@ -557,6 +610,12 @@ t1: CurID = CurID+1 CurID = CurID +1

如果我们直接使用单处理器调度的数据结构,其中的重点就是放置就绪进程的就绪队列或其他与调度相关的数据结构。那么这些数据结构就是需要互斥访问的共享数据。 为简化分析过程,我们以轮转调度采用的单就绪队列为例,面向多处理器的单队列调度的策略逻辑没有改变,只是在读写/修改就绪队列等共享数据时,需要用同步互斥的一些操作保护起来,确保对这些共享数据访问的正确性。

.. image:: queue-schedule.png
:align: center
:scale: 35 %
:name: Queue scheduling
:alt: 单队列调度示意图

采用单队列调度的一个好处是,它支持自动负载平衡,因为决不会出现一个CPU空闲而其他CPU过载的情况。

**处理器亲和性**
Expand All @@ -570,6 +629,12 @@ t1: CurID = CurID+1 CurID = CurID +1

多队列调度比单队列调度具有更好的可扩展性,多队列的数量会随着处理器的增加而增加,也具有良好的缓存亲和度。当多队列调度也有它自己的问题:负载均衡(Load Balance)问题。

.. image:: deque-schedule.png
:align: center
:scale: 35 %
:name: Deque scheduling
:alt: 多队列调度示意图

考虑如下的例子,在一个有4个进程,两个处理器的计算机系统中,有两个就绪队列,PA和PB在就绪队列Q1,PC和PD在就绪队列Q2,如果采用基于轮转调度的多队列调度,那么两个处理器可以均匀地让4给进程分时使用处理器。这是一种理想的情况。如果进程PB结束,而调度不进行进一步的干预,那么就会出现PA独占处理器1,PC和PD分时共享处理器2。如果PA也结束了,而调度还不进行进一步的干预,那么(Load Imbalance)就会出现处理器1空闲,而处理器2繁忙的情况,这就是典型的负载不均衡(Load Imbalance)的现象了。这就没有达到轮转调度的意图。

所以多队列调度需要解决负载不均衡的问题。一个简单的思路就是允许进程根据处理器的负载情况从一个处理器迁移到另外一个处理器上。对于上面的例子,如果是处理器1空闲,处理器2繁忙的而情况,操作系统只需把处理器2上的进程分一半,迁移到处理器1即可。当如果是处理器1上运行了PA,处理器2上运行了PC和PD,这就需要统计每个进程的执行时间,根据进程的执行时间,让进程在两个处理器间不停的迁移,达到在一定时间段内,每个进程所占用的处理器时间大致相同,这就达到了轮转调度的意图,并达到了负载均衡。具体处理有多种方式,比如如下方式调度:
Expand Down
Binary file added source/chapter5/deque-schedule.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/edf1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/edf2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/fcome-fserverd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/multi-core-schedule.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/pcb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/queue-schedule.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/real-time-schedule.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/rms.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/round-robin-theory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/sjf1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/chapter5/sjf2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e51fcf9

Please sign in to comment.