操作系统重点知识整理

1. 并发和并行

  • 并发:指宏观上在一段时间内能同时运行多个程序,但任一个时刻点上只有一个程序在处理器上运行,是逻辑上的同时发生(并行更多是侧重于物理上的同时发生)。
  • 并行:指同一时刻能运行多个指令,需要硬件支持,如多流水线或者多处理器。

2. 同步与异步

  • 同步:所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。(总结:由调用者主动等待这个调用的结果。)
  • 异步:当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

3. 信号量和经典同步问题

1. 信号量

  • 信号量是一个整数型变量,只能通过两个原子操作wait和signal来访问,即是P和V操作。
  • 如果信号量的取值只能为 0 或者 1,那么就成为了 互斥量(Mutex) ,0 表示临界区已经加锁,1 表示临界区解锁。
  • wait实现:
wait(semaphore s){
   s.value--;
   if(s.value < 0){
       block();
   }
}
  • signal实现:
signal(semaphore s){
   s.value++;
   if(s.value <= 0){
       block();
   }
}

2. 生产者-消费者问题

  • 信号量empty表示空缓冲项,初始化为n;full表示满缓冲项,初始化为0;

生产者代码

do{
    //制造产品。。。
    wait(empty);
    wait(mutex);
    //把产品加入到缓冲区。。。
    signal(mutex);
    signal(full);

} while(TRUE);

消费者代码

do{

    wait(full);
    wait(mutex);
    //消费产品,把产品移出缓冲区。。。
    signal(mutex);
    signal(empty);
}while(TRUE);

4. 死锁的四个条件以及死锁避免的算法

1. 四个条件

  1. 互斥:资源非共享
  2. 请求与保持:一个进程至少占有一个资源,并等待另外一个资源
  3. 不可抢占:资源不能被强占。
  4. 环路等待:P0等待资源为P1占有,P1等待资源为P0占有。

2. 死锁避免算法:银行家算法

死锁检测算法:如果一个进程所请求的资源能够被满足,那么就让它执行,释放它拥有的所有资源,然后让其它能满足条件的进程执行。

这里写图片描述

  • E 向量:资源总量
  • A 向量:资源剩余量
  • C 矩阵:每个进程所拥有的资源数量,每一行都代表一个进程拥有资源的数量
  • R 矩阵:每个进程继续请求的资源数量

进程 P1 和 P2 所请求的资源都得不到满足,只有进程 P3 可以,让 P3 执行,之后释放 P3 拥有的资源,此时 A = (2 2 2 0)。P1 可以执行,执行后释放 P1 拥有的资源,A = (4 2 2 2) ,P2 也可以执行。所有进程都可以顺利执行,没有死锁。

算法总结:
每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。

  1. 寻找一个没有标记的进程 Pi,它所请求的资源小于等于 A。
  2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。(将其占有的资源释放)
  3. 如果有没有这样一个进程,算法终止。

3. 死锁恢复

  • 利用强占恢复
  • 杀死进程

5. 虚拟内存机制与页面置换算法

虚拟内存

  • 虚拟内存的优点:允许执行的进程不必完全在内存中,程序可以比物理内存大;将逻辑内存与物理内存分离。
  • 基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。
  • 虚拟内存中,允许将一个作业分多次调入内存。釆用连续分配方式时,会使相当一部分内存空间都处于暂时或“永久”的空闲状态,造成内存资源的严重浪费,而且也无法从逻辑上扩大内存容量。因此,虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。虚拟内存的实现有以下三种方式:分页,分段,段页式。

页面置换算法

如果发生缺页,那么就需要将缺失的页从磁盘载入内存,如果内存不够,那么就要淘汰一些页,这就涉及到了页面置换算法。

1. FIFO

  • 所选择换出的页面是最先进入的页面。
  • 该算法会将那些经常被访问的页面也被换出,从而使缺页率升高。
    这里写图片描述

