《计算机的心智:操作系统之哲学管理》读书笔记——原文摘录

说明:

这本书的语言风格比较独特,作者以风趣形象的语言讲解计算机系统的原理,在读的过程中有一些比较重要的地方就做了摘录。

红字为原文目录

黑字为原书中的内容,我觉得重要,摘录出来,以备以后复习查看。若侵犯原作者版权等,请告知我,我及时删除。



前言

第一篇 基础原理篇
第1章 操作系统导论
引子:智者的挑战

1.1 人造学科

    人造科学(特点:不准确,具有相对性<没有对错>;从对人类活动的观察导出;依赖人的主观能动性;通常符合人的直觉)

    神造学科(特点:准确,绝对;从对自然存在的观察导出;不依赖人的主观能动性;通常违反人的直觉)

1.2 程序是如何运行的

1.3 什么是操作系统

    1、操作系统是介于计算机与应用软件之间的一个软件系统。它掌控计算机上所有事情,使计算机变得好用(使人类从繁琐的、复杂的对机器掌控的任务中解脱),使计算机运行变得有序(掌控计算机上所有事情)。

   2、主要功能(替用户及其应用管理计算机的所有软硬件资源;保证计算机资源的公平竞争和使用;防止对计算机的非法侵占与使用;保证操作系统自身正常运转)

1.4 魔幻与管理

 1、魔术师(将计算机以一个更容易、更方便、更强大的方式曾现出来,进程抽象,虚拟内存抽象)

2、管理者(cpu管理、内存管理、外存管理、I/O管理——将XX分配给不同的应用与用户)、(健壮性管理、安全性管理

1.5 用户程序与操作系统
1.6 操作系统的范畴
1.7 为什么学习操作系统
思考题

第2章 操作系统历史
引子:操作系统进化的推动因素
2.1 第一阶段:状态机操作系统(1940年以前)

2.2 第二阶段:单一操作员、单一控制端操作系统(20世纪40年代)

  一组标准库函数

2.3 第三阶段:批处理操作系统(20世纪50年代)

批处理监控器+操作系统库函数。分为两部分(一部分控制程序执行,另一部分支持程序执行)

2.4 第四代:多道批处理操作系统(20世纪60年代)

同一时间运行多个程序(宏观上),操作系统要在多个程序间切换并且能管理多个输入输出设备,保证一个进程不受另一个进程的干扰。

既要管理进程,又要管理内存、还要管理cpu调度

2.5 第五代之一:分时操作系统(20世纪70年代)

多用户,用户直接和电脑交互

2.6 第五代之二:实时操作系统

软实时系统和硬实时系统

2.7 第六代:现代操作系统(1980年以后)
2.8 操作系统的演变过程
2.9 操作系统的未来发展趋势
思考题

第3章 操作系统基本概念
引子:“差不多”精神

3.1 计算机硬件基本知识

  1、总线结构->流水线结构->多流水线、超标量计算和超长指令字等多指针发射机制

   2、存储架构(指令的存放单元)包括缓存、主存、磁盘、磁带。磁盘

   3、中断、软中断(中断过程中发生的中断

3.2 抽象

  1、抽象来源于现实(计算机硬件——cpu、内存、i/o设备)而又高于现实(更强大、更好用)

   2、抽象不光是操作系统提供给用户的一个存在,它也存在与操作系统内部(操作系统内部分为不同的功能块,而不同的功能块之间相互提供的也是抽象)

3.3 内核态和用户态

   1、内核态(特权态、拥有/访问资源多的状态)可靠性、安全性要求高,维护管理复杂,

     cpu管理,内存管理,输入和输出管理(要访问各种设备和底层数据结构),诊断和测试程序,文件管理(一部分,文件系统本身的管理)

   2、用户态(非特权态、访问资源将受到限制的状态)可靠性、安全性要求低,维护管理较简单

   文件管理(一部分,用户数据的管理),编译器、网络管理的部分功能、编辑器用户程序

   3、用户态和内核态是处理器的一种状态,不是程序的状态。可以通过设置状态字将CPU设置为内核态、用户态或其它子态。一个程序运行时,CPU是什么态,这个程序就运行在什么态。

   4、内核态和用户态的实现

  要限制一个程序对资源的访问,需要对程序的每一个指令进行检查(地址翻译)才能完成。程序发出的每一个指令都要经过这个地址翻译过程,通过对翻译的控制,就可以限制程序对资源的访问。内核态时,内核程序可以绕过内存地址翻译而直接执行特权指令,这种绕过翻译的做法可以突破系统对资源的控制。

3.4 操作系统结构

巨大单一体的操作系统(内核态)->层次化的操作系统(内核态)->微内核的操作系统(内核态+用户态)

3.5 进程、内存和文件

进程是一个运动中的程序。进程表,进程核

内存是进程的存放地址。

文件是操作系统提供的外部存储设备的抽象,是程序和数据的最终存放地址。

3.6 系统调用

1、操作系统一个系统程序,为别的程序提供服务的程序。系统调用是操作系统提供的应用程序服务界面(API)。用户程序是通过调

用这些API来获取操作系统的服务。

2、系统调用按功能可以划分为六类(进程控制类、文件管理类、设备管理类、内存管理类、信息维护类、通信类)

3、系统调用分为三个阶段(参数准备阶段、参数调用识别阶段、系统调用识别阶段)

3.7 壳shell
思考题

第二篇 进程原理篇

CPU是在操作系统控制(通过进程核线程)下按照一定的顺序进行正确计算的。因为并发,我们发明了进程和线程。

三层并发

流水线:计算机体系结构层面上的并发(指令级并发)

进程:处理器结构层面上的并发

线程:进程结构层面上的并发

第4章 进程
引子

4.1 进程概论

1、计算机三大核心功能(进程管理、内存管理、文件管理)

2、进程:一个程序加载到内存后就变成了进程。

4.2 进程模型

物理视角:进程切换。每个进程都占用一块内存空间,在任何时间,CPU只执行一条指令,一个进程,至于执行哪条指令由物理程序

              计数器指定也就是说所有进程公用一个程序计数器。

逻辑视角:多道并发。进程可以执行,也可以挂起后先让别的程序先执行,之后再接着执行。只需记住挂起时自己所处的位置每个

                进程都有一个程序计数器。

时序视角:持续推进。在运行一段时间后,进程都应该完成了一定的工作量。

进程不一定必须结终,可以一直运行到强制终止或关机。

4.3 多道编程的效率

多道编程的效率与每道程序的性质、多道编程的度数、进程切换消耗等都有关系,只要度数合适,利大于弊

4.4 进程的产生与消失

进程的产生(3种):系统初始化;执行进程创立程序;用户请求创立新进程。

进程的消失(4种):寿终(运行完成而退出),自杀(进程因错误而自行退出),他杀(进程被其他进程强行杀死),处决(进程

因异常而强行终结)

4.5 进程的层次结构

unix:进程树,进程组,父进程,子进程

windows:进程树,父进程,子进程(所有进程均地位平等)

4.6 进程的状态


进程挂起的原因:进程在执行过程中执行了某种阻塞操作,这种操作需要时间等待结果才能继续执行,系统将该进程挂起,让其他进程执行;一个进程执行时间太长,系统为了公平,将其挂起,让其他进程执行。前者是进程的原因,后者是系统的原因。

从理论上,等待到执行是可以发生的,只是这种状态转化没有任何实际价值而被操作系统禁止。

4.7 进程创立

1,申请空白进程控制块PCB);

2,初始化机器寄存器;

3,初始化页表;

4,将程序代码从磁盘读入内存;

5,将处理器状态设置为“用户态”;

6,跳转到程序的起始地址(设置程序计数器);

unix  fork->exec

windows   调用createprocess

4.8 进程与地址空间

进程空间也称为地址空间,地址空间就是进程要用的所有资源。所有资源构成了状态的划分。不可能有两个进程状态完全一样。所以

每个进程对应计算机的一种状态,而计算机状态就是所有存储单元的内容。

4.9 进程管理

操作系统管理进程。

1、进程管理所需要的手段

操作系统要管理进程就要维护关于进程的一些信息。操作系统用于维护进程记录的结构就是进程表或进程控制块(pcb,process 

control block,里面存放该进程的信息)。不同操作系统维护的进程信息是不尽相同的。但应包括寄存器、程序计数器、状态字、栈、指针、优先级、进程ID,信号、创建时间、耗用CPU时间、当前持有的各种句柄等。采纳的数据结构有线性表、链表、和结构,也可能有树和图。

2、进程管理要处理的问题

资源分配(公平)和效率

4.1 0进程的缺陷

(1)进程一个时间只能做一件事;

(2)进程在执行过程中遇到阻塞,只能挂起。

所以,人们就发明了进程,来解决上述问题。

思考题

第5章 线程
引子

5.1 进程的分身术——线程

   线程是进程的分身,是进程的不同执行序列。每个线程本质是一样的,即拥有同样的程序文本。 线程模式下,一个进程只扫有一个线程,但也可以有多个线程。将进程费解为线程还可以有效利用多处理器和多核计算机。

设计线程的目的就是共享资源,提高资源利用率

5.2 线程管理

    1、进程管理就是要维持线程的各种信息.存放这些信息的数据结构侧位线程康指标(线程控制块)。线程共享一个进程空间,因

此,许多资源是共享的,这些共享的资源是放在进程控制块中,而不是线程控制块;那些不被共享的资源和信息是放在线程控制块

中,而不是进程控制块(就像家里面的客厅和卧室——共享和不共享)。
 

   2、原则:1)共享的资源越多越好,2)如果某个资源不独享会导致线程运行错误,则该资源就是有线程独享,而其他资源则有进

