主要内容
进程概念的引入
问题:采用一个什么样的概念来描述计算机程序的执行过程和作为资源分配的基本单位,才能充分反映操作系统的执行并发、资源共享及用户随机的特点?
程序的概念
程序(program)描述计算机所要完成的具有独立功能的,并在时间上按严格次序前后相继的计算机操作序列集合,是一个静态的概念。
单道程序的顺序执行
我们把一个具有独立功能的程序独占处理机直至最终结束的过程称为程序的顺序执行。
特点:
(1)顺序性:每执行一条指令,系统将从上一个执行状态转移到下一个执行状态,且上一条指令的执行结束是下一条指令执行开始的充要条件。
(2)封闭性:程序执行得到的最终结果由给定的初始条件决定,不受外界因素的影响。
(3)可再现性:只要输入相同的初始条件,无论何时重复执行该程序都能得到相同的结果。
多道程序的并发执行
实际上,计算机经常需要同时处理多个具有独立功能的程序。上一篇简单介绍过的批处理系统、分时系统和实时系统都是这样的系统。
特点:
(1)独立性:每道程序在逻辑上都是独立的,不存在制约关系。
(2)随机性:程序的执行和数据的输入开始时间都是随机的。
(3)资源共享性:资源包括硬件资源和软件资源。资源共享将导致对进程执行速度的制约。
并发执行使为了增强计算机系统的处理能力和提高资源利用率所采取的一种同时操作技术。
程序的并发执行可分为两种:
1)多道程序系统的程序执行环境变化所引起的多道程序的并发执行。(有点啰嗦...)
2)某道程序的几个程序段包含着一部分可以同时执行或顺序可以颠倒执行的代码,即两段没有逻辑先后顺序的代码。
并发执行的影响
程序的并发执行充分利用了系统资源,从而提高了系统的处理能力,这是并发执行好的一方面。然而资源有限,程序的并发执行必然导致资源共享和竞争,从而改变程序的执行速度。当某一段代码的执行速度受到影响,自然会产生一系列连锁反应。
例如在栈的入栈和出栈操作中,若采用顺序执行,要么是先有数据入栈,再有数据出栈,要么就是反过来,执行过程十分严谨。若采用并发执行,入栈和出栈就有可能出现问题。譬如出栈开始执行时,入栈也刚要开始执行,出栈操作占用了处理机,入栈操作却还未放入栈顶元素,出栈操作自然也无法顺利进行。
为了控制和协调各程序执行过程中的软、硬件资源的共享和竞争,显然需要一个描述各程序段执行过程和共享资源的基本单位。
由于程序的顺序性、静态性和独立性,用程序段作为描述其执行过程和共享资源的基本单位既增加操作系统设计和实现的复杂度,也无法反映操作系统所应该具有的程序段执行的并发性、随机性以及资源共享等特性。(balbala长篇大论)
所以用程序来作基本单位是不合适的。
进程的定义
进程是一个动态的、一个程序对某个数据集的执行过程,是并发执行的程序在执行过程中分配和管理资源的基本单位。
如果把程序比作菜谱,进程就是按照菜谱炒菜的过程。
进程的描述
系统中需要有描述进程存在和能够反映其变化的物理实体,即进程的静态描述。
进程的静态描述由3部分组成:进程控制块(PCB),有关程序段和该程序段操作的数据结构集。进程的PCB是系统感知进程的唯一实体,程序段以及数据结构集是进程完成所需功能的物质基础。一个进程的PCB全部或部分常驻内存,而程序段和数据结构集存放在外存。
进程控制块(PCB)
PCB包含一个进程的描述信息、控制信息及资源信息,有些系统中还有进程调度等待所使用的现场保护区。
PCB集中反映一个进程的动态特征,创建一个进程时,应首先创建其PCB,然后根据PCB中的信息对进程实施有效的管理和控制。当一个进程完成其功能时,系统会通过释放PCB来释放进程所占有的各种资源,进程也随之消亡。
PCB的基本内容:
(1)描述信息:
1. 进程名或进程标识号。每个进程都有唯一的进程名或进程标识号,用于识别进程;
2. 用户名或用户标识号。每个进程都隶属于某个用户,有利于资源共享和保护;
3. 家族关系。表示进程之间的关系。
(2)控制信息:
1. 进程当前状态。进程在活动期间可分为初始态(刚被创建)、就绪态(准备占有处理机)、执行态(占有处理机)、等待状态(因其他原因暂时不能占有处理机)和终止状态(执行结束);
2. 进程优先级。进程优先级是选取进程占有处理机的重要依据;
3. 进程开始地址。规定该进程的程序以此地址开始执行;
4. 计时信息。进程占有和利用资源的情况;
5. 通信信息。该进程在执行过程中与其他进程的信息交换情况。
(3)资源管理信息:
PCB中包含最多的是资源管理信息,包括有关存储器的信息、使用输入输出设备的信息和有关文件系统的信息等。
(4)CPU现场保护区:
若进程因等待某个事件而进入等待状态或因某个事件发生而被中止在处理机上的执行,为了以后该进程能在被打断出恢复执行,需要设置专门的CPU现场保护区,以存储退出执行时的进程现场数据。
由于PCB中包含较多信息,往往要占据较大的存储空间(一般占几百到几千个字节),所以在某些系统中为了减少PCB对内存的占用量,只允许 PCB中最常用的部分保存在内存中,其他部分则存放于外存,待该进程将要执行时,与其他数据一起装入内存。
进程上下文(context)
在了解进程上下文之前,需要先搞清楚一个概念——进程调度。
无论是在批处理系统还是分时系统中,用户进程数一般都多于处理机数、这将导致它们互相争夺处理机。另外,系统进程也同样需要使用处理机。这就要求进程调度程序按一定的策略,动态地把处理机分配给处于就绪队列中的某一个进程,以使之执行。
进程上下文是一个抽象的概念。已执行过的进程指令和数据在相关寄存器和堆栈中的内容称为上文,正在执行的内容称为正文,待执行的内容称为下文。
进程上下文切换
在不发生进程调度时,进程上下文的改变是在同一进程内进行的,此时每条指令对进程上下文的改变较小。
进程上下文切换指的是不同进程之间的切换,切换过程一般包括3个部分,并涉及3个进程——
第一部分:保存被切换进程的正文部分至有关存储区;
第二部分:执行有关程序调度和资源分配的程序,选取新的进程;
第三部分:将被选进程的、原来被保存的正文部分,从有关存储区取出,并送至有关寄存器和堆栈中,激活被选进程的执行。(超级拗口的说...)
进程上下文切换比较耗费CPU时间,为了进一步提高执行效率,后来又提出了线程的概念。
进程空间与大小
任意进程都有自己的地址空间,该空间称为进程空间或虚空间。
进程空间的大小只与处理机的位数有关。例如,一个16位长处理机的进程空间大小为2的16次方,而32位长处理机的进程空间为2的32次方。
程序的执行都在进程空间内进行。
进程状态转换
前面介绍的进程控制块(PCB)中提到了进程的5种状态:初始态、就绪态、执行态、等待状态和终止状态。
5种基本状态间的转换:
创建进程→初始态→得到除处理机以外的其他资源→就绪态→进程调度,得到处理机→执行态→时间片用尽→就绪态;
执行态→等待某个事件(睡眠)→等待状态→等待的事件发生(唤醒)→就绪态;
执行态→进程结束→终止状态。
就绪态又可细分为内存就绪态和外存就绪态。处于内存就绪态的进程已经获得除处理机以外的全部资源,经进程调度得到处理机后可立即投入执行;处于外存就绪态的进程还需要先获得资源,成为内存就绪态的进程。
进程控制
所谓进程控制,就是系统使用一些具有特定功能的程序段来创建、撤销进程以及完成进程各状态间的转换,从而达到多进程高效率并发执行和协调、实现资源共享的目的。
在操作系统中,这些用于进程控制的程序段被做成原语。原语又分为创建原语、撤销原语、阻塞原语和唤醒原语等。
创建进程
创建进程有两种方式:由系统程序模块统一创建和由父进程创建(形成家族关系)。
无论是哪种创建方式,都必须调用创建原语来实现。创建原语扫描系统的PCB链表,在找到一定的PCB表后,填入调用者提供的各项参数,最后形成代表进程的PCB结构。参数包括进程名、进程优先级P0、进程正文段起始地址d0和资源清单R0等。
撤销进程
撤销进程的情况:
(1)进程已完成所要求的功能而正常终止;
(2)由于某种错误导致非正常终止;
(3)祖先进程要求撤销某个子进程。(连祖先都出来了....= = |||)
撤销原语首先检查进程链表或进程家族是否存在要撤销的进程,如果有,且该进程没有子进程,则释放该进程占有的所有资源,并释放PCB结构。
阻塞进程
阻塞原语实现进程从执行状态到等待状态的转换,首先保存当前进程的CPU现场,然后将PCB块中的进程状态设置为“等待状态”,再将被阻塞进程放入等待队列。旧进程(被阻塞进程)处置好后,就要转进程调度,选择新进程(就绪进程)投入运行。
唤醒进程
唤醒进程有两种方式:由系统进程唤醒和由事件发生进程唤醒。
唤醒原语首先将被唤醒进程从相应的等待队列摘下,然后将PCB块中的进程状态设置为“就绪状态”,并送入就绪队列。之后唤醒源于既可以返回原调用程序,也可以转进程调度。
死锁问题
定义:死锁是指各并发进程互相等待对方所拥有的资源,且这些并发进程在得到对方的资源之前不会释放自己占有的资源,从而造成了各并发进程不能继续往前推进的状态。
起因:系统提供的资源个数少于并发进程所要求的该类资源数。
显然,由于资源的有限性,不可能为所有进程无限制地提供资源。采用适当的资源分配算法,就可以达到消除死锁的目的。因此需要先了解产生死锁的必要条件。
必要条件:
(1)互斥条件。并发进程所要求和占有的资源不能同时被两个以上进程使用,进程对它所需要的资源进行排他性控制。
(2)不剥夺条件。进程占有的资源只能由进程本身释放,而不能被其他进程强行剥夺。
(3)部分分配。进程每次申请它所需要的一部分资源,在等待新资源的同时,继续占用已分配到的资源(即使已经使用完)。
(4)环路条件。存在一种进程循环链,链中的每一个进程已获得的资源同时被下一个进程所请求。
只要使上述4个必要条件中的某一个不满足,死锁就能解除。
实际上,消除死锁一般依靠检测和恢复。
当进程进行资源请求时,死锁检测算法检查并发进程是否出现环路,若出现,最简单的方法是终止各锁住进程,或按影响级别由低到高的顺序中止进程序列,直至释放的资源足够完成剩余进程。
线程的概念
为什么要引入线程?
进程是为了提高CPU的执行效率,减少因为程序等待带来的CPU空转以及其他计算机软、硬件资源的浪费而提出来的,是为了完成用户任务所需要的程序的一次执行过程以及为其分配资源的一个基本单位。
由前面介绍的内容可知,创建和切换进程耗费较大的系统开销和占用较多的资源。开销越大,服务器能支持和处理的用户访问请求就越少。
为了减少创建进程和进程上下文切换的开销,提高执行效率和节省资源,人们开始在操作系统中引入一个概念——线程。
线程的基本概念
线程是进程的一部分。因此线程有时会被称为轻量级进程(light weight process)。
线程的改变只代表了CPU执行过程的改变,除了CPU外,计算机内的软硬件资源的分配与线程无关,线程只能共享它所属的进程的资源。
每个线程都有自己的线程控制块(TCB),而TCB中保存的线程状态信息要比PCB少得多。
线程的适用范围
使用线程的最大好处是在有多个任务需要处理机处理时,减少处理机的切换时间;而且线程的创建和结束所需要的系统开销也比进程小得多。
尽管线程可以提高系统的执行效率,但并不是所有的计算机系统都适用线程。任务单一却设置线程反而会占用更多的系统资源。
由此可以推出多处理机系统、网络系统和分布式系统更适合适用线程。
应用线程的例子:一个用户主机通过网络对两台远程服务器进行远程调用(RPC)以获得相应结果的执行情况。
单线程:发送请求1后必须等待服务器1处理好并返回结果1后才能继续发送请求2;
多线程:发送请求1后即可继续发送请求2,不必等待结果1返回。
路过的圈毛君:“本篇很懒地省略了较多的,复杂的,暂时用不到的内容_(:з」∠)_”