前言
进程的组成
它由程序、数据、进程控制块(Process Control Block,PCB)
程序控制块:进程存在的唯一标识。其主要内容包括:
信息 | 含义 |
程序ID(PID、进程句柄 | 它是唯一的,一个进程都必须对应一个PID。PID一般是整形数字 |
特征信息 | 一般分系统进程、用户进程、或者内核进程等 |
进程状态 | 运行、就绪、阻塞,表示进程现的运行情况 |
优先级 | 表示获得CPU控制权的优先级大小 |
通信信息 | 进程之间的通信关系的反映,由于操作系统会提供通信信道 |
现场保护区 | 保护阻塞的进程用 |
控制信息 | 资源需求、分配控制信息 |
位置信息 | 指明程序及数据在主存或外存的物理位置 |
其他 | 工作单位,工作区,文件信息等 |
程序:程序部分描述了进程需要完成的功能
数据:数据部分包括执行时所需的数据及工作区
一个类比可以使我们更容易理解这一点。想象一位有一手好厨艺的计算机科学家正在为他的女儿烘制生日蛋糕。他有做生日蛋糕的食谱,厨房里有所需的原料:面粉、鸡蛋、糖、香草汁等等。在这个比喻中,做蛋糕的食谱就是程序(即用适当形式描述的算法),计算机科学家就是处理机(CPU),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料、以及烘制蛋糕的一系列动作的总和。现在假设计算机科学家的儿子哭着跑了进来,说他被一只蜜蜂螫了。计算机科学家就记录下他照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理螫伤。这里,我们看到处理机从一个进程(做蛋糕)切换到另一个高优先级的进程(实施医疗救治),每个(进程)拥有各自的程序(食谱和急救书)。当蜜蜂螫伤处理完之后,计算机科学家又回来做蛋糕,从他离开时的那一步继续做下去。
进程的状态及其状态间的切换
什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
一般来说,信号量S>=0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S<=0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。
经典例题:
某工厂仓库有一名保管员,该仓库可存放n箱零件。该工厂生产车间有m名工人,只要仓库空闲,工人将生产好的整箱零件放入仓库,并由保管员登记入库数量:该工厂销售部有k名销售员,只要仓库库存数能满足客户要求,便可提货,并由保管员登记出库数量。规定工人和销售员不能同时进入仓库,但是工人和工人,销售员和销售员可以同时进入仓库,其工作流程如下图所示。假设系统中P操作表示申请一个资源,当执行P操作叶对信号量减1,若信号量 S0,则执行P操作的进程继续执行,否则等待。系统中v操作表示释放一个资源,当执行V操作时对信号量加1,若信号量>0,则执行V操作的进程继续执行;若信号量≤ 0,则从阻塞状态唤醒一个进程,并将其插入就绪队列,然后执行V操作的进程继续。为了利用PV操作正确地协调工人和销售员进程之间的工作,设置了信号量S1、S2和S3,他们的初值分别为n、0和1。
a: P(S1) b: V(S2) c: P(S3) d: V(S3)
e: P(S2) c: V(S1) g: P(S3) h: V(S3)
进程调度
高级调度:又称作业调度、长程调度,把外存上处于后备队列中的那些作业调入内存,调度的对象时作业。
中级调度:为了提高内存利用率和系统吞吐量,涉及进程在内外存间的交换。从存储器资源管理的角度来看,把进程的部分或全部换出到外存上,可为当前运行进程的执行提供所需内存空间。
低级调度:又称进程调度或短调度。它决定于内存中的哪个就绪进程可以占用CPU。
1、FCFS(Firstcomefirst serve),或者称为FIFO算法,先来先处理。这个算法的优点是简单,实现容易,并且似乎公平;缺点在于短的任务有可能变的非常慢,因为其前面的任务占用很长时间,造成了平均响应时间非常慢。
2、时间片轮询算法,这是对FIFO算法的改进,目的是改善短程序(运行时间短)的响应时间,其方法就是周期性地进行进程切换。这个算法的关键点在于时间片的选择,时间片过大,那么轮转就越接近FIFO,如果太小,进程切换的开销大于执行程序的开销,从而降低了系统效率。因此选择合适的时间片就非常重要。选择时间片的两个需要考虑的因素:一次进程切换所使用的系统消耗以及我们能接受的整个系统消耗、系统运行的进程数。
时间片轮询看上起非常公平,并且响应时间非常好,然而时间片轮转并不能保证系统的响应时间总是比FIFO短,这很大程度上取决于时间片大小的选择,以及这个大小与进程运行时间的相互关系。
3、STCF算法(Shorttimeto complete first),顾名思义就是短任务优先算法。这种算法的核心就是所有的程序都有一个优先级,短任务的优先级比长任务的高,而OS总是安排优先级高的进程运行。
STCF又分为两类:非抢占式和抢占式。非抢占式STCF就是让已经在CPU上运行的程序执行到结束或者阻塞,然后在所有的就绪进程中选择执行时间最短的来执行;而抢占式STCF就不是这样,在每进来一个新的进程时,就对所有进程(包括正在CPU上执行的进程)进行检查,谁的执行时间短,就运行谁。
STCF总是能提供最优的响应时间,然而它也有缺点,第一可能造成长任务的程序无法得到CPU时间而饥饿,因为OS总是优先执行短任务;其次,关键问题在于我们怎么知道程序的运行时间,怎么预测某个进程需要的执行时间?通常有两个办法:使用启发式方法估算(例如根据程序大小估算),或者将程序执行一遍后记录其所用的CPU时间,在以后的执行过程中就可以根据这个测量数据来进行STCF调度。
4、优先级调度,STCF遇到的问题是长任务的程序可能饥饿,那么优先级调度算法可以通过给长任务的进程更高的优先级来解决这个问题;优先级调度遇到的问题可能是短任务的进程饥饿,这个可以通过动态调整优先级来解决。实际上动态调整优先级(称为权值)+时间片轮询的策略正是linux的进程调度策略之一的 SCHED_OTHER分时调度策略,它的调度过程如下:
(1)创建任务指定采用分时调度策略,并指定优先级nice值(-20~19)。
(2)将根据每个任务的nice值确定在cpu上的执行时间(counter)。
(3)如果没有等待资源,则将该任务加入到就绪队列中。
(4)调度程序遍历就绪队列中的任务,通过对每个任务动态优先级的计算(counter+20-nice)结果,选择计算结果最大的一个去运行,当这个时间片用完后(counter减至0)或者主动放弃cpu时,该任务将被放在就绪队列末尾(时间片用完)或等待队列(因等待资源而放弃cpu)中。
(5)此时调度程序重复上面计算过程,转到第4步。
(6)当调度程序发现所有就绪任务计算所得的权值都为不大于0时,重复第2步。
死锁
4个必要条件:
1.互斥条件:所谓互斥就是进程在某一时间内独占资源。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。法:
处理方法:
死锁的预防
1. 静态分配:在进程开始之初将所有其所需资源一次性分配给它->占有并保持
死锁的避免
1. 顺序分配:将资源按顺序标号,进程在申请资源的时候按顺序申请,当进程申请某资源的时候必须将其所需 的资源编号小于它的都申请到->环路
2. 银行家算法:当进程进入系统时,它必须说明对各类资源类型的实例的最大需求量。在申请资源时,要保证系 统的剩余资源量能够满足进程的所需要能完成任务的所有需求量->仍然存在着无限等待的可能
死锁的检测
在某时刻将所有资源装入set,将所有进程装入另一个set,如果某进程所需的所剩余资源能够被满足,将其从进 程set中删除掉,并且将其所占有的资源添加到资源set; 如此处理,直到进程set中的进程都不能被满足时,其中就 是死锁的进程。
死锁的排除
1.撤销所有死锁进程
2.设置恢复中间点,如果出现死锁,则从恢复点重新启动死锁进程
3.逐个撤销死锁进程,直至思索不再发生
4.从死锁进程中逐个强迫抢占某些资源,直至死锁不再发生。