前言
为了面试而翻起操作系统这本大book
进程间的通信方式(IPC)
- 共享内存
- 消息队列
- 信号
- 信号量
- 套接字
- 普通管道
- 有名管道
进程调度方法
- 先来先服务调度算法
- 短作业进程优先
- 优先权调度算法
- 高响应比优先调度算法
- 轮转法
- 多级反馈队列调度
线程间的通信方式
锁机制:
- 互斥锁
- 条件变量
- 读写锁
信号量机制:
- 无名线程信号量和命名线程信号量
信号机制:
类似进程间的信号处理机制
线程间的通信目的主要是用于线程同步,所以线程没有想进程通信中的用于数据交换的通信机制
###操作系统组成部分
- 进程管理:实质上是对处理机执行“时间”的管理,即如何将CPU真正合理地分配给每个任务。
- 存储管理:实质是对存储“空间”的管理,主要指对主存的管理;
- 设备管理:实质是对硬件设备的管理,其中包括对输入输出设备的分配、启动、完成和回收
- 文件管理:又称为信息管理
- 程序接口
- 用户界面
用户态和系统态在什么时候进行切换? 平时用的都是 64 位系统,那它和 32 位系统相比, 有什么区别和优点?
以下三种情况会导致由用户态到内核态的切换
- 系统调用
- 异常,如缺页中断
- 外围设备的终端,当外围设备完成用户请求的操作,回向cpu发出中断操作
1)选址能力不同 2)计算速度不同
选择一个你熟悉的磁盘臂调度算法进行简单描
- 先来先服务: 这种算法的思想比较容易理解。假设当前磁道在某一位置,依次处理服务队列里的每一个磁道,这样做的优点是处理起来比较简单,但缺点是磁头移动的距离和平均移动距离会很大。
- 最短寻道时间优先算法:这种算法的本质是利用贪心算法来实现,假设当前磁道在某一位置,接下来处理的是距离当前磁道最近的磁道号,处理完成之后再处理离这个磁道号最近的磁道号,直到所有的磁道号都服务完了程序结束。这样做的优点是性能会优于FIFO算法,但是会产生距离当前磁道较远的磁道号长期得不到服务,也就是“饥饿”现象,因为要求访问的服务的序列号是动态产生的,即各个应用程序可能不断地提出访问不同的磁道号的请求。
- scan算法:也就是很形象的电梯调度算法。先按照一个方向(比如从外向内扫描),扫描的过程中依次访问要求服务的序列。当扫描到最里层的一个服务序列时反向扫描,这里要注意,假设最里层为0号磁道,最里面的一个要求服务的序列是5号,访问完5号之后,就反向了,不需要再往里扫。结合电梯过程更好理解,在电梯往下接人的时候,明知道最下面一层是没有人的,它是不会再往下走的
- cscan算法:循环扫描算法,来看一下上一种算法,有什么问题。仔细一看,我们会发现,在扫描到最里面的要求服务的序列时,接着会反向,在接下来的很大一部分时间里,应该是没有要求服务的磁道号的,因为之前已经访问过了。什么意思,就是说从初始磁道号到最里层的一个磁道号之间的所有序列都已经访问过了,所以SCAN会增加等待的时间。为了解决这样的情况,CSCAN算法的思想是,访问完最里面一个要求服务的序列之后,立即回到最外层欲访问磁道。也就是始终保持一个方向。故也称之为单向扫描调度算法。从最里面的一个磁道立即回到最外层欲访问的磁道,这步的距离是两者磁道号差的绝对值。
进程和线程的区别
- 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
- 并发行:不仅进程之间可以并发执行,同一个进程的多个线程也可以并发执行
- 拥有资源:进程是拥有资源的一个独立单位, 线程自己基本上不拥有系
统资源, 只拥有一点在运行中必不可少的资源(如程序计数器、 一组寄存器和栈),但是它可以与同属一个进程的其他线程共享进程所拥有的全部资源。 进程之间是不能共享地址空间的, 而线程是共享着所在进程的地址空间的 - 系统开销: 在创建或撤销进程是由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。
操作系统的换页方法
opt:最佳替换算法(optional replacement)。替换下次访问距当前时间最长的页。opt算法需要知道操作系统将来的事件,显然不可能实现,只作为一种衡量其他算法的标准。
LRU:最近最少使用(Least Recently Used).替换上次使用距离当前最远的页。根据局部性原理:替换最近最不可能 访问到的页。性能最接近OPT,但难以实现。可以维护一个关于访问页的栈或者给每个页添加最后访问的时间标签,但开销都很大
FIFO:先进先出(First In First Out),将页面看做一个循环缓冲区,按循环方式替换。这是实现最为简单的算法,隐含的逻辑是替换驻留在内存时间最长的页。但由于一部分程序或数据在整个程序的生命周期中使用频率很高,所以会导致反复的换入换出
clock: 时钟替换算法(Clock),给每个页帧关联一个使用位。当该页第一次装入内存或者被重新访问到时,将使用位置为1。每次需要替换时,查找使用位被置为0的第一个帧进行替换。在扫描过程中,如果碰到使用位为1的帧,将使用位置为0,在继续扫描。如果所谓帧的使用位都为0,则替换第一个帧
图解:
操作系统的内存管理
计算机存储的层次结构图
内存管理方法
内存管理主要包括虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。
连续分配存储管理方式
连续分配是指为一个用户程序分配连续的内存空间,连续分配有单一连续存储管理和分区式储管理两种方式
单一连续存储管理
在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和 DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存
分区式存储管理
为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。
分区式存储管理引人了两个新的问题:内碎片和外碎片。
内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。
为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。
分区式存储管理常采用的一项技术就是内存紧缩(compaction)。
固定分区
固定式分区的特点是把内存划分为若干个固定大小的连续分区。分区大小可以相等:这种作法只适合于多个相同程序的并发执行(处理多个类型相同的对象)。分区大小也可以不等:有多个小分区、适量的中等分区以及少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区
优点:易于实现,开销小。
缺点:主要有两个:内碎片造成浪费;分区总数固定,限制了并发执行的程序数目。
动态分区
动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小。与固定分区相比较其优点是:没有内碎片。但它却引入了另一种碎片——外碎片。动态分区的分区分配就是寻找某个空闲分区,其大小需大于或等于程序的要求。若是大于要求,则将该分区分割成两个分区,其中一个分区为要求的大小并标记为“占用”,而另一个分区为余下部分并标记为“空闲”。分区分配的先后次序通常是从内存低端到高端。动态分区的分区释放过程中有一个要注意的问题是,将相邻的空闲分区合并成一个大的空闲分区。
下面列出了几种常用的分区分配算法:
< 大专栏 操作系统相关知识点p>最先适配法(nrst-fit):按分区在内存的先后次序从头查找,找到符合要求的第一个分区进行分配。该算法的分配和释放的时间性能较好,较大的空闲分区可以被保留在内存高端。但随着低端分区不断划分会产生较多小分区,每次分配时查找时间开销便会增大。下次适配法(循环首次适应算法 next fit):按分区在内存的先后次序,从上次分配的分区起查找(到最后{区时再从头开始},找到符合要求的第一个分区进行分配。该算法的分配和释放的时间性能较好,使空闲分区分布得更均匀,但较大空闲分区不易保留。
最佳适配法(best-fit):按分区在内存的先后次序从头查找,找到其大小与要求相差最小的空闲分区进行分配。从个别来看,外碎片较小;但从整体来看,会形成较多外碎片优点是较大的空闲分区可以被保留。
最坏适配法(worst- fit):按分区在内存的先后次序从头查找,找到最大的空闲分区进行分配。基本不留下小空闲分区,不易形成外碎片。但由于较大的空闲分区不被保留,当对内存需求较大的进程需要运行时,其要求不易被满足。
伙伴系统
固定分区和动态分区方式都有不足之处。固定分区方式限制了活动进程的数目,当进程大小与空闲分区大小不匹配时,内存空间利用率很低。动态分区方式算法复杂,回收空闲分区时需要进行分区合并等,系统开销较大。伙伴系统方式是对以上两种内存方式的一种折衷方案。
伙伴系统规定,无论已分配分区或空闲分区,其大小均为 2 的 k 次幂,k 为整数, l≤k≤m,其中:
2^1 表示分配的最小分区的大小,
2^m 表示分配的最大分区的大小,
通常 2^m是整个可分配内存的大小。
假设系统的可利用空间容量为2^m个字, 则系统开始运行时, 整个内存区是一个大小为2^m的空闲分区。在系统运行过中, 由于不断的划分,可能会形成若干个不连续的空闲分区,将这些空闲分区根据分区的大小进行分类,对于每一类具有相同大小的所有空闲分区,单独设立一个空闲分区双向链表。这样,不同大小的空闲分区形成了k(0≤k≤m)个空闲分区链表。
分配步骤:
当需要为进程分配一个长度为n 的存储空间时:
首先计算一个i 值,使 2^(i-1) <n ≤ 2^i,
然后在空闲分区大小为2^i的空闲分区链表中查找。
若找到,即把该空闲分区分配给进程。
否则,表明长度为2^i的空闲分区已经耗尽,则在分区大小为2^(i+1)的空闲分区链表中寻找。
若存在 2^(i+1)的一个空闲分区,则把该空闲分区分为相等的两个分区,这两个分区称为一对伙伴,其中的一个分区用于配, 而把另一个加入分区大小为2^i的空闲分区链表中。
若大小为2^(i+1)的空闲分区也不存在,则需要查找大小为2^(i+2)的空闲分区, 若找到则对其进行两次分割:
第一次,将其分割为大小为 2^(i+1)的两个分区,一个用于分配,一个加入到大小为 2^(i+1)的空闲分区链表中;
第二次,将第一次用于分配的空闲区分割为 2^i的两个分区,一个用于分配,一个加入到大小为 2^i的空闲分区链表中。
若仍然找不到,则继续查找大小为 2^(i+3)的空闲分区,以此类推。
由此可见,在最坏的情况下,可能需要对 2^k的空闲分区进行 k 次分割才能得到所需分区。
与一次分配可能要进行多次分割一样,一次回收也可能要进行多次合并,如回收大小为2^i的空闲分区时,若事先已存在2^i的空闲分区时,则应将其与伙伴分区合并为大小为2^i+1的空闲分区,若事先已存在2^i+1的空闲分区时,又应继续与其伙伴分区合并为大小为2^i+2的空闲分区,依此类推。
在伙伴系统中,其分配和回收的时间性能取决于查找空闲分区的位置和分割、合并空闲分区所花费的时间。与前面所述的多种方法相比较,由于该算法在回收空闲分区时,需要对空闲分区进行合并,所以其时间性能比前面所述的分类搜索算法差,但比顺序搜索算法好,而其空间性能则远优于前面所述的分类搜索法,比顺序搜索法略差。 需要指出的是,在当前的操作系统中,普遍采用的是下面将要讲述的基于分页和分段机制的虚拟内存机制,该机制较伙伴算法更为合理和高效,但在多处理机系统中,伙伴系统仍不失为一种有效的内存分配和释放的方法,得到了大量的应用。
页式和段式存储管理
前面的几种存储管理方法中,为进程分配的空间是连续的,使用的地址都是物理地址。如果允许将一个进程分散到许多不连续的空间,就可以避免内存紧缩,减少碎片。基于这一思想,通过引入进程的逻辑地址,把进程地址空间与实际存储空间分离,增加存储管理的灵活性。地址空间和存储空间两个基本概念的定义如下:
地址空间:将源程序经过编译后得到的目标程序,存在于它所限定的地址范围内,这个范围称为地址空间。地址空间是逻辑地址的集合。
存储空间:指主存中一系列存储信息的物理单元的集合,这些单元的编号称为物理地址存储空间是物理地址的集合。
根据分配时所采用的基本单位不同,可将离散分配的管理方式分为以下三种:
页式存储管理、段式存储管理和段页式存储管理。其中段页式存储管理是前两种结合的产物。
页式存储管理
将程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(page frame)。程序加载时,可将任意一页放人内存中任意一个页框,这些页框不必连续,从而实现了离散分配。该方法需要CPU的硬件支持,来实现逻辑地址和物理地址之间的映射。在页式存储管理方式中地址结构由两部构成,前一部分是页号,后一部分为页内地址w(位移量),如图4所示:
页式管理方式的优点是:
1)没有外碎片,每个内碎片不超过页大比前面所讨论的几种管理方式的最大进步是,
2)一个程序不必连续存放。
3)便于改变程序占用空间的大小(主要指随着程序运行,动态生成的数据增多,所要求的地址空间相应增长)。
缺点是:要求程序全部装入内存,没有足够的内存,程序就不能执行。
段式存储管理
在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间。在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在段式存储管理系统中,则为每个段分配一个连续的分区,而进程中的各个段可以不连续地存放在内存的不同分区中。程序加载时,操作系统为所有段分配其所需内存,这些段不必连续,物理内存的管理采用动态分区的管理方法。
在为某个段分配物理内存时,可以采用首先适配法、下次适配法、最佳适配法等方法。
在回收某个段所占用的空间时,要注意将收回的空间与其相邻的空间合并。
段式存储管理也需要硬件支持,实现逻辑地址到物理地址的映射。
程序通过分段划分为多个模块,如代码段、数据段、共享段:
–可以分别编写和编译
–可以针对不同类型的段采取不同的保护
–可以按段为单位来进行共享,包括通过动态链接进行代码共享
这样做的优点是:可以分别编写和编译源程序的一个文件,并且可以针对不同类型的段采取不同的保护,也可以按段为单位来进行共享。
总的来说,段式存储管理的优点是:没有内碎片,外碎片可以通过内存紧缩来消除;便于实现内存共享。缺点与页式存储管理的缺点相同,进程必须全部装入内存。
页式和段式管理的区别
页式和段式系统有许多相似之处。比如,两者都采用离散分配方式,且都通过地址映射机构来实现地址变换。但概念上两者也有很多区别,主要表现在:
1)、需求:是信息的物理单位,分页是为了实现离散分配方式,以减少内存的碎片,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了更好地满足用户的需要。
一条指令或一个操作数可能会跨越两个页的分界处,而不会跨越两个段的分界处。
2)、大小:页大小固定且由系统决定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的。段的长度不固定,且决定于用户所编写的程序,通常由编译系统在对源程序进行编译时根据信息的性质来划分。
3)、逻辑地址表示:页式系统地址空间是一维的,即单一的线性地址空间,程序员只需利用一个标识符,即可表示一个地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
4)、段比页大,因而段表比页表短,可以缩短查找时间,提高访问速度。
线程的同步机制
- 临界区(Critical Section):通过对多线程的串行化来访问公共资源或一段代码, 速度快, 适合控制数据访问。 在任意时刻只允许一个线程对共享资源进行访问, 如果有多个线程试图访问公共资源, 那么在有一个线程进入后, 其他试图访问公共资源的线程将被挂起, 并一直等到进入临界区的线程离开, 临界区在被释放后, 其他线程才可以抢占。
- 互斥量(Mutex):采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限, 因为互斥对象只有一个, 所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享, 还能实现不同应用程序的公共资源安全共享
- 信号量(semaphore):它允许多个线程在同一时刻访问同一资源, 但是需要限制在同一时刻访问此资源的最大线程数目。
- 事件(Event):通过通知操作的方式来保持线程的同步, 还可以方便实现对多个线
程的优先级比较的操作