2. OPT(Optimal)

  • 所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。
  • 是一种理论上的算法,因为无法知道一个页面将来多长时间会被再访问到。
    这里写图片描述

3. LRU(Least Recently Used)

  • 虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。
    这里写图片描述

补充,实现LRU的三种方案:

  1. 用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已满时,将时间戳最大的数据项淘汰。

  2. 利用一个链表来实现,每次新插入数据的时候将新数据插到链表的头部;每次缓存命中(即数据被访问),则将数据移到链表头部;那么当链表满的时候,就将链表尾部的数据丢弃。

  3. 利用链表和hashmap,和第二种方案基本相同,只不过用到了hashmap存储每个元素的引用,数据被访问的时候无需遍历链表。


6. 磁盘调度算法

  1. 先来先服务(FCFS, First Come First Serverd)
    根据进程请求访问磁盘的先后次序来进行调度。优点是公平和简单,缺点也很明显,因为未对寻道做任何优化,使平均寻道时间可能较长。
    这里写图片描述

  2. 最短寻道时间优先(SSTF, Shortest Seek Time First)
    要求访问的磁道与当前磁头所在磁道距离最近的优先进行调度。这种算法并不能保证平均寻道时间最短,但是比 FCFS 好很多。SSTF 会出现进行饥饿现象。考虑以下情况,新进程请求访问的磁道与磁头所在磁道的距离总是比一个在等待的进程来的近,那么等待的进程会一直等待下去。
    这里写图片描述

  3. 扫描算法(SCAN)
    SCAN 算法在 SSTF 算法之上考虑了磁头的移动方向,要求所请求访问的磁道在磁头当前移动方向上才能够得到调度。因为考虑了移动方向,那么一个进程请求访问的磁道一定会得到调度。当一个磁头自里向外移动时,移到最外侧会改变移动方向为自外向里,这种移动的规律类似于电梯的运行,因此又常称 SCAN 算法为电梯调度算法。
    这里写图片描述

  4. 循环扫描算法(CSCAN)
    CSCAN 对 SCAN 进行了改动,要求磁头始终沿着一个方向移动。
    这里写图片描述


7. 机械磁盘原理

这里写图片描述

  • 磁盘片的表面被逻辑的划分为圆形磁道,磁道再进一步划分为扇区,每一个磁道可能包含数百个扇区。位于同一磁臂的的磁道集合形成了柱面
  • 随机访问时间=寻道时间+旋转等待时间。
  • 寻道时间:移动磁臂到所要的柱面所用时间;(磁盘调度算法相关的时间就是这个)
  • 旋转等待时间:等待所要的扇区转到磁臂下所用的时间。

7. 文件系统分配方法

1.连续分配

  • 要求每个文件在磁盘上占有一个连续的块。
  • 如果文件长为n并且从位置b开始,则该文件将占有b,b+1,b+2…b+n-1。一个文件目录包括开始块的地址以及文件的块数。
  • 寻道时间比较短,支持顺序访问和直接访问。
  • 新文件分配比较麻烦,可能产生外部碎片。

这里写图片描述

2.链接分配

  • 采用链接分配,每个是磁盘块的链表。磁盘块分布在磁盘任何地方,每块都有指向下一块的地址。文件目录包括文件的第一块的指针以及最后一块的指针。
  • 类似链表,不能直接访问。
  • 指针占用空间。

这里写图片描述

3.索引分配

  • 把链接分配的所有指针放在一起,即通过索引块解决问题。
  • 先从索引块查找文件索引,支持直接访问,没有外部碎片。

这里写图片描述