程里的所有线程共享。
   

 3、线程共享资源:地址空间、全局变量、打开的文件、子进程、闹钟、信号及信息服务程序,定时器、占用cpu的时间,线程独享

资源:程序计数器、寄存器、栈、状态字。

5.3 线程的实现方式

    线程的实现方式有两种:a)、进程自己来管理线程,用户态编程实现;b),操作系统来管理线程,内核态编程实现。进程的实

现方式:由于进程是在cpu上实现并发(多道编程),而cpu是由操作系统管理的,所以进程的实现只能是由操作系统内核来进行,

而不是由用户态实现的情况。
  

  1、内核态线程的实现

      线程是进程的分身,是进程的不同执行序列,线程应该是cpu调度的基本单位,又因为cpu调度是由操作系统实现的,所以操作

系统管理进程是天经地义的。
  

     与操作系统管理进程一样。操作系统管理线程,就要保护维护线程的各种资料,即进程控制块存放在操作系统内存空间中。这样,操作系统内核就可以保有进程控制块和线程控制块。而根据进程控制块和线程控制块提供的信息,操作系统就可以对线程进行各种类似进程的管理:线程调度,线程的资源分配,各种安全措施的实现。

   

 优点:1)用户编程保持简单,因为线程的复杂度有操作系统承担,用户编程时无需管理线程的调度(线程执行和挂起),2)由于

操作系统能够监测所有的线程,当一个线程执行阻塞操作时,操作系统就可以调用另一个线程。
    

缺点:1)效率低,从用户态到内核态是要花时间的;2)内核态占用内核稀缺的内存资源,因为操作系统要维护线性表,操作系统所占内存空间是固定的,由于线程数量较多(与进程相比),内存空间很容易就占满,这样最后会导致系统“死掉”。

2、用户态线程实现

   用户自己写一个执行系统做调度器,即除了正常执行任务的线程外,还有一个专门负责线程调度的线程。一个线程在执行一段时间后就主动把资源释放给别人使用。

优点:灵活;线程切换快;切换线程无需到内核态。

缺点:由于无法确定什么时候出让cpu使用权最合适,编程有点困难;用户态编程无法达到线程多道编程的目的,一个线程受阻,整个进程都无法继续。(解决办法:不让进程阻塞;阻塞后想办法激活同一进程的其它线程)。第一种行不通,


5.4 现代操作系统的线程实现模型

     用户态的操作系统负责进程内部线程非阻塞线程的切换,内核态的操作系统负责阻塞线程的切换,这样我们就可以同时实现用户态和内核态管理,内核态的线程较少,用户态线程多,每一个内核态的线程可以服务一个或多个用户态的线程,也就是线性态的线程被复用了内核态。用户态几个线程使用一个内核态的线程,如果一个线程阻塞了,那就换另一个执行。

5.5 多线程的关系

线程的通信与同步

5.6 讨论:从用户态进入内核态

有两种情况或造成一个线程从用户态进入内核态

