-
进程管理
- 进程:资源分配的基本单位
- 线程:独立调度的基本单位,一个进程中有多个线程,共享进程资源
- 区别:
- 拥有资源:进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源
- 调度:线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程的切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换
- 系统开销:创建或撤销进程,系统都要为之分配或回收资源,所付出的开销远大于创建或撤销进程时的开销,而线程切换只需要保存和设置少量寄存器内容,开销很小
- 通信:线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助IPC
-
进程状态切换
-
只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间, 转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态 转换为就绪态。
-
进程调度算法
-
批处理系统:保证吞吐量和周转时间
-
先来先服务:按照请求的顺序调度,有利于长作业,不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业有需要执行很长时间,造成了短作业等待时间过长
-
短作业优先:按估计运行时间最短的顺序进行调度,长作业有可能会饿死,处于一直等待短作业执行完毕的状态,因为如果一直有短作业到来,那么长作业永远得不到调度
-
最短剩余时间优先:按估计剩余时间最短的顺序进行调度
-
-
交互式系统:快速进行响应
-
时间片轮转:将所有就许进程按FCFS的原则排成一个队列,每次调度时,把CPU时间分配给队首进程,该进程可以执行一个时间片,当时间片用完是,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把CPU时间分配给队首的进程,算法效率和时间片的大小有很大关系:因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上花过多时间
- 优先级调度:为每个进程分配一个优先级,按优先级进行调度,为了防止低优先级得进程永远等不到调度,可以随着时间得推移增加等待进程的优先级
- 多级反馈队列:一个进程需要100个时间片,那么此啊哟和老公时间片轮转需要交换100次,多级队列就是为这种需要连续执行多个时间片进程考虑,设置多个队列, 每个队列时间片大小不同,例如1,2,4,8等,在第一个队列没有执行完,就会被移到下一个队列,每个队列得优先级不同,上一级得队列没有执行完得进程,才会到下一级
-
- 实时系统:要求一个请求在一个确定的时间内的到响应,硬实时和软实时,前职业必须满足绝对的截止时间,否则可以容忍一定得超时
-
-
进程同步
- 临界区
- 同步和互斥:同步指多个进程按一定顺序执行,互斥指多个进程在同一时刻只有一个进程能进入临界区
- 信号量:一个整形变量,可以down和up操作,也就是PV操作
-
down : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;
-
up :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。
-
typedef int semaphore;
semaphore mutex = 1;
void P1() {
down(&mutex);
// 临界区
up(&mutex);
}
void P2() {
down(&mutex);
// 临界区
up(&mutex);
}
- 管程:它进程永远不能使用管程。有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否者其它进程永远不能使用管程。
-
进程通信
- 管道:只支持半双工通信(单向交替传输); 只能在父子进程中使用。
- FIFO:命名管道,去除了管道只能在父子进程中使用的限制。FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进程和服务器进程之间传递数据。
- 消息队列:相比于 FIFO,消息队列具有以下优点:
- 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
- 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
- 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
- 信号量:它是一个计数器,用于为多个进程提供对共享数据对象的访问
- 共享存储:允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。
- 套接字:与其它通信机制不同的是,它可用于不同机器间的进程通信。
- 管道:只支持半双工通信(单向交替传输); 只能在父子进程中使用。
-
死锁
-
必要条件
-
互斥:每个资源要么已经分配给了一个进程,要么就是可用的。
-
占有和等待:已经得到了某个资源的进程可以再请求新的资源。
-
不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。
-
环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资
源。
-
-
处理方法:
- 鸵鸟策略:因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
- 死锁检测和死锁恢复:
- 每种类型一个资源的死锁检测:每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。
- 多种类型资源的死锁检测
- 死锁恢复:抢占恢复,回滚恢复和杀死进程
- 死锁预防:破坏四个必要条件其中之一即可
-
-
页面置换算法
- 最佳:所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。
- 最近最久未使用:为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。
- 最近未使用:每个页面都有两个状态位:R 与 M,当页面被访问时设置页面的 R=1,当页面被修改时设置 M=1。其中 R 位会定时被清零。当发生缺页中断时,NRU 算法随机地从类编号最小的非空类中挑选一个页面将它换出。NRU 优先换出已经被修改的脏页面(R=0,M=1),而不是被频繁使用的干净页面(R=1,M=0)。
- 先进先出:选择换出的页面是最先进入的页面。该算法会将那些经常被访问的页面也被换出,从而使缺页率升高。
- 第二次机会算法:当页面被访问 (读或写) 时设置该页面的 R 位为 1。需要替换的时候,检查最老页面的 R 位。如果 R 位是 0,那么这个页面既老又没有被使用,可以立刻置换掉;如果是 1,就将 R 位清 0,并把该页面放到链表的尾端,修改它的装入时
间使它就像刚装入的一样,然后继续从链表的头部开始搜索。
-
时钟:第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。
-
磁盘调度算法
- 先来先服务:按照磁盘请求的顺序进行调度,公平简单,未做任何优化,平均寻道时间很长
- 最短寻道时间优先:优先调度与当前磁头所在磁道距离最近的磁道。虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。具体来说,两端的磁道请求更容易出现饥饿现象。
- 电梯算法:电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向