8. 中断和轮询

  • 对I/O设备的程序轮询的方式,是早期的计算机系统对I/O设备的一种管理方式。它定时对各种设备轮流询问一遍有无处理要求。轮流询问之后,有要求的,则加以处理。在处理I/O设备的要求之后,处理机返回继续工作。尽管轮询需要时间,但轮询要比I/O设备的速度要快得多,所以一般不会发生不能及时处理的问题。当然,再快的处理机,能处理的输入输出设备的数量也是有一定限度的。而且,程序轮询毕竟占据了CPU相当一部分处理时间,因此,程序轮询是一种效率较低的方式,在现代计算机系统中已很少应用。
  • 程序中断通常简称中断,是指CPU在正常运行程序的过程中,由于预先安排或发生了各种随机的内部或外部事件,使CPU中断正在运行的程序,而转到为响应的服务程序去处理。
  • 轮询——效率低,等待时间很长,CPU利用率不高。
  • 中断——需要保存和恢复现场,CPU利用率高。

9. 多线程模型

线程的实现可以分为:用户级线程和内核级线程。

  • 内核级线程:切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态;可以很好的利用smp,即利用多核cpu。windows线程就是这样的。
  • 用户级线程内核的切换由用户态程序自己控制内核切换,不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核Cpu,目前Linux pthread大体是这么做的。

多线程模型有三种:
- 一对一:指每一个用户级线程创立的时候,就有一个内核线程创建。缺点开销大。优点比多对一模型更好的并发功能,允许多个线程并行运行在多个处理器上。一旦用户线程终止,两个线程都将离开系统。(反过来,一个内核线程不一定就会对应一个用户线程)。一般一直使用API或者是系统调用创建的线程均为一对一线程。例如,linux使用clone创建的线程,以及win下使用CreateThread创建的线程。

这里写图片描述

  • 多对一:多是用户,一是内核。如果一个线程阻塞了系统调用,那么种进程都会阻塞,因为任一时刻只有一个线程可以访问内核。

这里写图片描述

  • 多对多:克服了多对已的缺点,开发人员可以创建任意多的用户线程,并且相应内核线程能在多处理器系统上并发执行。

这里写图片描述


10. 内存管理

1. 连续内存分配(块式)

  • 将内存分为多个固定区(pation)。操作系统有个表,记录那些内存可用与不可用。当新进程需要分配内存时,为该进程查找足够大的孔(hole),找到则分配。
  • 动态分配问题:从一组可用孔中选择一个空闲孔有以下方法:

    1. 首次适应:分配第一个足够大的孔,查找到一个符合条件的就可以停止。
    2. 最佳适应:分配最小的、足够大的孔,必须查找整个列表。
    3. 最差适应:分配最大的孔,同理必须查找整个列表。
  • 首次适应和最佳适应效率较高。

  • 该方式会产生外部碎片。

2. 分页(页式)

  • 分页允许进程的物理地址空间是可以非连续的,为绝大多数操作系统采用。
  • 实现方法:将物理内存分为固定大小的块,称为帧(frame);将逻辑内存也分为同样大小的块,称为页(page)。
  • 在分页机制中,CPU生成的地址(逻辑地址)=页号+页偏移。页号作为页表的索引,通过页表可以找到每页所在物理内存的基地址,基地址+页偏移就形成了物理地址。如下图,逻辑地址空间为2^m,页大小为2^n,m-n为页号,n为页偏移。
    这里写图片描述

  • 如下图,页大小为4B,逻辑地址3(页号为0,页偏移为3)先查找页表中0页号对应的帧,得到帧5,所以映射为物理地址23=(5*4)+3。

这里写图片描述

  • 采用分页技术 不会产生外部碎片,但是可能产生内部碎片。
  • TLB(转换表缓冲区)与页表一起使用,能够加快页表访问速度:TLB只包括页表中的一小部分条目。当CPU产生逻辑地址后,将其页号提交给TLB。如果找到页号,那么也就得到了帧号,并可用来访问内存。如果页码不在TLB中,那么就需要访问页表从而得到帧号进而访问内存,同时将页号和帧号放进TLB中用以下次查询。

3. 分段(段式)

  • 一个段构成一个独立的地址空间。每个段的长度可以不同,并且可以动态增长。
  • 消除内部碎片,会产生外部碎片。
  • 逻辑地址=段号s+段内偏移d。