(1)程序运行期间发生中断或异常,系统会自动切换到中断或异常处理机制上来。

(2)程序系统调用也会造成一个线程从用户态进入内核态。

5.7 讨论:线程的困惑——确定性与非确定性

(1)线程提供了程序层面上的并发性能,并发既提高了系统的效率(吞吐率),有改善了用户的响应时间。但它带来了系统运行的不确定性,相对于单一进程,多进程的执行效率和执行正确率均存在不确定性。

(2)类似于硬件的流水线机制(提供指令级的并发),

(3)在多流水线多梯度的情况下,许多指令同时在不同的流水线和梯度上执行,其之间存在的数据和指令依赖关系十分复杂。线程和流水线的管理十分复杂,从某种程度上说,线程和流水线分别是软件层和硬件层不确定的根源。

思考题

第6章 线程通信
引子

6.1 为什么要通信

进程通信(IPC,inter-process  communcation)、线程通信

6.2 线程对白:管道、记名管道、套接字

1、管道,管道是一个线性字节数组,类似文件,使用文件读写的方式进行访问。因为通过文件系统看不到管道,所以它不是文件。

管道可以设到内存里,


创建管道在shell和程序里是不一样的:shell里,只用“|”   $ sort < file1  |grep  zou    在两个utility “ sort ”和“ grep ”之间创建了一个管

道,数据从sort 流向grep。sort 的结果作为grep的输入。程序里面,创建管道需要使用系统调用popen()或者pipe().


管道的一个重要特点是使用管道的两个线程之间必须存在某种关系。


2、记名管道,如果在两个不相关的线程,之间进行管道通信,就要使用记名管道。记名管道是一个有名字的管道。记名管道与文件系

统共享一个名字空间,即我们从文件系统中看到记名管道,记名管道不能和文件系统中的任何文件重名。


记名管道的名称有两部分组成:计算机名和管道名。如\\[主机名]\管道\[管道名]\。对于同一个主机来说,与许多个同一命名管道的实

例并且可以有不同的进程打开,但不同的管道有属于自己的管道缓冲区和通信环境。


缺点:管道和记名管道只能在unix和linux中使用,管道的管道通信只能在相关进程间进行,记名管道需要知道名字来打开。


3、套接字


6.3 线程电报:信号(signal)

   

管道与套接字——这两种方式通信的缺点:1、必须事先在通信的进程间建立连接(创建管道和套接字),这就耗费资源;2、一方选

择使用管道与套接字发送信息,另一方选择接收的时机,甚至可以不接收。3、建立连接需要时间,如果信息量小的话,效率会十分

低下。


在计算机里,信号就是一个内核对象/内核数据结构,发送方将数据结构的内容填好,并指明该信号的目标进程后,发出特定的软件

中断。操作系统接收到特定的终端请求后,知道是有进程要发送信号,于是到特定的内核数据结构里查找信号接收方,并发出通知。

接到通知的进程则是对信号进行相关处理。这个过程与电报的过程相似。

6.4 线程旗语:信号量

在计算机里,信号量实际上是一个简单整数,一个进程在信号变为0或1的情况下推进,并且将信号变为1或0来防止别的进程推进。

当进程完成任务后,则将信号再变为0或1,从而允许其它进程执行。注意:信号量不管是一个通信机制,更是一个同步机制。

6.5 线程拥抱:共享内存

  

    分属于两个进程的线程间需要共享大量数据,以前的线程通信方式都无法满足。共享内存就是这两个线程共享一片内存,可以访

问这片内存中的任何内容。要使用共享内存通信,首先一个线程创建一片内存区域专门做通信用,而其他线程则将这片区域映射到自

己的地址空间。这样,线程自己的地址空间中对应共享内存的区域时,就是在和其他线程通信。

  

    共享内存与管道的区别:使用共享内存的两个内存必须在同一台物理电脑上,共享内存的访问方式是随机的,而不是只能从一端

写,从另一端读,其灵活性比管道和套接字大得多,能够传递的信息复杂得多。

  

   缺点:1)管理复杂,使用共享内存的两个线程必须在同一台物理电脑上才能使用的通信方式;2)安全性脆弱,由于两个线程存在一片共享的内存,一个中病毒,就很容易传到另一个线程。

     另:使用全局变量在同一个线程的线程间实现通信不称为共享内存。


6.6 信件发送:消息队列

    消息队列是一列具有头和尾的消息排列。新来的消息在队尾,读取消息则是从队列头部开始。消息队列与管道的区别:1)消息队

列无需固定的读写进程,任何有权限的进程都可以读写,2)它可以支持多个进程,多个进程可以读写消息队列,多对多。3)消息队

列只是在内存中实现。


6.7 其他通信机制

思考题

第7章 进程同步
引子

7.1 为什么要同步

设计线程的目的就是共享资源,提高资源利用率。线程之间的关系是合作关系。但多线程带来的是执行过程的不确定性和执行结果的不确定性。

7.2 线程同步的目的

目的一是不管线程之间的执行如何穿插,其结果都是正确的(要保证多线程执行下结果的正确性)。
目的二是保证效率。
同步就是让所有的进程按照一定的规则执行,其正确性和效率都有迹可循

7.3 锁的进化

两个进程争相执行同一段代码或访问同一个资源的现象叫竞争。这个可能造成竞争的共享代码段或资源叫临界区。

同一时刻两个线程在同一段代码上执行,叫代码竞争。同理,还有数据竞争。

(1)为了避免竞争,就需要某种协调手段,防止两个或以上的线程同时就进入到临界区。协调的目的就是在任何时刻只能有一个线程访问临界区,这叫互斥。正取互斥的四个条件:不能同时有两个线程同时在临界区里面,能够在任何薯莨和速度的CPU上正取执行,在互斥区域外不能阻止另一个线程的执行,线程不能无限制的等待进入临界区。

(2)锁,有两个基本操作:闭锁和解锁。

闭锁有两个步骤:等待锁达到打开状态,获得锁并锁上。这两个步骤应该是原子操作,不可分开,要连续进行。

解锁:很简单,打开锁就行了。

锁具有的特性:初始状态是打开状态,进临界区前必须获得锁,出临界区前打开锁,如果别人持有锁则必须等待。


所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。

7.4 睡觉与叫醒:生产者与消费者问题

   睡觉与叫醒,就是如果锁被对方持有,你不用等待锁变为打开状态,而是回去睡觉,锁打开后再把你叫醒。

