目录
CPU是计算机系统中最重要的硬件资源之一,CPU的使用效率将直接影响计算机系统的整体性能。现代计算机系统中,一台计算机可以同时处理多个任务,这些任务通常以进程或线程的方式组织。因此,CPU管理实际上是进程管理。掌握进程的概念对于理解操作系统的实质具有非常重要的意义,只有理解了进程,才能掌握CPU的工作原理。
2.1CPU管理
2.1.1CPU管理的功能
CPU管理的主要任务是将CPU进行分配,并对其运行进行有效的控制和管理,以高效地执行用户提交的作业。现代操作系统中,CPU是以进程为基本单位进行分配和运行的,因而CPU管理也可以视为进程管理。CPU管理主要包括以下功能。
1.进程控制
多道程序运行环境中,并发执行需要创建多个进程,并分配必要的资源。程序结束后,必须撤销这些进程,并回收所占的各类资源。进程控制的主要任务是为程序创建进程、撤销已结束的进程、分配和回收各类资源,以及控制进程在运行过程中的状态转换。
2.进程同步
并发进程通常是以异步方式工作的,并以不可预知的速度向前推进。为了使多个进程能有条不紊地运行,系统应提供同步机制,使得进程能相互协调、合作。协调方式共有两种:
(1)互斥方式:指多个进程之间排他地访问临界资源,其中临界资源是指一次只能被一个进程访问使用的资源,即当一个进程访问临界资源时,其他需要访问该临界资源的进程必须等待;仅当该临界资源被释放后,其他进程才可以访问该临界资源,即“有我没他,有他没我”。
(2)同步方式:指多个进程之间相互协调、相互合作,依次执行。即前一个进程结束了,后一个进程才能开始;前一个进程没有结束,后一个进程就不能开始。即“有你才有我,没你就没有我”。
3.进程通信
多个并发执行的进程之间经常互相配合去完成共同的任务,因此往往需要交换信息。进程通信的任务就是用来实现相互合作进程之间的信息交换。
(1)直接通信方式:源进程利用发送命令直接将消息发送到目标进程的消息队列上,然后由目标进程利用接收命令从其消息队列中取出消息。此方式适用于同一台计算机系统中相互合作的进程。
(2)间接通信方式:源进程利用发送命令将消息发送到一个专门用于存放消息的中间实体(也称邮箱)中,然后由目标进程利用接收命令从该中间实体中取出消息。此方式适用于不同计算机系统相互合作的进程。
4.进程调度
用户作业或进程必须获得CPU才能运行。等待在后备队列中的作业,根据某种调度策略,占用CPU,并执行。CPU调度包括作业调度(也称高级调度)、进程调度(也称低级调度)和中级调度(也称交换调度)。
(1)作业调度:指按照某种算法从后备队列中选择若干作业,给它们分配必要的资源,调入内存,建立相应的进程,并将其插入到就绪队列。
(2)进程调度:指按照某种算法从进程的就绪队列中选出一个进程,给它分配CPU,设其状态为运行态,使进程投入运行。
(3)中级调度:指按照某种算法将那些暂时不能运行的进程从内存中移到外存中,释放其所占资源,让其他进程运行;移到外存上的进程具备运行条件时,再按照某种算法将它们重新调入内存,等待运行。
2.1.2程序的执行
程序执行是指程序在计算机系统中的运行过程。程序的执行方式有顺序执行和并发执行两种。
1.程序的顺序执行
程序通常由若干个操作组成。程序执行时,必须按照用户编写的先后次序逐个执行操作,只有当前一个操作执行完成后,才能执行后一个操作。假设系统中有三道作业,它们均有输入、计算和打印三种顺序操作,即先输入需要的数据(I),然后进行计算(C),最后打印计算结果(P)。它们的顺序执行情况如图2-1所示。
图2-1 程序的顺序执行
首先执行第一个程序的输入、计算和打印操作,然后再进行第二个程序的输入、计算和打印操作,如此不断循环进行。当第一个程序输入时,处理器和打印机是空闲的;当处理器进行运算时,输入设备和打印设备是空闲的;当程序在打印结果时,处理器和输入设备则没事可做。显然,在这种程序运行方式下,计算机的系统资源利用效率很低。
程序顺序执行的特点:
(1)顺序性:CPU严格按照程序所规定的操作顺序执行,即前一操作执行完了,后面的操作才能开始。
(2)封闭性:程序在运行时独占系统内全部资源,其执行结果不受外界因素的影响。
(3)确定性:程序执行的结果是确定的,与执行速度和时间无关,即程序无论是从头到尾不停地执行,还是走走停停地执行,都不会影响到最终结果。
(4)可再现性:只要程序的执行环境和初始条件相同,程序无论重复执行多少次,都将获得相同的结果,即计算结果可再现。
程序顺序执行的顺序性、封闭性、确定性和可再现性可给程序的编制、调试带来很大方便,但作业的串行执行将导致计算机系统的资源利用率低下、吞吐量小。
2.程序的并发执行
为了解决程序顺序执行效率低的问题,操作系统引入了多道程序设计和并发执行的概念,以增强计算机系统的处理能力,提高各种资源的利用率。并发执行是指一个程序的执行还没结束,另一个程序的执行已经开始了。宏观上,系统在一段时间内完成或执行了多道程序或作业;微观上,在单CPU环境中(即只有一个CPU并且是单核的CPU的计算机系统)任何时刻只有一个程序获得CPU并运行。
如前所述,假设系统中有三道作业或程序,它们由输入、计算和输出这三个步骤组成。系统在处理这三道程序时,各步骤之间有时并不存在严格的执行次序,它们可以并发执行。假设它们并发执行的流程如图2-2所示。
当第1道程序的输入结束后,其计算过程可以开始。在第一道程序在计算过程中,系统的输入设备已空闲,因而可用来处理第二道程序的输入操作,即I2和C1可同时进行,使得CPU和外设并行工作。同理,P1、C2和I3也可并发执行,其他过程依次类推。这种执行过程就是程序的并发执行,即第一道程序在执行结束前,第二道、第三道也在处理过程中,它充分利用了CPU与外设并行工作的能力。
程序并发执行的特点:
(1)间断性:程序并发执行时,由于与其他程序之间共享资源或相互合作,形成了相互制约的关系,致使程序执行时具有“执行——暂停——执行”的间断性活动规律。
(2)失去封闭性:程序并发执行时,系统中各类资源被多个程序共享访问,使得程序在运行过程中将受到其他程序的影响,从而失去封闭性。
(3)不再可现性:由于失去了封闭性,因而同一个程序多次执行或以不同方式执行时,可能导致出现不同的结果。
假设系统中有两道并发执行的程序A和B,它们共享变量N,初始值为0。程序A做N=N+1操作,程序B要先打印N的值,再将N值清零。程序A和程序B执行的顺序若不相同,N的结果将产生不同的变化,如:
(1)N=N+1在print(N)和N=0之前,此时N的值分别为1、1、0.
(2)N=N+1在print(N)和N=0之间,此时N的值分别为0、1、0.
(3)N=N+1在print(N)和N=0之间,此时N的值分别为0、0、1
引入并发的目的是为了提高CPU等资源的利用率和系统的处理能力,进而提高系统效率,但是可能引起程序结果的不可再现性,因此,必须采用某种措施,使并发程序能保持其结果的可再现性。
1966年,Bernstein提出了程序并发执行的条件,称为Bernstein条件,以保证并发程序结果的可再现性。该条件是指若干个进程分别对不同的变量集合进行操作,则这些进程可以并发执行。
Bernstein条件:给定并发程序Pi,R(Pi)和W(Pi)表示Pi在执行期间所读取和改变的变量集合。如果并发执行的程序P1和P2满足,那么P1、P2可以并发执行,且不会影响最终结果。
值得注意的是,Bernstein条件在理论上可以保证程序能够并发执行,但在实际情况中,进程之间由于共享某些资源,经常不满足Bernstein条件,尽管它们在理论上不能并发执行,但是只要采取适当的措施,它们还是可以正确、安全地并发执行。
2.2进程的概念
多道程序环境下,程序的执行是动态变化的,在系统中处于“走走停停、停停走走”的运动状态。为了使程序能够并发执行,并能够如实反映程序活动的动态特征,操作系统引入了进程,以对并发执行的程序加以控制和描述。计算机系统中CPU是以进程为基本单位进行分配和管理的。
2.2.1进程的定义
进程的概念是20世纪60年代初期,首先由麻省理工学院的MULTICS系统IBM公司的CTSS/360系统中引入并实现的。其后,人们对它不断加以改进,从不同的方面对它进行描述。一般而言,进程是指一个具有独立功能的程序在某个数据集上的一次运行过程,它是系统资源分配和调度的基本单位。
进程和程序是两个截然不同的概念,两者的区别如下:
(1)程序是静态的,它由用户编写的若干代码的集合,可作为资料长期保存;进程是动态的,它是程序在系统中的一次运行过程。
(2)进程和程序并非一一对应,同一个程序可以由多个进程分别执行,这些进程虽然执行相同的程序,但处理不同的数据;同样,一个进程通过程序间的调用方式,会涉及多个程序。
它们之间的关系类似于菜谱和炒菜,其中程序相当于菜谱,而进程就是每一次按照菜谱炒菜的过程。
2.2.2进程的特征
进程具有以下5个基本特征:
(1)动态性:进程是程序在CPU上的一次执行过程,它具有一定的生命周期,其状态也会不断发生改变,表现为“因创建而产生,因调度而执行,因得不到资源而暂停,因撤销或完成而消亡”。
(2)并发性:多个进程同时存在于内存中,在一段时间内交替使用CPU,同时运行。并发性是进程也是操作系统的重要特征。
(3)独立性:进程实体是一个能独立运行的基本单位,同时也是独立获得资源和独立调度的基本单位。
(4)异步性:系统中的进程按照各自独立的、不可预知的速度向前推进。
(5)结构性:进程实体具有一定的结构,它由程序段、数据段、和进程控制块组成。
2.3进程的状态
2.3.1进程的基本状态
由于共享系统中的资源,因此进程之间相互制约、相互依赖,其整个生命周期呈现为“运行——暂停——运行”。进程在其生命周期中创建、就绪、运行、阻塞、终止这五种状态。
(1)创建态:指进程正在被创建或刚刚创建完成,但还没有放入就绪队列之前的状态。
(2)就绪态:指一个进程获得了除CPU以外的其他所需资源,一旦获得CPU后便可运行的状态。就绪队列是指将系统中所有处于就绪状态的进程,排成一个或多个队列。
(3)运行态:指进程正在CPU上运行时的状态。单CPU环境中,某个时刻最多只有一个进程处于运行态;而多CPU环境中,可能有多个进程同时处于运行态。
(4)阻塞态(也称等待态)指正在运行的进程由于发生某些事件(如输入/输出请求、申请额外资源等)暂时无法继续执行的状态,即进程的运行受到了阻塞。阻塞(等待)队列是指系统中所有处于阻塞态的进程,组织成一个或多个队列。
(5)终止态:指一个进程正常结束或异常被终止,但该进程所拥有的资源(如进程控制块PCB)还未完全被撤销时的状态。
2.3.2进程的状态转换
进程最初始于创建态,在随后的推进过程中,将在就绪态、运行态和阻塞态之间相互转换,最后结束于终止态。
进程的创建过程由多个步骤组成:首先申请一个空白进程控制块,并填写用于控制和管理进程的信息;然后为该进程分配必要的资源;最后将该进程插入就绪队列,其状态也转换为就绪态。如果在创建过程中,进程所需的资源不能得到满足,导致创建未完成,进程不能被调度运行,此时进程所处的状态称为创建态。操作系统初始化时,创建第一个进程,然后由该进程不断地创建其他进程,此外,其他进程也可以通过系统调用方式,创建新的子进程,从而形成进程间的层次体系,称为进程树或进程家族。
进程自然结束或被其他有终止权的进程所终结时,将进入终止态。进入终止态的进程以后不能再执行,但系统暂时为其保留相关状态和计时统计数据,供其他进程调用。一旦其他进程提取了信息后,系统将删除该进程(即清空进程控制块),并将其所占用的空间返给系统。
进程在推进过程中的状态转换过程如图所示2-3.
图2-3进程状态的变化
(1)NULL→创建态:程序执行时,先创建一个新的进程。
(2)创建态→就绪态:进程创建并获得了除CPU外其他相关资源后,将被移至就绪队列,此时处于就绪态。
(3)就绪态→运行态:处于就绪态的进程被进程调度程序按某种调度算法选中后,被分配CPU上运行,此时,该进程的状态就由就绪态转变为运行态。
(4)运行态→阻塞态:正在运行的进程由于等待某个事件(如I/O请求或等待某个资源)的发生而无法继续运行,只好暂停运行,此时进程就由运行态转变为阻塞态。
(5)阻塞态→就绪态:处于阻塞队列中的进程,如果所需要的资源得到满足或完成I/O响应,将会被唤醒,重新回到就绪队列,等待下一次调度。
(6)运行态→就绪态:正在运行的进程由于系统分配给它的时间片用完结束,或因优先级较低而暂停运行,重新回到就绪队列,等待下一次调度。
(7)运行态→终止态:正在运行的进程由于自然结束或因执行错误而陷入内核,而结束运行并作结束处理。
2.3.3进程的挂起状态
为了更有效地使用系统有限的资源,部分现代操作系统中引入了挂起状态。进程被挂起意味着该进程处于静止状态。此时,若进程正在执行,则将暂停执行;若进程处于就绪态,则挂起后该进程暂时不接受调度。引起挂起状态主要是基于下列需求:
(1)系统需求:系统运转过程中,有时需要挂起某些进程,检查资源的使用情况,以便调整系统负荷,改善系统运行性能;或是系统在出现故障或受到破坏时,需要挂起某些进程,以排除故障。
(2)父进程需求:父进程需要考察或修改子进程,或者协调各个子进程之间的活动,要求挂起自己的子进程。
(3)用户需求:用户在运行期间发现可疑问题时,要求挂起自己的子进程以便进行某些程序的调试,检查和改正。
(4)对换需求:系统为了缓和内存和其他资源的紧张情况,将处于等待状态的进程挂起,并将它们从内存换出到外存,腾出内存空间给其他进程。
引入挂起状态后,若进程被挂起,则处于静止状态;反之,若未被挂起,则处于活动状态。进程的状态转换情况如图2-4所示,其中除上节转换外,还增加了以下几种状态转换。
(1)创建→活动就绪:系统完成进程创建的必要操作后,在性能和内存容量许可的情况下,将该进程的状态转换为活动就绪状态。
(2)创建→静止就绪:系统完成进程创建的必要操作后,若性能和内存容量不许可,则不分配给该进程所需资源,并将该进程存放在外存,其状态转换为静止就绪状态。
(3)活动就绪→静止就绪:系统使用挂起命令,将(活动)就绪队列中的某些进程挂起,这些进程处于静止就绪状态,暂时无法被调用执行。
(4)活动阻塞→静止阻塞:系统使用挂起命令,将(活动)阻塞队列中的某些进程挂起,这些进程就处于静止阻塞状态,当这些进程在其所期待的事件出现后,则将从静止阻塞变为静止就绪。
(5)静止就绪→活动就绪:处于静止就绪状态的进程被使用激活命令激活后,将变为活动就绪状态。
(6)静止阻塞→活动阻塞:处于静止阻塞状态的进程被使用激活命令后,将变为活动阻塞状态。
2.4进程的描述
2.4.1进程结构
进程是程序的一次运行过程,它是由程序段、数据段和进程控制块(PCB-Processing Control Block)组成的一个实体,其中:
(1)程序段:对应程序的操作代码部分,用于描述进程所需要完成的功能。
(2)数据段:对应程序执行时所需要的数据部分,包括数据、堆栈和工作区。
(3)进程控制块:记录进程运行时所需要的全部信息,它是进程存在的唯一标识,与进程一一对应。
2.4.2进程控制块
进程控制块(PCB)是进程实体的重要组成部分,它记录了操作系统所需要的、用于描述进程情况及控制进程运行所需要的全部信息。原来不能独立运行的程序或数据,通过PCB就可成为一个可以独立运行的基本单位。系统通过PCB感知进程的存在,并对其进行有效管理和控制。系统创建一个新进程时,为它建立一个PCB;当进程结束时,为它建立一个PCB;当进程结束时,系统又回收其PCB,该进程也随之消亡。
进程控制块主要包括下述四个方面的信息:
(1)进程标识信息:用于标识、区分一个进程,通常有外部标识符和内部标识符两类。外部标识符通常由字母、数字所组成的一个字符串,用户或其他进程访问该进程时使用。内部标识符是操作系统为每个进程赋予的唯一一个整数,是作为内部识别而设置的。
(2)进程调度信息:用于描述与进程调度有关的状态信息,包括进程状态、进程优先权、调度信息和等待事件等。进程状态指明进程当前的状态,作为进程调度和对换时的依据;进程优先权说明进程使用CPU的优先级别,其中优先权高的进程将优先获得CPU;调度信息描述与进程调度算法相关的信息,如进程等待时间、已运行的时间等;等待事件是指进程由运行态转变为阻塞态所等待发生的事件。
(3)CPU状态信息:用于保留进程运行时CPU的各种信息,使得进程暂停运行后,下次重新运行时能从上次停止的地方继续运行。CPU状态信息通常包括通用寄存器、控制和状态寄存器、用户栈指针等。CPU状态字记载了程序执行的状态信息,如条件码、外中断屏蔽标识、执行状态(核心态或用户态)标识等。
(4)进程控制信息:包括进程资源、控制机制等一些进程运行时所需要的信息,如:
①程序和数据地址:指该进程的程序和数据所在的内存和外存地址,以便该进程再次运行时,能够找到程序和数据。
②进程同步和通信机制:指实现进程同步和通信时所采用的机制,如消息队列指针、信号量等。
③资源清单:指除CPU外,进程所需的全部资源和已经分配到的资源。
④链接指针:用于指向该进程所在队列的下一个进程的PCB首地址。
2.5进程的组织
多道程序设计环境中,系统通常拥有数十个、数百个乃至数千个进程。为管理方便,系统将处于相同状态的进程组织在一起,形成一个或多个队列,以节省系统查找进程的时间。进程的组织结构如图2-5所示。
如前所述,系统是通过PCB感知进程的存在,且每个进程都有唯一的PCB。由于PCB进程被系统访问,因此常驻内存。为了有效地管理系统中数量众多的PCB,系统必须采取适当的方式将它们组织在一起。常用的进程组织方式有线性表、链表、索引方式。
图2-5 进程状态变化的实现
1.线性表方式
系统按照进程号或进程创建的先后顺序,而不管其处于何种状态,将所有进程的PCB组织成一个线性表,其中该表的首地址存放在内存的一个专用区域,如图2-6所示。
线性表组织方式的特点:实现简单、开销小,但每次查找时都需要查找整张表格,因而费用较高,仅适合进程数量不多的系统。
图2-6 PCB线性表组织方式
2.链接方式
系统采用链接指针方式,将具有相同状态进程的PCB链接成队列,如就绪队列、阻塞队列、空闲队列等。每个队列由一个头指针指向队列的第一个PCB,其组织方式也采取不同车略。例如,就绪队列中的进程可按优先级高低的方式进行排列,优先级最高的进程其PCB排在队首;根据阻塞的原因不同,将处于阻塞态的进程PCB排成等待I/O队列、等待分配内存队列等;将系统内存的PCB区域中所有空闲空间排除空闲队列,以方便PCB的分配与回收。链表队列的组织方式如图2-7所示。
图2-7 PCB链表组织方式
3.索引方式
系统根据各个进程的不同状态,建立相应的索引表,其中具有相同状态的进程组织成一个索引表,如就绪索引表、阻塞索引表、空闲索引表等,再由头指针指向各个索引表。每个索引表的标目中记录了具有相同状态的各个PCB在内存中的地址。索引表的组织方式如图2-8所示。
图2-8索引组织方式
2.6进程的控制
进程控制的主要任务是为作业程序创建进程,撤销已结束的进程,以及控制进程在运行过程中的状态转换,从而达到进程高效执行和协调工作、实现资源共享的目的。
2.6.1操作系统内核
进程控制一般是由操作系统内核中的原语来实现的。现代操作系统的层次结构设计中,与硬件紧密相关的模块、各种常用设备的驱动程序以及运行频率较高的模块,通常都安排在紧靠硬件的软件层次中。它们常驻内存,因而被称为操作系统内核。操作系统内核的基本功能包括两个方面:一是系统支撑功能,包括中断处理、时钟管理和原语操作等;二是资源管理功能,包括进程管理、存储器管理和设备管理等。
如前所述,为了防止操作系统本身及其关键数据被破坏,CPU的执行状态通常分成系统态(管态)和用户态(目态)两种。系统态具有最高的特权,能执行一切指令,能访问所有的寄存器和存储区;用户态具有较低特权的执行状态,仅能运行规定的指令,访问指定的寄存器和存储区。通常情况下,用户程序或应用程序只能在用户态运行,既不能执行操作系统指令,也不能访问操作系统区,以防止应用程序对操作系统的破坏。
2.6.2进程控制原语
原语是指由具有特定功能的、执行过程中不可被中断的指令集合。原语是一个不可分割的基本单位,它只能顺序执行,不能并发执行。原语与系统调用都是通过使用访管指令来实现,但它们是两个不同的概念,区别主要在于:原语是由操作系统内核实现的,而系统调用是由系统进程或系统服务程序实现的;原语在执行过程中不可被中断,而系统调用执行时允许被中断。
用于进程控制的原语主要有:进程的创建、撤销、阻塞、唤醒以及挂起和激活原语。
1.进程创建
程序在运行之前,必须先创建相应的进程。创建进程的目的是为一个程序建立一个进程控制块,并为它分配地址空间。
引起进程创建的事件主要有以下四类:
(1)用户登录:分时系统中,用户输入登录命令后,若为合法用户,系统将为该用户建立一个进程。
(2)作业调度:批处理系统中,当作业调度程序按某种算法调度某个作业时,便将该作业装入内存,分配必要的资源,并为它创建进程。
(3)提供服务:当运行中的用户进程提出某种请求(如打印文件)后,系统将专门创建一个进程,以提供用户所需要的服务。
(4)应用请求:应用进程根据自己的需要,创建一个新的子进程。
系统获取创建进程的需求后,调用进程创建原语,按照下列步骤创建一个新的进程:
(1)为新进程分配唯一的进程标识符,并从PCB队列中申请一个空闲的PCB。
(2)为新进程分配必要的内存空间和其他各种资源。
(3)初始化PCB中的相应信息,如标识信息、CPU信息、进程控制信息。
(4)若条件许可,将新进程的PCB插入到就绪队列中。
2.进程撤销
当一个进程正常运行结束或者在运行过程中出现了异常或故障时,系统或该进程的父进程需要调用进程撤销原语,回收其所占用的内存,释放相应的资源,撤销该进程的PCB。进程在被撤销时,其子进程也应被撤销。引起进程撤销的事件主要有三类:进程正常运行结束、进程出现异常错误(如执行了非法指令、算法运算错误、地址越界、I/O故障等)和进程应外界请求而终止运行。
系统获取撤销进程的请求后,调用进程撤销原语,按照下列步骤撤销一个进程:
(1)根据被撤销进程的标识符,从相应的PCB队列中寻找到该进程的PCB,获取该进程的状态以及资源占用情况。
(2)若该进程处于运行态,则立即终止该进程的运行。
(3)若该进程有子孙进程,则还要终止其子孙进程。
(4)释放并回收该进程所占有的全部资源,将资源归还给父进程或操作系统。
(5)将被撤销进程的PCB从所在队列中移出,撤销该进程的PCB,并将其加入到空闲PCB队列中。
3.进程阻塞
正在运行的进程,由于发生等待事件(例如等待I/O,等待其他进程发来的消息)而不能继续运行下去时,需要调用阻塞原语阻塞自己。引起进程阻塞的事件主要有四类:请求系统服务、启动某种操作、新数据尚未到达和无新工作可做。
系统获得阻塞进程的请求后,调用阻塞原语,按照以下步骤阻塞指定的进程:
(1)立即停止执行该进程。
(2)修改该进程PCB的相关信息,如将运行状态变为阻塞状态,并指出阻塞的原因。
(3)将修改后的PCB插入到对应的阻塞队列。
(4)转入进程调度程序,重新调度就绪队列中的其他就绪进程。
4.进程唤醒
当阻塞队列中的进程所等待的事件发生了,系统调用阻塞原语,唤醒由于等待该事件而进入阻塞状态的进程。系统将被唤醒的进程从该阻塞队列中移出,并插入到就绪队列。阻塞和唤醒原语的作用正好相反:进程由于等待某事件的发生而调用阻塞原语进行阻塞,若事件已发生,则需使用唤醒原语将其唤醒,否则该进程就永远处于阻塞状态。引起进程唤醒的事件主要有四类:请求系统服务得到满足、启动某种操作已完成、新数据已经达到和有新工作可做。
系统获得唤醒进程的请求后,调用进程唤醒原语,按照下列步骤唤醒指定的进程:
(1)根据事件原因,从相应的阻塞队列中找到该进程的PCB。
(2)将该进程从阻塞队列中移出。
(3)修改该进程的PCB,并将进程状态由阻塞改为就绪。
(4)将修改后的PCB插入到就绪队列。
5.进程的挂起
系统中若出现了引起挂起事件,则利用挂起原语将指定的进程挂起,将其暂停运行,并将该进程由活动状态改为静止状态,其PCB也相应地换到外存的对换区中。引起进程挂起的事件主要有四类:系统需求、父进程需求、用户需求和对换需求。
系统获得挂起进程的请求后,调用进程挂起原语,按照下列步骤挂起指定的进程:
(1)根据事件原因,从相应队列中查找并获得该进程的PCB。
(2)检查要被挂起进程当前的状态,并进行相应处理:若该进程正处于运行态,则停止运行,修改其状态为静止就绪;若该进程为活动阻塞状态,则将其状态改为静止阻塞,并插入到相应的阻塞队列;若该进程为活动就绪状态,则将其状态改为静止就绪状态,并插入到相应的静止就绪队列。
(3)将被挂起进程的PCB非常驻内存部分交换到磁盘对换区。
6.进程的激活
当挂起事件已结束,如内存资源充裕或进程请求激活指定进程等,系统或有关进程调用激活原语将指定的进程由静止态激活为活动态,并将其从静止队列中移出,重新插入到活动状态队列。激活原语与挂起原语的作用正好相反:进程由于需要而调用挂起原语,暂停运行或调度,若挂起事件已结束,则需要使用激活原语将其激活,以便重新调用或运行。
系统获得激活进程的请求后,调用激活原语,按照下列步骤激活指定的进程:
(1)根据激活事件,从相应队列中查找并获得被激活进程的PCB。
(2)根据被激活进程的状态,进行相应处理:若该进程的状态为静止阻塞,则将其状态修改为活动阻塞,并插入相应的活动阻塞队列;若状态为静止就绪,则修改为活动就绪,并插入活动就绪队列。
2.7线程
自20世纪60年代引入进程以来,它已是操作系统中最重要、最基本的概念。随着计算机技术的发展和应用的深入,传统的进程概念已经越来越不适应新的需求了,特别是计算机网络、数据库以及并行技术的发展,使得进程的局限性越来越明显。20世纪80年代,人们又提出了比进程更小的、能独立运行的基本单位——线程,以进一步改善系统性能。现在多线程技术作为一项重要的技术,除了应用于操作系统(如Windows、Linux、Solaris和OS/2等)中,在计算机网络、数据库管理系统以及应用软件中也有着广泛的应用。
2.7.1线程的引入
进程由进程控制块、程序块、数据块和堆栈组成。进程创建后,系统需分配该进程基本的内存空间以及所需要的其他各种外围设备资源和软件资源等。随着计算机技术的发展,基于进程的并发程序设计存在一定的效率问题:
(1)进程粒度大、切花开销高:作为资源分配和调度的基本单位,进程状态的频繁切换,以及线程保护和恢复将浪费大量的CPU时间。此外,系统内存空间的容量也限制了可容纳进程的总数。
(2)进程的并发程度不高:进程包含信息较多、粒度太粗,导致其切换频率不宜太高,从而限制了进程的并发程度。此外,进程的切换、进程之间的通信等开销较大,导致进程不适合并行计算、分布式计算机的要求。
为了解决进程所带来的上述问题,人们将进程的两个属性(“独立分配资源”与“被调度执行”)分离,即作为调度和分配的基本单位,不能同时作为独立分配资源的单位;而对于拥有资源的单位,不必频繁切换,进而提出了线程的概念。
1.线程的概念
线程是系统独立调度和CPU分配的最小单位,它是进程中的一个实体,除拥有运行中必不可少的资源(程序计数器、寄存器和栈等)外,不拥有其他系统资源,故而又称轻量级进程。尽管线程不拥有系统资源,但它可与同属一个进程的其他线程一起共享该进程所拥有的全部资源。
多线程环境下,进程是系统进行资源分配的基本单位,仍然有一个进程控制块和用户地址空间(如CPU、I/O资源、文件以及其他资源等)。线程是CPU调度和分派的基本单位,拥有自己独立的堆栈和线程控制块,它是进程的组成部分,且能在进程中并发执行。线程和进程是两个既相互联系又相互区别的概念,具体介绍如下:
(1)划分尺度:线程是进程的一个执行单元,因而粒度更小。
(2)资源分配:进程是资源分配的基本单元,而线程不拥有系统资源,此外,同一个进程内多个线程可共享该进程的资源。
(3)地址空间:进程拥有独立的地址空间,而线程没有独立的地址空间,但它与其他线程一起共享其所属进程的地址空间。
(4)CPU调度:线程是CPU调度的基本单位。
(5)并发执行:一个进程可包含多个线程,但每个线程只能属于一个进程,因而线程并发程度更高。
每个进程可以包含多个线程,它们共享所属进程所拥有的资源及地址空间,因而可访问相同的数据。进程与线程之间的关系如图2-9所示。
由此可见,线程可以大大减少程序并发执行时所付出的时间和空间开销,从而极大地提高了系统效率。
图2-9 多线程进程模型
2.线程的状态
线程与进程类似,在整个运行期间具有三种状态:
(1)就绪态:指线程已经具备了各种执行条件,若获得CPU便可以立即执行。
(2)运行态:指线程已经获得了CPU,并处于执行过程中。
(3)阻塞态:指线程在执行中,因某事件出现而受到阻塞,处于暂停执行状态。
线程状态之间的转换和进程状态之间的转换相同。由于线程不是资源的拥有单位,因此没有挂起状态。此外,若进程由于系统性能而被挂起,则它所包含的所有线程都必须对换出去。
3.线程控制块
在结构组成方面,线程由线程控制块、用户堆栈、系统堆栈以及一组CPU状态以及一组CPU状态寄存器和有一个私用内存存储区组成。线程控制块是线程是否存在的唯一标志,它通常包括线程标识符、一组寄存器(程序计数器,状态寄存器和通用寄存器)、线程运行状态、优先级、线程专有存储区(用于线程切换时存放现场保护信息等)、信号屏蔽、堆栈指针等。
2.7.2线程的类型
根据切换操作是否依赖内核,线程可分为三类:用户级线程、内核级线程和混合型线程。
1.用户级线程
用户级线程是指线程的所有管理和控制任务全部由应用程序来完成,在用户空间内实现,并由线程库来支撑。线程库是用户级线程管理的例行程序包,它包含了用于创建和撤销线程的例程、在线程之间传递消息和数据的例程、线程调度以及保存和恢复线程的代码。
用户级线程的主要优点:
(1)线程切换开销小:由于所有用户级线程的管理都在用户地址空间的进程内进行,而不需要再系统态和用户态之间转换,因而节省了模式切换的开销,减轻了系统的开销及负担。
(2)管理控制方便:用户级线程属于应用程序,因而应用程序可以更加灵活地管理、控制线程,甚至可以根据需要来设定线程的调度算法、优先级等。
(3)健壮、实用性强:用户级线程在用户空间运行,其创建、撤销和切换均由自己的线程库实现,因而可在各种操作系统中运行。
用户级线程的主要缺点:
(1)当某个线程被阻塞时,其所属进程中的其他线程也会被阻塞,导致系统效率较低。
(2)相同进程中多个线程不能真正并行,因为CPU一次只能分配给一个进程,且只有其中一个线程可以执行。因此,多CPU环境下,即使其他CPU空闲,该进程中的其他线程也不能执行。
2.内核级线程
内核级线程由操作系统直接支持,其创建、调度和管理都依赖于系统内核,由内核来实现。应用程序若需要使用线程,则必须通过调用内核提供的应用程序接口来实现。目前,大多数现代操作系统如Windows、Mach和OS/2等实现的都是内核级线程。
内核级线程的主要特点:
(1)同一个进程内的多个线程可以并行执行,如果进程中的一个线程被阻塞,内核既可以调用相同进程中的其他线程运行,也可以调度其他进程中的线程运行。
(2)内核线程具有很小的数据结构和堆栈,且切换速度块,从而大大地提高了操作系统的性能和效率。
(3)多CPU环境中,内核可同时将一个进程的多个线程分配到多个CPU执行。
由于内核级线程的管理和调度均在系统内核(系统态)中进行,而应用程序则在用户态下运行,因此,同一个进程中的线程切换经常会引起从用户态到系统态、从系统态再到用户态之间的转换,从而导致系统内核的开销和负担较重。
3.混合型线程
用户级线程和内核级线程各有优缺点,为此,SUN公司在Solaris操作系统中综合了两者的特点,提出了混合式线程,它同时实现了用户级线程和内核级线程。混合式线程环境中,系统内核支持对线程的管理,同时也提供线程库,使得用户也可以建立、调度和管理用户级线程。这种情况下,一个用户应用程序中的多个线程既可以在多处理器上并行运行,同时阻塞一个线程也不需要封锁整个进程。