声明:笔者仍为在校学生,有错误之处恳请批评指正~
一、进程的概念?
搞清楚这个问题,我们要先有程序的概念。
(1)什么是程序?
程序可以看做代码、数据、管理文件的集合。
程序设计的结构模式有顺序程序和多道程序设计。
(2)顺序程序
顺序程序是指程序在计算机上按照写入的顺序先来后到地执行。有点类似队列(FIFO,first in first out)的结构,顺序程序设计也就是不同的程序按序执行。这样的程序设计有顺序性、资源独占性和可再现性。
(3)多道程序设计
并行和并发的概念?并行和并发有什么区别?
并行指在某一确定的时间节点有多道程序同时进行(就好像肩并肩向前进行一样)。并发是指在某一时间段内发生若干事件。多道程序设计由此引出。
并发机制使得程序的执行结果不可再现,也使得程序之间相互制约——假如A执行到一半需要B的结果,而B还没有结束运行,那么A将等待。另外,程序之间共享数据资源,提高利用率和系统效率。
基于以上对程序的理解,我们可以对进程做一个不完全的、狭义的定义——因为进程的定义不是唯一的,没有一个能涵盖其所有特性的定义:
当然还有更多涵盖更广的定义,这也是马上要讨论的内容。
二、进程的定义与组成
方敏老师的《操作系统》中总结了进程的一个完整概念:
“进程是程序的一次执行,改程序可以和其他程序并发执行;它是一个动态的实体。在传统的操作系统设计中,进程既是基本的分配单元,也是基本的执行单元。”
正如所述,进程和程序是多对多的关系——一个进程可以包括多个程序,一道程序也可以被多个进程执行。
(1)进程的组成?
首先,进程的执行需要执行环境。那么如果一个程序暂时退出处理机,再次调用它的时候我们怎么恢复到原来的执行环境呢?最好的办法是把原来的环境保存起来,这就用到了进程的映像来实现上述的功能。进程映像就是其存储映像。
进程的存储映像的构成:
(2)进程的生命周期
进程的创建?
要搞明白操作系统是怎样创建一个进程的,就必须先要知道一台计算机的初始化是怎么完成的——由引导程序先将操作系统加载到内存,之后才可以执行操作系统。操作系统为进程创建PCB和分配地址空间的过程就是进程创建的过程。
(3)进程的终止?
主要分为两大类:寿终正寝和意外死亡。
正常结束的程序完成了代码段指定的所有操作,让出CPU;
异常结束情况很多:内存不足\等待时间过长\地址越界\父进程结束它的子进程\算数错误\父进程终止,所有子进程同时被终止等等
(4)PCB(进程控制块)简介
”PCB是操作系统用来记录进程的详细状态和相关信息的基本数据结构,它和进程是一一对应的,是进程的唯一标识。“
不同的操作系统产生的PCB的内容有所不同,大致包括:标识信息、现场信息、控制信息。
PCB的存在形式:在内存中以表的形式存在。操作系统为了对PCB方便统一管理把所有的PCB放在一块内存上形成了PCB表。
(5)进程的状态转换
进程的三种状态:就绪态(ready)、运行态(running )、阻塞态(blocked)
运行态:程序正在占用处理机。处理机正在执行该进程的程序。
就绪态:进程已经具备了可以运行的条件,等待系统分配CPU。
阻塞态:进程因为某个事件不能运行;
可转换过程:一个循环:就绪—>运行—>阻塞—>就绪;
一个可反向过程: 运行—>就绪;
转换原因:
就绪—>运行:不再有其他程序占据CPU,系统为就绪态程序分配CPU;
运行—>阻塞:进程由于等待其他某些事件的发生暂时被挂起,让出CPU。所以就绪态也称为挂起态。
阻塞—>就绪:阻塞态的程序获取了需要的资源重新进入就绪队列中。由于CPU有其他程序的运行而进入就绪等待。
运行—>就绪:由于给进程分配的时间片已经用完,系统需要处理下一个进程;或者有优先级更高的程序要进入处理机,所以该进程重新进入就绪态。这种机制和要讨论的进程调度有关。
(6)进程队列
系统中有各种不同状态的进程,怎么对这些进程进行管理呢?答案是,将PCB按照一定方法组织起来,方便统一查找和管理(之前介绍PCB时候说过,PCB是进程的唯一标识)。这种特定的组织方法多为队列,利用指针组成链表,方便进程调度和查找。
当进程的状态有变化时,被排到另外的队列中,引起进程的出入队。处理器管理出入队简称队列管理。
(7)相关例题
user space 下能否将一个进程中的不同线程绑定在不同的CPU上?
答:不能。user space 下,进程是操作系统调度的基本单位。
三、 进程控制
(1) 进程控制主要干什么?
答:创建和撤销进程以及实现进程间的相互转换。
进程控制的实现依靠操作系统内核——内核是在硬件之上的第一层软件扩充,为系统对进程控制管理提供环境。
实现操作功能:通过原语(primitive)
(2)原语及其分类
进程创建原语:
系统中有很多进程,它们是怎么创建的呢?通常创建进程有两种方式:一种是在系统生成时就建立一些系统进程,如系统调度进程;另一种是经过进程创建原语创建进程——通常是非常驻系统进程和用户进程。
进程可以创建很多子进程来帮助自己完成任务。
子进程也可以创建进程,形成进程家族。
进程撤销原语:
进程阻塞原语:
进程的阻塞是进程自身主动调用阻塞原语的结果,是自愿的行为;
具体步骤:
进程唤醒原语:
唤醒不同于阻塞的主动执行,而是需要其他的进程调用唤醒原语来完成;
原语:机器指令构成的可完成特定功能的程序段。
进程挂起、解挂原语(更新中)
(3)进程的特征
并发性、动态性、独立性、制约性、结构性... ...(深入了解后更新)
三、进程调度
(1)选择调度算法的原则
进程调度:按照一定的算法从就绪队列中选择某个进程进入CPU运行,以达到合理分配使用CPU资源、提高处理机效率,并使得各进程公平的得到处理机资源的方法。
就像前面提到的,多道程序设计的操作系统允许多个进程同时进入内存,通过分时复用技术共享CPU。进程调度的任务就是:有效选择占有CPU的进程,控制协调系统高效工作。
注意:
(2)进程调度算法
· 先进先出(FIFO)——缺点很明显
· 基于优先数的算法
让每个进程有一个优先数,数值大优先级高,调度时优先选择优先数大的进程进入CPU。怎么确定这个优先数呢?
有两种方法:静态优先数法和动态优先数法。
静态:创建进程时就规定好优先数,运行时保持不变
动态:优先数在执行过程中可调整——占用CPU时间太长,数值减小;等待时间太长,数值增大。(UNIX采用)
进程占用CPU方式也有两种:
顾名思义,不可剥夺式是指一个程序占用CPU直到结束为止。可剥夺式,进程运行中有更优先的程序要进入CPU,当前的进程就需要让出CPU。时间片轮转程序调度算法就属于这种模式。
(3)时间片轮转调度算法
类似于分时系统,时间片轮转程序调度算法简称轮转法,系统规定一个时间长度作为允许进程执行的时间片。如果进程在这段时间内没执行完毕,那么它必须让出CPU,等待下一次系统分配时间片。如果程序执行中发生阻塞或异常,即使时间片没用完也会主动让出CPU。
具体的步骤:
时间片选择方法:固定时间片长度和可变时间片长度。
确定时间片长度的依据:
(4)多级队列算法
目标:为了解决切换进程的成本问题。
根据进程性质或类型的不同,将就绪队列分为若干子队列。优先级最高的子队列进程运行一个时间片,次高级运行两个时间片,再低一级的进程分配4个时间片,以此类推。
如果一个进程在一个时间片内没有运行完,它会被移到下一级的队列中;仅当较高级的队列为空时,才调度较低优先级的进程执行~
四、进程之间的相互作用——进程之间的同步和互斥
多道程序设计系统中,同一时刻可能有相互影响的多个程序在执行——比如需要相互配合的任务,一个程序可能需要等待其他程序的输出。我们称这些并发的程序之间存在制约关系。当两个或两个以上的进程竞争同一个资源时,就需要一个同步互斥机制来协调多个进程对该资源的顺序使用。进程之间的这种同步和互斥的关系需要在进程之间建立一定的通信机制来达到协调进程的目的。
(1)进程间的同步和互斥
临界资源:又称独占资源,是指在一段时间内只能又一个进程访问的资源——可以是硬件设备:打印机、绘图仪等;也可以是共享的变量、数据、队列等资源。
假设有两个进程P1、P2,他们有共享的变量count;
P1:
{
...
R1 = count;
R1 = R1 + 1;
count = R1;
...
}
P2
{
R2 = count;
R2 = R2 + 1;
count = R2;
}
假如和我们期待的一样,两个进程顺序执行,那么最后count会被+2;
可对于这样共享同一个变量的并发进程,在计算其中的处理语句顺序是不可知的。比如执行顺序可能是这样:
R! = count;
R2 =count;
R1 = R1 +1;
count = R1;
R2 = R2 +1;
count = R2;
可以看到两个程序以各自的速度向前推进,似乎没有向着我们想要的趋势进行。最后count的值被加1而不是加2.
为什么会出现这样的错误呢?怎么避免这样的错误?
错误原因是对共享变量的访问没有加以限制——对于共享变量,在一个进程访问时,不应该给其他进程相关的访问权限(你正在一个单独的公共卫生间上厕所,这个时候你肯定不希望有人进来和你共用吧(滑稽))。
结论:必须实现临界区的访问进程互斥。
怎么实现进程互斥——硬件方法和软件方法,具体的几种方法不做详细介绍。
(2)进程的同步机制
操作系统中使用一般的同步机制——semaphore以及有关的P、V操作。
semaphore:我不知道我的参考资料翻译为“信号量”是什么意思——有的参考资料翻译为“旗语”,另外查阅资料得知原始的翻译为铁道上的信号灯,这么看来“旗语”好像更贴切和容易理解一些。我们姑且就这么称呼。
P 操作:检测与阻塞
V操作:唤醒
semaphore是一个整型变量,与队列有关,它的值仅能够由PV操作来改变。
semaphore分为公有和私有,公有的旗语值通常设置为1,用于实现进程间的互斥;私有的旗语值设置为0或n,用于实现进程间同步。我们会举例说明。