7.5 信号量

  信号量是

原语,来源于原子不可分的传说。操作系统的原语,由若干多机器指令构成的完成某种特定功能的一段程序,具有不可分割性.即原语的执行必须是连续的,在执行过程中不允许被中断 。

7.6 锁、睡觉与叫醒、信号量
7.7 管程
7.8 消息传递
7.9 栅栏
思考题

第8章 进程调度
引子

8.1 调度的目标

   单一cpu模式下,实际上任何时刻只能有一个进程或线程处于执行状态。操作系统进程调度的目的:一种程序大部分时间在cpu上执行(大部分时间在计算,然后花少量时间输入输出),一种程序大部分时间在进行输入输出(大部分时间在输入输出,然后花少量时间计算,I/O导向程序或输入输出密集型程序),还有一中介于前面两种模式之间(平衡型程序)。

8.2 处理器调度的总体目标

  cpu调度目标:要达到极小化响应时间、极大化系统吞吐率、保持系统各个功能部件均处于繁忙状态和某种貌似公平的机制。

8.3 先来先服务调度算法

8.4 时间片轮转

其主要目的是改善短程序的响应时间。方法是周期性的进行进程切换。
1)系统响应时间主要依赖时间片的选择,若选择的较长,就和8.3相似,若选择的较短,系统的大部分时间都花费在进程的上下文切换上,而不是执行程序上。
2)若运行的进程较多,时间片就要选择的短一点,否则用户体验较差,

8.5 短任务优先

     STCF(shorted time  to completion first)优先级高的任务先运行,短任务优先级高于长任务,短任务优先比前几个的响应时间要短。分为非抢占和抢占两种。
缺点:1)长程序可能得不到响应时间而饥饿,我们无法知道那个进程要运行多长时间。

8.6 优先级调度

赋予重要的进程以高优先级以确保重要任务得到cpu时间。

8.7 混合调度算法

将所有进程分为不同的大类,每个大类一个优先级,高优先级的大类中的进程先执行,同大类的进程使用时间片轮转来执行。

8.8 其他调度算法
8.9 实时调度算法
8.1 0高级议题:调度异常之优先级
倒挂
思考题

第9章 锁的实现
引子:锁的实现哲学
9.1 以中断启用与禁止来实现锁
9.2 以测试与设置指令来实现锁
9.3 以非繁忙等待、中断启用与禁止来实现锁
9.4 以最少繁忙等待、测试与设置来实现锁
9.5 中断禁止、测试与设置
思考题

第10章 死锁应对
引子

10.1 发生死锁的原因

在一个多道编程的环境里,一个系统里存在多个进程或线程,这些进程和线程公享计算机里的资源,资源就是一个一个程序工作时所需的东西,如磁盘驱动器、锁、信号量、数据表格等。既可以是硬件:cpu、内存、磁盘等,也可以是软件:锁、信号量等看不见摸不着的东西。

资源是否可以抢占又可以分为:可抢占资源和非可抢占资源(如果被抢,将造成系统运行错误)。

10.2 死锁的描述

线程使用资源的顺序是:请求资源,使用资源,释放资源。

如果请求没被批准,则会发生:(a)阻塞等待,(b)立即返回,(c)失败退出,结束线程。

第一种结果可能会导致死锁

如果有一组线程,每个线程都在等待一个事情(资源的释放)的发生,而这个事情只能有该组内的另一线程发出,我们就称这组线程发生了死锁。在死锁状态下,没有线程可以执行、释放资源或被叫醒。

百度百科上的定义:集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。

10.3 死锁的4个必要条件

(1)必要条件:资源有限。指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

(2)必要条件:持有等待。一个线程在请求新的资源时,其已经获得的资源并不释放,而是继续占有。

(3)条件:不能抢占。指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

(4)条件:循环等待条件

10.4 哲学家就餐问题

1O.5 死锁的应对

有四种应对策略:

(1)允许死锁存在

(a)顺其自然,不予理睬,(b)死锁检测与修复

(2)不允许死锁存在

(c)死锁的动态避免,(d)死锁的静态防止

10.6 消除死锁的必要条件

(1)消除资源的独占条件:使尽可能多的作用资源变得可以共享。

(2)消除保持和请求条件:一个进程必须获得所有需要的资源后才能顺利进行;另一种是一个进程必须获得所有需要的资源后才能顺利进行,但是若不能满足,那就把所有已获得的资源全释放。

(3)消除非抢占条件:允许对资源的抢占,例cpu和内存等,但有些资源被抢后会造成严重后果,例锁。

(4)消除 循环等待条件:一个进程需要多个资源,1,2,它可能先申请去,再申请2;也可能先申请2,再申请1。则可能会造成死锁。若规定申请的顺序就可以避免死锁。


10.7 银行家算法:冒险的代价
10.8 哲学家就餐问题之解

10.9 讨论:死锁的思考——综合治理

死锁的四种应对策略:不予理睬,死锁检测与修复,死锁的动态避免,死锁的静态防止。

不予理睬和静态防止较合理,另外两种成本过高。通过对这两种策略的组合,例如对cpu和内存实施可抢占的静态防止策略,对磁盘、打印机等实施假脱机的共享,我们有效防止了死锁的可能,对锁等一些软件资源,我们就按照规定顺序请求,从而防止在这些资源上出现死锁,在剩下的其它资源上出现死锁,我们就不予理睬了。

10.1 0讨论:死锁、活锁与饥饿

除了死锁以外,多道编程或多线程编程还要面对资源饥饿,某个进程或线程一直等不到它需要的资源。

思考题

第三篇 内存原理篇
第11章 基本内存管理
引子

11.1 内存管理的环境

理想状态下,程序员对内存的要求:大容量、高速度和持久性。

现实内存架构:缓存+主存+磁盘+磁带。缓存(低容量、高速度、高价格)、主存(中容量、中速度、中价格)、磁盘(大容量、低速度、低价格)。这样的架构就需要一个有效的管理机制——内存管理。

     内存管理,就是对内存架构进行管理,使程序在内存架构的每一个层次上对于用户来说都是一样的,虚拟内存是操作系统提供给用户的另一个“幻想”。

11.2 内存管理的目标

(1)地址保护:在内存中运行的多道程序互不干扰。一个进程不能进另一个进程的地址空间。

