3. 进程与线程
3.1 进程的概念
3.1.1 多道程序设计
多道程序同时进入内存并运行,其目的是为了提高系统效率,但是伴随而来的程序的并发执行和系统资源的共享使得采用多道程序技术的操作系统工作变得更复杂,不像单道程序系统那样简单、直观。
并发环境是指在一段时间间隔内,单处理器上有两个或两个以上的程序同时处于开始运行但尚未结束的状态并且次序不是事先确定的。并发程序是指在并发环境中执行的程序。
3.1.2 进程
1. 进程的概念
进程(process)是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单元。
进程与程序的区别:
1)程序是永存的;进程是暂时的,是程序在数据集上的一次执行,有创建有撤销,存在是暂时的;
2)程序是静态的观念,进程是动态的观念;
3)进程具有并发性,而程序没有;
4)进程是竞争计算机资源的基本单位,程序不是。
5)进程和程序不是一一对应的: 一个程序可对应多个进程即多个进程可执行同一程序; 一个进程可以执行一个或几个程序;
2. 进程的基本特征
1)动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
2)并发性:任何进程都可以同其他进程一起并发执行。
3)独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。
4)异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。
3.2 进程的状态与转换
进程的三种基本状态:运行状态、就绪状态、阻塞状态。
运行状态(running):运行状态是指当前进程占有CPU,并在CPU上运行。
就绪状态(ready):就绪状态是指进程已经具备运行条件,但由于没有空闲CPU,暂时不能运行。
阻塞状态(blocked):阻塞状态又称等待状态或封锁状态,是指进程因等待某一事件而暂时不能运行。处于阻塞状态的进程不具备运行条件,即使CPU空闲,它也无法运行。
进程的其他状态:
新建(new):已完成创建进程所必要的工作,但尚未同意执行该进程。
终止(terminated):终止执行后,进程进入该状态。
3.3 进程的控制
3.3.1 进程控制块
进程控制块(Processing Control Block),也称进程描述块(Process Descriptor),是操作系统核心中一种数据结构,主要表示进程状态。在创建进程时,首先建立PCB,它伴随进程运行的全过程,直到进程撤销而报销。系统可以利用PCB来控制和管理进程,所以说,PCB(进程控制块)是系统感知进程存在的唯一标志。
进程控制块的组成一般包括:进程描述信息、进程控制信息、所拥有的资源和使用情况、CPU现场信息。
1)进程描述信息:进程标识符(process ID)、进程名、用户标识符(user ID)、进程组关系。 每个进程都必须有一个标识符,通常是一个整数。
2)进程控制信息:当前状态、优先级(priority)、程序的磁盘地址、代码开始地址、进程队列指针、通信信息。
3)所拥有的资源和使用情况:虚拟地址空间的状况、打开文件列表
4)CPU现场信息:寄存器值(通用寄存器、程序计数器PC、程序状态字PSW、栈指针)、指向该进程页表的指针
PCB是一个通用的名称,在Linux操作系统中进程控制块叫task_struct。
3.3.2 进程的控制
进程是有生命周期的,这一过程包括进程的产生、运行、暂停、终止。对进程的这些操作称为进程控制。进程控制包括进程创建、进程撤销、进程阻塞、进程唤醒、改变进程优先级、调度进程运行。这些操作都要对应地执行一个特殊的程序段(操作系统核心程序),同时系统也通过系统调用给用户提供进程控制的功能。完成进程控制的这种特殊的系统调用,我们把它成为原语。实际上它是一种特殊的系统调用命令,执行时是不可中断的。共有4中原语,分别为进程阻塞、进程唤醒、进程创建、进程调度。
1. 进程的创建
进程创建的过程:
1)给新进程分配一个唯一标识以及进程控制块
2)为进程分配地址空间
3)初始化进程控制块。
4)设置相应的队列指针。如把新进程加到就绪队列中
在Linux系统中使用fork/exec来创建新进程,在Windows中使用createProcess来创建新进程。
2. 进程的撤销
进程撤销的过程:
1)收回进程所占有的资源,如关闭打开的文件、断开网络连接、回收分配的内存
2)撤销该进程的PCB
3. 进程的阻塞
进程阻塞的过程:
1)停止当前进程的执行
2)现行进程的CPU现场保存
3)现行状态由“运行”改为“阻塞”
4)转到进程调度程序
4. 进程唤醒
进程唤醒的过程:
1)把阻塞进程从相应的阻塞队列中摘下
2)将现行状态改为就绪状态,然后把该进程插入就绪队列中
3)如果被唤醒的进程比当前运行进程的优先级更高,则重新设置调度标志。
UNIX系统中的几个进程控制操作:
fork():通过复制调用进程来建立新的进程,是最基本的进程建立过程。
exec():包括一系列系统调用,它们是通过用一段新的程序代码覆盖原来的地址空间,实现进程执行代码的转换。
wait():提供初级进程同步操作,能使一个进程等待另外一个进程的结束。
exit():用来终止一个进程的执行。
3.4 线程
3.4.1 线程的概念
1. 线程概念的引入
进程是资源的拥有者,同时也是CPU调度的基本单位,这双重身份使得在进程创建、撤销以及状态转换中,系统要为之付出较大的时间和空间开销。因为上述原因,系统中所设置的进程数目不宜过多,进程切换频率也不宜太高,但这样限制了进程并发程度的进一步提高。
现代操作系统中把资源分配和调度分离开来,把进程作为资源分配的单元,把线程作为系统调度的单位。线程只拥有一些在运行时必不可少的资源(如程序计数器、一组寄存器和栈),它与同属一个进程的其他线程共享该进程拥有的全部资源。
所以说线程是进程中的一个运行实体,是CPU的调度单位,即在同一进程中增加了多个执行序列(线程),有时将线程称为轻量级进程。
2. 线程的状态
每个线程有一个thread结构,即线程控制块(简称TCB),用于保存自己的私有信息,主要包括:状态和调度信息、线程标识信息、现场信息、线程私有存储区、指针(指向TCB)。
进程产生的同时产生第一个线程,其他线程在以后由任一线程请求创建。与进程一样,除了新建状态和终止状态,线程创建后运行过程中3个主要状态,分别是运行、就绪、阻塞。
3.4.2 线程与进程的比较
1. 调度单位
传统操作系统中,拥有资源的基本单位和独立调度分派的基本单位都是进程,在引入线程的操作系统中,进程只作为资源分配的基本单位,线程则作为调度和分派的基本单位。
2. 并发性
在引入线程的操作系统中,不仅进程之间可以并发执行,作为比进程更小的执行单位,一个进程中的多个线程之间也可以并发执行。
3. 拥有资源
传统的操作系统中,进程是拥有资源的独立单位。在多线程环境中,进程仍然有一个进程控制块和用户地址空间。线程本身基本上不拥有资源,只拥有少量必不可少的资源。线程具有共享性,属于同一进程的线程共享进程的资源。
4. 系统开销
由于创建或撤销进程时,系统都要为之分配或回收资源,操作系统所付出的时间和空间开销将显著地大于重建或撤销线程的开销。进程切换涉及当前进程CPU环境的保存及新被调度运行的进程CPU环境的设置,包括程序地址和数据地址等。而线程的切换只需保存和设置少量寄存器的内容。线程之间的切换比进程之间的切换花费的时间要少。由于同一进程中多个线程具有相同的地址空间,同一进程中的线程共享存储空间和文件,它们无需内核的支持就可以互相通信。
3.4.3 线程的实现
1. 用户级线程
用户级线程只存在于用户级,线程的创建、撤销及切换都不利用系统调用实现,因而这种线程与内核无关,内核也不知道这种线程的存在。内核是以进程为单位,实现进程状态的转换,所以同一进程的线程之间的切换在用户空间实现,内核并不知道用户空间线程的活动。
用户级线程由用户空间运行的用户级线程库实现,任何应用程序通过线程库进行程序设计。用户级线程库是线程运行的支撑环境。线程库是用于管理用户级线程的可以被所有系统共享的应用级实用程序。
用户级线程的优缺点:
优点:
1)线程切换不需要内核特权方式,所以线程之间切换速度快
2)调度算法是应用程序特定的
3)用户级线程可以运行在任何操作系统上(只需要实现线程库)
缺点:
1)内核只将处理器分配给进程,所以同一进程的两个线程不能同时运行于两个处理器上。
2)大多数系统调用是阻塞的,因此,由于内核阻塞进程,故进程中所有线程也被阻塞。
2. 内核级线程
内核级线程的线程管理有操作系统内核在内核空间实现,如线程创建、结束、同步等系统调用。内核调度以线程为单位。
内核为应用程序开发者提供了一个应用程序设计接口API,应用程序通过调用API函数,实现线程的创建和控制管理。除了API函数调用外,应用程序区不需要有任何线程管理的其他代码。
内核级线程的优缺点:
优点:
1)在多处理器上,同一进程内线程可以并发执行;
2)如果进程中的一个线程阻塞,内核能够调度同一进程内的其他线程占有处理器;
缺点:
1)当对线程的控制需要从一个线程传送到另一个线程时,需要经过用户态到和内核态,再从内核态到用户态的模式切换,系统开销较大。
3.混合式线程
线程创建在用户空间完成,线程调度在内核态完成。