4. 段页式

  • 结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。

分页和分段的对比

分页和分段系统有许多相似之处。比如,两者都采用离散分配方式,且都要通过地址映射机构来实现地址变换。但在概念上两者完全不同,主要表现在下述三个方面。

  • 页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外部碎片,提高内存的利用率,但是会有内部碎片。或者说,分页仅仅是由于系统管理的需要而不是用户的需要。段则是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好地满足用户的需要。

  • 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。

  • 分页的作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个记忆符,即可表示一个地址;而分段的作业地址空间则是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。


11. 进程间通信的方式

  • 管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。
  • 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其它进程也访问该资源。主要作为进程间以及同一进程内不同线程之间的同步手段。
  • 消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
  • 共享内存就是映射一段能被其它进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
  • 套接字也是一种进程间通信机制,与其它通信机制不同的是,它可用于不同机器间的进程通信。

12. 进程和线程的区别

  • 进程:进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
  • 线程:是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

  • 根本区别就一点:用多进程每个进程有自己的地址空间(address space),线程则共享地址空间(例如共享堆,全局变量等),每个线程有自己的寄存器,栈。所有其它区别都是由此而来的: 1。速度:线程产生的速度快,线程间的通讯快、切换快等,因为他们在同一个地址空间内。 2。资源利用率:线程的资源利用率比较好也是因为他们在同一个地址空间内。 3。同步问题:线程使用公共变量/内存时需要使用同步机制还是因为他们在同一个地址空间内。


13. CPU调度算法

  • FCFS先到先服务调度:这是一种不可抢占方式的调度算法,优点是实现简单,缺点是后来的进程等待CPU的时间较长,可能会有饥饿现象。
  • SJF最短作业优先调度:CPU优先分配给最短CPU区间的进程,实现难度较大,因为要准确预定下一个进程的CPU执行周期是很困难的。
  • 优先级调度:根据优先级的抢占式调度
  • 轮转法(RR)调度:按照时间片切分,轮转调度。需要将CPU的处理时间分成固定大小的时间片,如果一个进程在被调度选中之后用完了系统规定的时间片,但又未完成要求的任务,则它自行释放自己所占有的CPU而排到就绪队列的末尾,等待下一次调度。同时,进程调度程序又去调度当前就绪队列中的第一个进程。时间片长度的选取非常重要。如果时间片长度过短,将使进程上下文切换次数也大大增加,从而加重系统开销。反过来,如果时间片长度选择过长,有可能轮转法变成了先来先服务法。时间片长度的选择是根据系统对响应时间的要求和就绪队列中所允许最大的进程数来确定的。
  • 多级队列调度:进程例如前台进程和后台进程,可分到不同的队列,每个队列优先级不同,有自己的调度算法。
  • 多级反馈队列调度:允许进程在队列之间移动,例如CPU时间长的队列会移动到更低优先级队列。

14. 进程同步的方式

注意要与进程通信的方式区分开

  • 信号量:用于进程间传递信号的一个整数值。在信号量上只有三种操作可以进行:初始化,P操作和V操作,这三种操作都是原子操作。P操作(递减操作)可以用于阻塞一个进程,V操作(增加操作)可以用于解除阻塞一个进程。
  • 管程:信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。

15. 用户模式和内核模式

  • 当用户的应用程序运行时,系统处于用户模式。当应用程序需要系统调用时,则由用户模式切换到内核模式,这个过程会发生中断。只要操作系统获得了计算机的控制权,它就处于内核模式,当它将控制权交回给用户时,会切回到用户模式。
    这里写图片描述

16. 进程的几种状态

  • 运行态:进程占用CPU,并在CPU上运行;
  • 就绪态:进程已经具备运行条件,但是CPU还没有分配过来;
  • 阻塞态:进程因等待某件事发生而暂时不能运行;

以上笔记摘自《操作系统概念》

猜你喜欢

转载自blog.csdn.net/huanglu20125/article/details/79487990
今日推荐