(2)地址独立:程序发出的地址应与物理主存地址无关。指针里的地址是程序空间(虚拟空间)的虚拟地址(程序地址)。

11.3 虚拟内存的概念

   虚拟内存的中心思想是将物理主存扩大到便宜的、大容量的磁盘上,即把磁盘空间看做是主存空间的一部分。程序可以完全放在主存里,也可以完全放在磁盘空间里,可以部分放在主存里,可以部分放在磁盘空间里。

    这样就给人一种内存空间增大的假象。

11.4 操作系统在内存的位置

计算机中存在着两种程序:管理计算机的程序(操作系统)和使用计算机的程序(用户程序)。管理者本身也使用资源(内存空间)。

(1)最简单的办法就是把内存分为两部分,操作系统和用户程序各占一部分。分有两种情况,如下图,操作系统是为用户服务的,在逻辑上应处于用户程序的下面,左边的较符合人们的思维习惯,且在复位、中断、陷入等操作时,控制移交给操作系统更方便。



(2)现代计算机除了RAM外,还有ROM。操作系统可以全部放在ROM内,也可以部分放在ROM内。由于ROM比较贵,所以多采取后者。

(3)使用ROM的另一个好处是,把输出输入和内存访问统一起来。把输入输出设备里的寄存器或其他存储媒介编入内存地址,使得访问输出输入设备和访问内存一样。这种输出输入叫做内存映射的输出输入。如果访问的地址高于RAM的最高地址,就属于I/O操作,否者就是正常内存操作。

a)没有内存映射的输出输入,ROM里面全是操作系统。

b)使用了内存映射的输出输入,ROM的一部分是操作系统,另一部分属于I/0设备。

c)使用了内存映射的输出输入,ROM里面全属于I/0设备,如上图的右边的条形柱所示

11.5 单道编程的内存管理

最简单的内存管理就是单道编程的内存管理,每次程序都会加载在固定的内存地址。

11.6 多道编程的内存管理

由于是多道编程,就无法把程序加载在固定的内存地址。

(1)固定分区的多道编程的内存管理

把用户程序的内存空间部分分为几个区域,可以大小一样,也可以不一样。当加载用户程序时,选择一个当前空闲且容量够大的分区加载。在此模式下,一个新程序可能要在一个队列中等待。当有合适分区出现时,才进行加载。但会出现小程序占用大分区、小空间闲置的现象。

  如果程序按照空间大小排在相应的队列里就可以解决上述问题,但也会出现有空闲空间但不能运行程序的尴尬。

(2)地址翻译

   物理地址=虚拟地址+(程序)基址(程序所在区域的起始地址)

    程序所在区域的起始地址<有效地址<程序所在区域的起始地址+程序长度

  设置两个端值:基址和极限,存放在基址寄存器和极限寄存器。只有内核可以改变基址和极限。

(3)动态地址翻译的优点

  灵活、利于地址保护、可以使虚拟空间的概念得以实施。

(4)非固定分区的多道编程的内存管理


固定分区的多道编程的内存管理的缺点有:程序大小与分区大小不匹配、僵化、地址空间无法增长。

非固定分区的多道编程的内存管理的思想很简单,用户程序的空间作为一个整体存在,来一个程序,就分一块空间,用完了,就退出来,让其它程序用,如上图。

同“固定分区的多道编程的内存管理”一样,设置两个端值:基址和极限,存放在基址寄存器和极限寄存器。

一个空间的增长

但是程序增长通常有两个来源,数据和栈。这两个空间的增长方式对整个程序的扩展性产生影响。


a)、向同一个方向增长,但是这种方式空间利用率低。

b)、unix,相向的方向增长;windows,是给栈划定了边界,超出了边界就报错。

c)还有第三种,交换。

(5)交换

交换就是讲一个进程从内存倒出到磁盘上,再将其从磁盘上加载到内存中来的过程。

交换的目的:给程序腾出一个大的空间;实现进程切换(代价高,一般不这样做)。

(6)重叠

将程序按照功能分为一段一段功能相对完整的单元,一个单元执行完后,再执行另一个单元,前面的单元就不会再执行,可以就可以把后面的程序单元覆盖到当前的程序单元上,这样就可以执行一个比物理内存还要大的程序了。

(7)双基址

  如果我们运行两个一样的程序,只要设定两组基址和极限,就可以让它们共享部分内存空间。

11.7 闲置空间管理

位图表示法:给每个分配单元赋予一个字位,用于记录该单元是否闲置。成本空间是固定的,但没有容错能力,如下图。

链表表示法:将分配单元按是否闲置链接起来,如下图。


思考题

第12章 页式内存管理
引子

12.1 基址极限管理模式的问题

以前本书讲过的内存管理的方法:

(1)单道编程:固定加载地址的内存管理

