清华大学】操作系统 陈渝——Part7 进程/线程 管理
进程描述
为什么要有进程?
进程的概念比较抽象,在使用计算机的过程中,从某种角度说,运行的程序可以看成是进程,代表着程序在整个执行过程中的描述。
CPU的利用率时而高时而低,代表进程有时占CPU高有时占CPU少;
内存,网络的消耗也一样。
操作系统本来只支持跑一个程序,由于计算机的发展,CPU越来越强,内存越来越多,可以在CPU种放入更多的可以用来运行的程序,这时再用"程序"的概念来表示在操作系统中的各个程序就不再合适了。可能存在一个程序
跑了多份儿,多个程序的实例怎么来表示呢?由此,引出了进程的概念,通过进程可以更好地表示程序地执行过程。
7.1 进程的定义
进程:一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。
实例:写一个小程序,源代码经过编译可以变成可执行程序,执行程序包含了代码段,数据段等,这段程序放在文件系统中,以一种可执行文件的形式存在,是静态的,看不到可以完成哪些功能。只有当把它调入到内存中以后,让这个程序可以执行起来(CPU执行一条条指令,对相应的数据进行处理,可以完成一定功能),这个过程是一段动态过程,这个过程叫做“进程”。
7.2 进程的组成
一个进程应该包括:
- 程序的代码;
- 程序处理的数据;
- 程序计数器中的值,指示下一条将运行的指令;
- 一组通用的寄存器的当前值,堆、栈 ;
- 一组系统资源(如打开的文件)
总之,进程包含了正在运行的一个程序的所有状态信息。
进程与程序的关系
- 程序是产生进程的基础,进程执行的所有的功能在程序中有描述
- 程序的每次运行构成不同的进程,程序只有一份,放在硬盘中,可以多次执行这个程序,因为每次执行处理的数据不一样,行为不一样。
- 进程是程序功能的体现
- 通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。
进程与程序的区别
- 进程是动态的,程序是静态的;
- 程序是有序代码的集合,进程是程序的执行,进程有核心态 / 用户态
- 进程是暂时的,程序是永久的;
- 进程是一个状态变化的过程,程序可以长久保存;
- 进程的组成包括程序、数据和进程控制块(即进程状态信息)
实例:
7.3 进程的特点
- 动态性:可动态地创建、结束进程;
- 并发性:进程可以被独立调度并占用处理器运行;
- 并发和并行:并发是一段时间内多个进程在执行,并行是在一个时刻有多个进程在执行。一个CPU的情况下,无法实现并行,因为在某一个时刻只能执行一个进程,可以在一段时间内执行多个进程,因此只能实现并并发,只有多个CPU时才能执行并行。
- 独立性:不同进程的工作不互相影响(需要操作系统的支持);
- 操作系统怎么样确保进程的独立性呢?在内存管理章节中可知,操作系统通过页表使得不同的程序访问的不同的地址空间,不会越过自己的地址空间,一旦越过便会产生异常,页错误。
- 页表是保证进程独立性的一个重要机制,操作系统给不同的进程分配不同的页表分配,让每一个进程在独立的空间中运行,使得进程间独立工作,它们的代码数据不受影响。
- 制约性:因访问共享数据 / 资源或进程间同步而产生制约。取决于进程间的同步互斥。
实例:
( a ). 动态性
( b ). 独立性
( c ). 制约性
进程的特点和功能需要操作系统的支持,如果设计一个操作系统,怎么样开实现其中的进程管理机制呢?
操作系统是软件程序,可以直接管理计算机硬件资源。
程序 = 算法 + 数据结构
描述进程的数据结构:进程控制块
(Process Control Block, PCB)
操作系统为每一个进程都维护了一个PCB,用来保存与该进程有关的各种状态信息。
7.4 进程控制结构(PCB)
- 进程控制块:操作系统管理控制进程运行所用的信息集合,内核为每一个进程维护了对应的PCB。
操作系统用PCB来描述进程的基本情况以及运行变化的过程,PCB是进程存在的唯一标志。 - 使用进程控制块
进程的创建:为该进程生成一个PCB;
进程的终止:回收它的PCB;
进程的组织管理:通过对PCB的组织管理来实现
PCB含有以下三大类信息
(一)进程标识信息:
例如本进程的标识ID,本进程的产生者标识(父进程标识);用户标识。
(二) 处理机(CPU)状态信息保护区。保护进程的运行现场信息:
CPU需要寄存器来处理很多事情
- 用户可见寄存器,用户程序可以使用的数据,地址等寄存器
- 控制和状态寄存器,如程序计数器(PC),程序状态字(PSW)
- 栈指针,过程调用 / 系统调用 / 中断处理 和 返回时需要用到它。
(三)进程的控制信息:
- 调度和状态信息,用于操作系统调度进程并占用处理机使用。
- 进程间通信信息,为支持进程间的与通信相关的各种标识、信号、信件等,这些信息存在接收方的进场控制块中。
- 存储管理信息,占用了多大的内存,包含有指向本进程映像存储空间的数据结构。
- 进程所用资源,说明由进程打开、使用的系统资源。如打开的文件等。
- 有关数据结构连接信息,进程可以连接到一个进程队列中,或连接到相关的其他进程的PCB。
PCB组织方式
进程的执行过程是动态的,通过链表的形式完成动态的插入/删除 效果更好。
- 链表:同一状态的进程其PCB成一链表,多个状态对应多个不同的链表
各状态的进程形成不同的链表:就绪链表、阻塞链表 - 索引表:同一状态的进程归入一个index表(由index指向PCB),多个状态对应多个不同的index表
各状态的进行形成不同的索引表:就绪索引阻塞索引表。
进程状态
7.5 进程的生命周期原理
进程生命期管理
进程创建
引起进程创建的3个主要事件:
- 系统初始化时
- 用户请求创建一个新进程,向操作系统发出请求
- 正在运行的进程执行了创建进程的系统调用
此时构建的PCB表示初始状态
进程运行
内核选择一个就绪可以执行的进程,让它占用处理机并执行,此时为从就绪态变为运行态
- 为何选择?
- 如何选择?
后续调度算法
进程等待
在以下情况下,进程等待(阻塞)
- 请求并等待系统服务,无法马上完成
- 启动某种操作,无法马上完成
- 需要的数据没有到达
进程只能自己阻塞自己,因为只有进程自身才能知道何时需要等待某种事件的发生。从运行态到等待态,处于等待态的进程不占用CPU,可以让其他就绪的进程运行。
进程唤醒
进程唤醒的原因:
1.被阻塞的进程需要的资源可以被满足
2.被阻塞的进程等待的事件到达
3.将该进程的PCB插入到就绪队列
进程只能被别的进程或者操作系统唤醒。
进程结束
在以下四种情形,进程结束:
1.正常退出(自愿的)
2.错误退出(自愿的)
3.致命错误(强制性的)
4.被其他进程杀死(强制性的)
7.6 进程的状态变化模型
进程的三种基本状态:进程在生命结束前处于且仅处于三种基本状态之一。
不同系统设置的进程状态数目不同。
运行状态(Running):当前进程正在占用CPU运行时
就绪状态(Ready) :一个进程获得了除CPU以外的一切所需资源,一旦得到处理机即可运行。
等待状态(Blocked):一个进程正在等待某一事件而暂停运行时。如等待某资源,等待输入/输出完成。
状态切换图示:
进程其他的基本状态:
创建状态(New):一个进程正在被创建,还没被转到就绪态之前的状态
结束状态(Exit):一个进程正在从系统中消失时的状态,这是因为进程结束或由于其他原因所导致。
可能的状态变化如下
Null - New :一个新进程被产出来执行一个程序。
New - Ready:当进程被创建完并完成初始化后,一切就绪准备运行时,变为就绪态。这个就绪态不会不会持续很久。
Ready - Running:处于就绪态的进程被进程调度程序选中后,就分配到CPU上来运行。
Running - Exit:当进程表示它已经完成或者因出错,当前运行进程会由操作系统作结束处理。
Running - Ready:处于运行状态的进程在其运行过程中,由于分配给它的CPU时间片用完而让让出CPU。由操作系统来完成,操作系统有时钟管理,会感知这个时间片。
Running - Blocked:当进程请求某样东西且必须等待时。比如等待定时器的到达,读写文件。
Blocked - Ready:当进程要等待某件事件到来时,它从阻塞状态变到就绪状态。
7.7 进程挂起模型
挂起:把一个进程从内存转到外存。
为什么会有进程挂起?合理充分地利用系统资源,释放资源给其他进程。
进程在挂起时,意味着进程没有占用内存空间,会把占用的内存空间导入到磁盘上。处在挂起状态的进程映像在磁盘上。
挂起状态
- 阻塞挂起状态(Blocked-suspend):进程在外存并等待某事件的出现。
- 就绪挂起状态(Ready-suspend):进程在外存,但只要进入内存,即可运行。
与阻塞挂起相关的状态转换
-
阻塞到阻塞挂起:阻塞状态的进程在运行时发现内存空间不够了,变成阻塞挂起,释放空间给就绪进程和正在运行的进程。
没有进程处于就绪状态或就绪进程要求更多内存资源时,会进行这种转换,以提交新进程或运行就绪进程; -
就绪到就绪挂起:一般就绪进程比阻塞进程优先级高一些,因此操作系统会优先选择处于阻塞状态的进程,把它变成阻塞挂起进程。
当有高优先级阻塞(系统认为会很快就学的) 进程和低优先就绪进程时,系统会选择挂起低优先级就绪进程; -
运行到就绪挂起:对抢占式分时系统,当有高优先级阻塞挂起进程因事件出现而进入就绪挂起时,系统可能会把当前运行进程转到就绪挂起状态。
-
在外存时的状态转换:
阻塞挂起到就绪挂起::当有阻塞挂起进程因相关事件出现时,系统会把阻塞挂起进程转换为就绪挂起进程。 -
解挂/激活(Activate):把一个进程从外存转到内存,可能有以下情况:
就绪挂起到就绪:没有就绪进程或挂起就绪进程优先级高于就绪进程时,会进行这种转换。
阻塞挂起到阻塞:当一个进程释放足够内存时,系统会把一个高优先级阻塞挂起(系统认为会很快出现所等待的事件)进程转换为阻塞进程
OS怎么通过PCB和定义的进程状态来管理PCB,帮助完成进程的调度过程?
以进程的角度看待操作系统:
状态队列
- 由操作系统来维护一组队列,用来表示系统当中所有进程的当前状态;
- 不同的状态分别用不同的队列来表示(就绪队列、各种类型的阻塞队列);
- 每个进程的PCB都根据它的状态加入到相应的队列当中,当一个进程的状态发生变化时,它的PCB从一个状态队列中脱离出来,加入到 另外一个队列。
状态的队列是操作系统管理进程的一个重要数据结构,通过队列,把一个个进程对应的PCB有效组织起来,便于操作系统有效管理。
因为优先级不同,会存在多个就绪状态的队列。
阻塞状态进程根据等待的事件有不同的队列。
线程描述
7.8 为什么要有线程?
单进程的实现方法
多进程的实现方法
如何解决上述那些问题?
需要提出一种新的实体,满足一下特性:
(1) 实体之间可以并发地执行
(2) 实体之间共享相同地地址空间
这种实体就是 : 线程(Thread)
7.9 线程定义
Thread : 进程当中的一条执行流程。
从两个方面来重新理解进程:
- 从资源组合的角度:进程就是用来管理资源的。进程把一组相关的资源组合起来,构成了一个资源平台(环境),包括地址空间(代码段、数据段)、打开的文件等各种资源。
- 从运行的角度:代码在这个资源平台上的一条执行流程(线程),线程是进程的重要组成部分。
线程 = 进程 - 共享资源
线程优点:
- 一个进程中可以同时存在多个线程;
- 各个线程之间可以并发地执行;
- 各个线程之间可以共享地址空间和文件资源等。
线程缺点:
-
一个线程崩溃,会导致其所属进程的所有线程崩溃,安全可靠性没有保证。
线程所需的资源
独占资源和共享资源。
多线程中,每个线程有自己的寄存器和堆栈,确保线程控制流独立执行。
进程与线程的比较
- 进程是资源分配单位 ;线程是CPU调度单位
- 进程拥有一个完整的资源平台 ; 线程独享必不可少的资源,如寄存器和堆栈
- 线程同样拥有就绪,阻塞和执行三种基本状态,具有状态之间的转换关系
- 线程能减少并发执行的时间和空间开销:
- 线程的创建时间比进程短;
- 线程的终止时间比进程短;
- 同一进程内的线程切换时间比进程短,进程切换需要切换内存管理中的页表,开销很大,硬件信息都会无效,而线程是共享同一页表,没有这方面的开销。
- 由于同一进程的各线程间共享内存和文件资源,可直接进行不通过内核的通信。
7.10 线程的实现
主要有三种线程的实现方式:
1. 用户线程
操作系统看不到的线程,在用户空间实现,由应用库来管理;
用户线程的缺点
- 阻塞性的系统调用如何实现?如果一个线程发起系统调用而阻塞,则整个进程在等待;
- 当一个线程开始运行后,除非它主动交出CPU使用权,否则它所在的进程当中的其他线程将无法运行,因为操作系统看不到用户线程,只能看到它所属的进程;
- 由于时间片分配给进程,故与其它进程相比,在多线程执行时,每个线程得到的时间片较少,执行会较慢。
2. 内核线程
操作系统能看到的线程,操作系统自身来管理,在内核中实现
用户线程与内核线程的对应关系
- 多对一
- 一对一
- 多对多
3. 轻量级进程
在内核中实现,支持用户线程。
一个进程可有一个或多个轻量级进程,每个量级进程由一个单独的内核线程来支持。
7.11 进程切换(上下文切换)
程序以进程的形式在CPU中运行,各个进程共享CPU资源,不同时刻需要切换不同进程,让不同的进程占用CPU执行。这个切换过程称之为进程的 “上下文(Context)切换”,切换的是进程使用需要的寄存器资源。
-
进程切换(上下文切换)
暂停当前运行进程(从运行状态改变成其他状态);
调度另一个其他进程(从就绪态转变成运行状态),从就绪队列中找一个进程。 -
进程切换的要求
- 切换前,存储许多部分的进程上下文
- 切换后,恢复进程上下文,必须能够在之后恢复他们,所以进程不能显示它曾经被暂停过
- 必须快速(上下文转换是非常平凡的)
-
需要存储什么(进程生命周期信息)上下文?
- 寄存器(PC,SP…)
- CPU状态…
- 内存地址空间
进程切换应该尽可能避免,一些时候可能会费时,
上下午切换的开销应该是越少越好,实现基本都是汇编语言实现的。
- PCB: 内核的进程状态记录
- 内核将相同状态的进程的PCB放置同一队列
- 内核将相同状态的进程的PCB放置同一队列
7.12 进程控制 – 创建进程
- 进程创建:操作系统给用户使用的一个系统调用,完成进程的创建工作。
- 不同系统提供进程创建的API不同
- Windows进程创建API:CreateProcess(filename)
- Unix进程创建系统调用:fork/exec