(2)多道编程:固定分区的内存管理;非固定分区的内存管理;交换内存管理。这三种多道编程均使用了一种实现机制:基址+变址。(物理地址=虚拟地址+(程序)基址

12.2 分页内存管理
12.3 分页系统的优缺点
12.4 翻译速度
12.5 缺页中断处理
12.6 锁住页面
12.7 页面足寸
12.8 内存抖动
思考题

第13章 页面更换算法
引子
13.1 页面需要更换
13.2 页面更换的目标
13.3 随机更换算法
13.4 先进先出算法
13.5 第二次机会算法
13.6 时钟算法
13.7 最优更换算法
13.8 NRU算法
13.9 IRU算法
13.10 工作集算法
13.11 工作集时钟算法
13.12 页面替换策略
思考题

第14章 段式内存管理
引子
14.1 分页系统的缺点
14.2 分段管理系统
14.3 分段的优缺点
14.4 段页式内存管理
14.5 段号是否占用寻址字住
14.6 讨论:否定之否定的嵌套一纯粹
分段与逻辑分段、分页与段页
思考题

第四篇 文件原理篇
第15章 磁盘操作

引子

现代的计算机系统所处理的数据多存放在磁盘中。

文件系统就是磁盘的抽象,或者说操作系统为磁盘所提供的抽象就是:文件及文件系统

15.1 磁盘组织与管理

磁盘就是形状像盘子的磁性存储介质。特性:数据存放持久,圆形,磁性,成本低廉。

15.2 磁盘的结构

一块磁盘是有多块盘片(正反)组成,每个盘面配有一个磁头,磁头公用一个磁臂,

15.3 盘面的结构

磁道和扇面,磁道是一个一个的同心圆,每个磁道又被分为扇面(扇区),数据以扇面进行存储,扇面是磁盘的最小I/O单元。

扇面有三部分组成:标题、数据和纠错信息。

15.4 磁盘驱动器的访问速度

影响磁盘读写速度的三个因素:寻道时间、旋转延迟、数据传输时间。

15.5 操作系统界面

15.6 磁盘调度算法

算法:先来先服务、短任务优先、短服务优先、电梯梯度、提前查看电梯梯度、单向电梯梯度

思考题

第16章 文件基础
引子

16.1 为什么需要文件系统

     所有应用程序都要对数据进行处理,输入和输出数据,这些数据要找个地方存放。内存容量有限,不持久,且难以共享,进程结束或断电,数据就会消失。磁盘容量大,低成本,持久,且可以共享,进程结束或断电,数据也不会消失。但是一般用户不知道怎样驱动磁盘,计算数据在磁盘的什么位置         

     操作系统是个魔术师,提供给用户的是各种幻象——抽象,进程->cpu,虚拟内存->内存,磁盘->文件系统。文件系统是操作系统提供的另一个抽象,他是一个看不见,摸不着,但是却可以使用的一个介于磁盘与用户之间的界面,它使磁盘变得更容易使用。

16.2 什么是文件系统

       文件系统将其接触的磁盘物理特性转换为用户看得到的路径名和文件名。用户对磁盘进行访问只需要路径名和文件名即可,无需磁盘的具体信息。

16.3 文件系统的目标

  1、 地址独立(文件数据的产生和将来磁盘地址相对独立)

  2、地址保护(文件访用权限)

16.4 文件的基本知识

16.5 从用户角度看文件系统

  1、文件命名(操作系统将文件名翻译成其数据块在磁盘上存放的地址)

  2、扩展名(通常表示文件类型,.c,.cpp,.exe)

4、文件存储组织

    a、关系导向型组织,将数据之间的关系记录在文件里面,文件爱你的构建与数据之间的关系存在着某种对应关系

     1>记录流存放方式下,数据以一个记录一个记录的方式,顺序排列

     2>树形存放方式下,数据不光是按记录排列,记录之间的关系也可以被捕捉,层次关系排列,但不形成环

     3>网状存放方式下,可以成环

    b、非关系导向型组织,其组织形式不考虑数据里面的任何结构。数据就是一个数据流(可能是字位流,字节流,数据块流,它们之间的区别也就是“流”的单位不同),没有记录,没有关系。

   c、两种组织方式比较:

   关系导向型组织:文件系统需要知道很多细节(记录本身的细节,还要记录文件之间的细节),增加了文件系统的复杂性。后果是:文件系统本身的设计更加费时费力;由于文件系统的记录格式可能不同,一个文件不能再另外一个文件系统下访问,这样会照成文件的可靠性与兼容性问题。

   非关系导向型组织:由于操作系统辨认的是数据块。字节或字位,数据的语义并没有包括在组织方式里,任何操作系统都可以读写这些文件。

   字节流的文件系统更加方便,操作系统的代码更加可靠,更加灵活、用户编写也更加方便。

5、文件类型

   a、目录,记录文件的文件,它的内容是关于别的文件

   b、一般文件,用来保存数据,根据内容的组织方式可分为文本文件和二进制文件

     1>文本文件,存放的是没有经过处理的文件,ASCII码表示的文件,任何编辑器都可以打开

     2>二进制文件,存放的是经过处理的文件,普通编辑器打不开,特定软件可以打开,加密文件也是二进制文件

   c、块文件,关于输入输出设备的。,块文件模拟的是输入输出。对于每一个输入输出设备的,我们都以一个块文件来表示。需要与输入输出设备发生数据交换时,就以该文件替换。

6、文件格式

7、文件访问

   a、顺序访问,从开头访问,按先来后到的顺序读取数据,不能在中间随便跳转,但可以快进快退。

   b、随机访问,可以按照任何顺序读取数据记录,现对文件进行选点(seek),到达位置后开始读写。

8、文件属性

9、文件操作

16.6 地址独立的实现机制:文件夹

      操作系统需要一个数据结构(文件夹)来记录每个文件在磁盘上的位置,文件夹,也称为目录价(folder),存放的不是用户数据,而是关于文件和文件系统的信息。文件夹是用来追踪问价的,里面存放的是文件到文件地址的映射(文件 ->文件在磁盘上的地址),

    1、文件夹结构

   由于文件夹里面有文件夹,这就形成了一个层次结构,这个层次结构的顶端是根文件夹,也就是根目录。根目录受损,整个文件夹都会崩溃(可以通过技术部分恢复)。

   2、相对路径与绝对路径

   文件名"/zou/cs307/file.pdf"

    相对路径:

    绝对路径:从根目录开始的一个完整路径

   3、共享与链接


16.7 文件系统调甩
16.8 内存映射的文件访问
思考题

第17章 文件系统实现

引子

分区的理由:1、不同的分区可以建立不同文件系统,这样可以方便我们对文件的管理。分区具有安全上的优势,一个分区坏了,不影响其他分区的使用。分区具有可靠性上的优势,一个分区有故障,不影响其他分区的运行。

必须分区的理由:对磁盘空间的管理,计算机内存的长度通常有限,而磁盘地址需要存放在内存字中,这样操作系统可以访问的磁盘地址数量就是有限的,这个上限数就限制了操作系统可以访问的磁盘空间大小。内存字长度16位,操作系统能够表示的磁盘地址为2的16次方,即65536个磁盘地址。假设每个地址(磁盘数据块)的大小为512个字节,则操作系统能够访问地址的磁盘空间为512*65536个字节,约32Mb的空间。如果把磁盘数据块的尺寸增大,但许多文件占不到一个磁盘数据块,这样可能会造成浪费。但如果采取分区的话,可以把磁盘分为若干个32Mb的空间。

17.1 文件系统的布局

一个磁盘分为若干个三面,扇面从0开始递增,第0扇面存放的是主引导记录(MBR),该记录的内容是一个小程序,用于启动计算机,若该扇面损坏,磁盘者无法使用。


大致布局与上图类似,整个磁盘的布局如上图:从左到右依次为,主引导记录,磁盘分区表,分区1(主分区),分区2,。。分区n。

                         主分区又分为引导记录,超级数据块,闲置空间管理,I-NODE区,根目录区,文件与目录区。

磁盘分区表里面给出的是磁盘的所有分区及其开始地址和终结地址。

操作系统放在主分区里面,计算机启动时,处于主板ROM里面的bios程序首先运行,BIOS在进行一些基本的系统配置扫描后对磁盘的0扇区进行读操作,将MBR里面的程序读到内存并运行,MBR程序接下来找到系统主分区,并将系统主分区里面的引导记录(boot  Recode)加载并运行,boot  Recode里面内容是个小程序,负责找到操作系统映像,并加载到内存,从而启动操作系统。引导记录(boot  Recode)后面的内容因情况而异,一般来说,在该记录块后面的磁盘内容因文件系统的不同而不同。

   上述叙述是其中的一种,具体布局可能不同。

17.2 文件的实现

文件的实现要解决以下几个问题:给文件分配磁盘空间,记录这些磁盘空间的位置,将文件内容存放到这些空间。

存放的方式:连续方式,非连续方式(链表、索引)

1、连续存放方式,优点是读写效率高,缺点是空间浪费,文件扩展不易。

2、非连续方式:链表,每个数据块里面留出一个指针的空间,用来存放下一个数据块的位置。缺点,1)数度慢,特别是随机访问时,需要一个一个找下去;2)指针占空间;3)计算机里面的尺寸都是2的n次方,如果数据块中的一部分空间来存指针,另一部分存数据的就很可能不是2的m次方了,这样数据处理的效率就会下降。

  文件分配表(FST,file  allocation  table),所有指针从数据块里抽出来,放在一起形成一张表,存放在内存里。

3、FAT文件系统,使用FAT机制的文件系统,有FAT12,FAT16,FAT32三种,磁盘内存字节数为12,16,28(不是32个)。FAT表的大小与物理磁盘大小和磁盘数据块大小有关,物理磁盘越大,磁盘数据块越小,FAT表越大。

4、索引文件系统,

拓展阅读:FAT文件系统原理http://blog.chinaunix.net/uid-23215128-id-2521273.html

17.3 目录实现:地址独立的实现
17.4 闲置空间管理
思考题

第18章 文件系统
引子
18.1 文件系统访问控制
18.2 主动控制:访问控制表
18.3 能力表
18.4 访问控制的实施
18.5 文件系统性能
18.6 提高系统性能的方法
18.7 文件系统设计分析:日志结构的文件系统
18.8 海量数据文件系统
思考题

第五篇 I/O原理篇
第19章 输入输出
引子

19.1 什么是输入输出

19.2 输入输出的目的

   1、输入输出的目的有两个:

      a、屏蔽输入输出设备之间的差异。

      b、在不同的设计之间进行数据表示的转换。

   2、为达到上述目的,我们要保持下列机制:

      a、设备独立:不管输入输出设备是不是更好、更新,我们进行输入输出的模式和方法保持不变。

      b、设备保护:一个输入输出设备的操作不会影响对另一个输入输出设备的操作。

19.3 输入输出硬件

   1、输入输出硬件以设备存储和传输数据的方式可以划分为块设备和字符设备。

        块设备:以数据块为单位存储和传输数据的输入输出设备,磁盘、光盘、U盘、磁带等。

        字符设备:数据以字节(字符)为单位存储和传输数据的输入输出设备,鼠标,键盘,打印机、网络界面等。

        另,网络界面,有时候可以和内存进行DMA,看起来更像块设备。时钟既不属于块设备,也不属于字符设备。

    2、块设备和字符设备最大的区别是在寻址。块设备的数据按照数据块为单位进行寻址,每个数据块都有唯一的磁盘地址,数据块是可以寻址的,字符设备的字符是不可以寻址的(?)。

      设备控制器作用:1)控制设备的物理运行;2)将序列字位流转化为字节块流;3)进行纠错操作。
1、根据cpu与设备控制器沟通方式以及与内存的不同关系,物理I/O模式分为以下三种:
    a)专有通道的I/O:I/O和内存是完全脱离的。每个控制寄存器被赋予一个I/O端口(一个8位或16位的整数,这个整数与内存地址无关系,操作系统必须使用专门的输入输出特殊指令来进行数据的读写)
优点:与内存分开,输入输出操作不会影响内存选择
缺点:也是“与内存分开”,程序员必须使用IN/OUT低级指令,增加程序设计的难度,这是早期的计算机使用的。
    b)内存映射的I/O:将I/O映射到内存中,从而使I/O和内存管理得到统一。I/O设备的每个控制寄存器和设备缓冲区被赋予一个唯一的内存地址对这些地址的访问,也就是对输入输出设备的访问,从这些地址的访问逻辑上看,就是内存地址。
优点:I/O和内存管理得到统一
缺点:1)缓存使用引起的问题。
      2)总线竞争
    c)混合I/O:前两种方式的组合
2、根据cpu在I/O过程中的涉入程度进行分类
   a)繁忙等待访问:不管内存映射的输入输出,处理器均需要与I/O控制器与数据缓存区进行数据交换(按字节/数据块交换)。
   b)直接内存访问(DMA,Direct Memory Acess):如果是按数据块交换,即需要大量数据传输,就无需CPU的介入,I/O设备直接与内存交换,数据传输有DMA控制器进行管理。
    DMA输入输出的过程如下:
CPU对DMA进行设置,高暑期I/O的起始地址和数据长度;启动DMA过程;DMA进行数据传输;DMA结束后发出中断;CPU响应中断并处理结束事宜。
DMA模式需要考虑:如何访问总线(DMA与CPU形成内存总线竞争——解决方案:周期盗用或爆发模式);数据存放何处(直接放入内存、或先放入DMA缓冲区,然后通过中断让CPU一次性将DMA的数据考入内存);内存寻址模式(虚拟地址或物理地址)

19.4 输入输出软件

I/O软件的目的是魔幻和管理:魔幻将不同I/O设备的不同屏蔽,使它们看起来是一样的,管理师对这些设备进行管理,该独享的独享,该共用的共用,该缓冲的缓冲,并对设备进行实际的驱动(发出读写命令)。
1、I/O软件的目的:
设备独立:程序对I/O设备的访问不依赖于设备的物理特性,且在输入输出程序的编写时无需事先指定指定I/O设备。
统一命名:设备与文件的命名不依赖于具体的计算机,这样使用名字将使程序可以在任何机器上运行。
错误处理:对输入输出过程中产生的数据错误进行侦测与纠正,并且纠错应该是在最靠近硬件的层面上进行。
数据传输:实际操控数据在主机与外设之间的传递。
缓冲:为数据传输提供一个临时存放地,然后在方便的时候将数据拷贝到最后的目的地。
共用与独享:将设备尽量变为共享,以增大资源利用率和降低死锁发生的概率。
2、逻辑I/O模式

从CPU的涉入程度来分,可以分为可编程I/O和中断驱动I/O,这两种分别对应硬件原理的繁忙等待I/O和直接内存访问.
a)可编程I/O:在可编程模式下,CPU等待I/的完成,即CPU涉入很深,这种模式叫轮询,或繁忙等待。在等待的时间里,CPU不能干任何事情。
b)中断驱动I/O:中断驱动是将CPU从繁忙中解脱出来,在发送完一批数据后,CPU就去忙其他事情。I/O设备处理完这批数据后,就向CPU发出中断,CPU再发送另外一批数据。
中断驱动过程:1)CPU初始化I/O并启动第一次I/O操作,2)CPU去忙别的事情,3)I/O处理完数据时,向CPU发出中断请求,4)CPU处理中断,5)CPU恢复被中断的程序。
3、直接内存访问I/O原理(DMA)
中断驱动的I/O需要周期性的中断来发射或接受后续的数据,会降低系统的效率。

19.5 I/O软件分层

输入输出是个极为繁琐的事情。它牵涉到用户空间和内核空间的数据交换,I/O设备的设置与启动,中断响应与返回,而且整个过程需要提供一个与I/O设备无关的统一界面.
1、中断服务程序,

思者题

第六篇 多核原理篇

多核对操作系统的影响:

(1)多核对操作系统的进程和线程调度产生了直接影响。

(2)在多核条件下,一条指令再多的核上执行,对单核环境下的同步机制有影响。

(3)能耗的管理。

本篇最重要的内容是多核的协调。

第20章 多核结构与内存
引子

20.1 以量取胜

多核:同一个芯片(cpu)上多个核(core)

多处理器:一个体系上放置多个cpu。

20.2 多核基本概念

在x86体系结构下,多处理功能芯片经过了对称多处理器结构、超线程结构、多核结构、多核超线程结构的4个演变阶段。

(1)多处理器结构

除了提升CPU主频和增加一、二级缓存容量外,提升计算机性能最直截了当的的办法就是在一个电脑里面安装多个cpu。

又分为对称多处理器结构(SMP)和非对称多处理器结构(AMP)。

(2)超线程结构

Inter提出了超线程技术让一个cpu同时执行多重线程,从而提高cpu效率和用户满意度。

超线程技术是一个cpu上同时执行多个程序共同分享该cpu内的资源。可以让应用程序在同一时间里使用芯片的不同部分。同一个物理cpu可以外化为多个逻辑cpu,这样一个物理cpu可以同时执行多个线程。但两个线程同时需要一个资源时,其中一个要暂停。

(3)多核结构

多cpu成本高、功耗大,超线程技术又不等同与两个cpu的性能,经常碰到两个线程同时需要一个资源其中一个要暂停的情况。

多核技术可以克服上述的缺点。

多核结构就是在一个cpu里面布置两个执行核,两套执行单元(ALU、FPU、L2缓存等),其他部分则是两个核共享。

(4)多核超线程结构

多核情况下,我们也可以使用超线程技术,从而形成多核超线程。即同一个物理执行核里面可以分解为多个逻辑逻辑执行单元。

20.3 多核的内存结构

UMA:将内存作为与执行核独立的单元构建在核之外,所有的核均通过同一总线对内存进行访问。由于每个内核使用相同的方式访问内存,器到内存的延时也相同。

优点是设计简单、易实现。缺点是难以针对单个程序进行访问优化,扩展困难,多核对共享内存的竞争会使系统效率下降。

NUMA:使用多个分开的独立共享内存,每个执行核或cpu到达不同共享内存的距离不同,延时也不同,这种延时不同的内存共享模式称为非均匀内存访问。

优点是灵活、易扩展。缺点是对调度要求高。

COMA:

在每个执行核里面配备缓存,其执行所需要的数据均缓存在该缓存里面。这种完全由缓存满足数据访问的模式称为全缓存内存访问。每个执行核配备的缓存共同组成了全局地址空间。

NORMA:非远程内存访问模式

若内存单元为每个执行核私有,且每个执行核只能访问自己的私有内存,对其它内存的访问通过消息传递进行。

优点:设计比numa简单。缺点是执行核间的通信成本高。此模式在多核体系结构下使用较少。

20.4 对称多处理器计算机的启动过程

20.5 多处理器之间的通信
20.6 SMP缓存一致性

20.7 多处理器、超线程和多核的比较

多处理器、超线程和多核都是为了提升计算机性能,均可以同时执行多个指令序列。

思考题

第21章 多核环境下的进程同步
与调度
引子
21.1 多核环境下操作系统的修正
21.2 多核环境下的进程同步与调度
21.3 多核进程同步
21.4 硬件原子操作
21.5 总线锁
21.6 多核环境下的软件同步原语
21.7 旋锁
21.8 其他同步原语
21.9 核环境下的进程调度
21.10 多核环境下的能耗管理
21.11 讨论:多核系统的性能
思考题

第七篇 操作系统设计原理篇
第22章 操作系统设计之原理
引子
22.1 操作系统设计的追求
22.2 操作系统设计的第1条哲学原理:层次架构
22.3 操作系统设计的第2条哲学原理:没有时错
22.4 操作系统设计的第3条哲学原理:懒人哲学
22.5 操作系统设计的第4条哲学原理:让困于人
22.6 操作系统设计的第5条哲学原理:留有余地
22.7 操作系统设计的第6条哲学原理:子虚鸟有——海市蜃楼之美
22.8 操作系统设计的第7条哲学原理:时空转换——沧海桑田之变
22.9 操作系统设计的第8务哲学原理:策机分离与权利分离
22.10 操作系统设计的第9条哲学原理:简单为美——求于至简、归于永恒
22.11 操作系统设计的第10条哲学原理:适可而止
思考题
结语
参考文献

你可能感兴趣的:(读书)