6 进程管理
进程(Process)描述
-
定义:一个具有一定独立功能的程序在一个数据集合上的动态执行过程
-
组成:
- 程序代码(Code)
- 程序处理的数据 (Data)
- 程序计数器中的值,指示下一条将运行的指令
- 一组通用寄存器当前的值,堆、栈
- 一组系统资源(文件系统、内存、网络等)
-
程序 vs 进程
-
联系:
- 程序是进程的基础,进程是程序功能的体现
- 程序的每次运行对应于不同的进程
- 一个程序可以通过多次执行,对应多个进程;进程可以通过相互调用,对应多个程序
-
区别:
-
程序是静态的有序代码集合,进程是程序的动态执行,进程有核心态(通过调用OS接口,如打开文件)和用户态
-
进程是暂时的,程序是永久的
-
进程包括程序、数据和进程控制块PCB(Process Control Block,即进程状态信息)
OS为每个进程创建了一个PCB,用来保存与该进程相关的状态信息
-
-
进程特点
- 动态性:进程可动态的创建和结束
- 并发性:进程可独立地被调度运行并占用处理机
- 独立性:不同进程间的工作互不影响(每次运行的结果应该都是正确的)
- 制约性:因访问共享数据/资源或进程间同步而产生制约性
进程控制结构
- PCB组成
- 进程标识信息:本进程标识,父进程标识,用户标识
- 处理器状态信息(保持进程运行现场信息)
- 用户可见寄存器:用户程序可用的数据、地址等寄存器
- 控制和状态寄存器,如程序计数器,程序状态字(PSW)
- 栈指针,过程调用/系统调用/中断处理和返回时需要用到
- 进程控制信息
- 调度和状态信息。用于OS调度进程并占用处理器使用
- 进程间通信信息。与支持进程间的通信相关的各种标识、信号、信件等,这些信息存在接收方PCB中
- 存储管理信息。包含执行本进程映像存储空间(内存块)的数据结构
- 进程所用资源。说明由进程打开、使用的系统资源,如打开的文件
- 有关数据结构连接信息。进程可以连接到一个进程队列中,或连接到相关其他进程的PCB
- PCB组织过程
- 链表:同一状态的进程PCB组成一个链表,多个状态对应多个不同的链表(如就绪链表、阻塞链表)
- 索引:同一状态进程归入一个索引表,多个状态对应多个不同的索引表(如就绪索引表、阻塞索引表)
进程状态
进程生命周期管理
- 进程开始(状态:Start ⇒ Ready)
- 原因:
- 系统初始化时
- 用户请求创建进程
- 正在运行的进程执行了进程创建的系统调用
- 原因:
- 进程运行(状态:Ready ⇒ Running)
- 为何选择Ready进程?
- 如何选择?
- 进程等待(阻塞)(状态:Running ⇒ Blocked)
- 原因:
- 请求并等待系统服务,无法马上完成(如打开文件)
- 启动某种操作,无法马上完成(如需要依赖于另一个进程完成)
- 需要的数据没有到达
- 进程等待只能由进程自身发起,因为只有进程自身知道何时需要等待
- 原因:
- 进程唤醒(状态:Blocked ⇒ Ready)
- 原因:
- 被阻塞进程获得所需要的资源
- 被阻塞进程等待的事件到达
- 将该进程PCB插入Ready队列
- 进程自身处于等待状态,所以只能由其他进程或OS唤醒
- 原因:
- 进程结束(状态:Running ⇒ Done)
- 原因
- 正常退出(自愿)
- 错误退出(自愿)
- 致命错误(强制性,OS杀死),如进程试图访问其他进程的页帧
- 被其他进程杀死(强制性),如某些系统管理进程判断该进程占用过多系统资源,可能破坏系统稳定性,故杀死
- 原因
进程状态变化模型
- 三种基本状态:进程在生命结束前的三种基本状态
- 运行状态(Running):一个进程正在CPU上运行
- 就绪状态(Ready):进程得到了除CPU外的一切所需资源,等得到CPU即可执行
- 等待/阻塞状态(Blocked):进程等待某一事件/资源而暂停执行
- 其他基本状态
- 创建状态(New):一个进程正在被创建,还没转入就绪态之前的状态
- 结束状态(Exit):一个进程正从系统中消失的状态,但还没完全消失,PCB还存在
- 状态转换图
- 几种状态转换
- NULL ⇒ New:新进程的PCB被创建出来
- New ⇒ Ready:新进程完成初始化后,获得除CPU外的一切其他资源,进入Ready队列等待CPU调度
- Ready ⇒ Running:进程被CPU调度运行
- Running ⇒ Exit:进程已完成或发生错误退出
- Running ⇒ Blocked:进程等待某些事件完成,或等待资源就绪(如等待文件读写完成)
- Running ⇒ Ready:进程用完OS分配的CPU时间片,进入Ready状态,等待后续CPU的调度(程序并发时,每个进程轮流运行一段时间片)
- Blocked ⇒ Ready:进程等待的某事件到来
进程挂起
-
含义:进程处于挂起状态时,不占用物理内存。进程映像(通过swap out)存放在外存。
-
挂起状态
- 阻塞挂起状态(Blocked-suspended):进程在外存中等待某事件的出现
- 就绪挂起状态(Ready-suspended):进程在外存,只要进入内存,即可运行
-
状态转换
- 内存 ⇒ 外存
- 阻塞 ⇒ 阻塞挂起:没有进程处于就绪状态或就绪进程需要更多资源时,会进行这种转换,以提交新进程或运行就绪进程
- 就绪 ⇒ 就绪挂起:当有高优先级阻塞进程(系统认为很快会就绪的)和低优先级就绪进程时,OS会选择挂起低优先级进程(如果没有定义优先级,一般阻塞进程优先级低于就绪进程,所以一般OS会先挂起阻塞进程)
- 运行 ⇒ 就绪挂起:对于抢先分时系统,当有高优先级阻塞进程等待的事件发生而进入就绪挂起时,OS可能挂起运行中的低优先级进程
- 外存中的状态转换
- 阻塞挂起 ⇒ 就绪挂起:处于阻塞挂起的进程获得所需的资源后,进入就绪挂起状态,但仍存储在外存中
- 内存 ⇒ 外存
-
解挂/激活(Activate):一个挂起的进程从外存回到内存
- 就绪挂起 ⇒ 就绪:当没有就绪进程或就绪进程优先级低于挂起的就绪进程时发生
- 阻塞挂起 ⇒ 阻塞:当系统物理内存足够时,系统会把一个高优先级阻塞挂起进程(OS认为其等待的事件很快会发生)转换为阻塞进程
-
状态队列
问题:OS 如何通过PCB和进程状态管理进程?
- OS系统维护一组队列,用来表示系统当中所有进程的当前状态
- 不同状态用不同队列表示,如阻塞队列、就绪队列等(可能还会按优先级细分)
- 不同队列存放到不同进程的PCB;当进程状态改变时,则将其PCB从原队列取出放到相应的队列中
线程(Thread)
为什么需要线程?
-
单进程的顺序执行可能导致程序性能受限于进程中的某个部分(如文件读写)
-
将单进程拆解为多进程,则需要考虑 ①进程间的通信、资源共享;②OS维护进程的开销增大(创建进程需要分配资源、创建PCB;结束进程需释放资源、清除PCB;进程切换需要保存进程状态信息)
-
需要创建这样一个实体:①实体间可以并发执行 ②实体间共享地址空间
什么是线程?
-
线程是进程中的一条执行流程
-
进程 = 资源管理 + 线程
-
优点:(性能)
- 一个进程中可以存在多个线程,多线程可以并发地执行
- 各线程共享地址空间和文件等资源
-
缺点:(安全)
- 安全可靠性下降,一个线程崩溃,会导致其所属进程的全部线程崩溃
- 线程共享代码、数据、文件,不共享堆栈和寄存器
-
线程与进程的比较
- 线程同样具有就绪、阻塞、运行三种基本状态,以及状态间的转换关系
- 进程是资源分配单位,线程是CPU调度单位
- 进程拥有完整的资源平台,而线程只独享必要的资源(如寄存器、堆栈)
- 线程能减少并发执行的时间和空间开销
- 线程创建、终止的时间比进程短(因为不需要考虑内存管理、文件释放等)
- 同一进程内的线程切换比进程切换时间短(因为不需要切换页表等)
- 同一进程内的各个线程共享内存和文件等资源,通信不需要经过内核
线程的实现
-
用户线程(在用户空间实现)
- 用于Posix Pthreads、Mach C-threads、Solaris Threads
- 不依赖系统内核,通过用户级线程库函数进行管理,包括线程创建、终止、同步、调度等。OS意识不到线程存在
- 优点:
- 可用于不支持线程技术的单进程系统
- 用户态切换通过线程库函数实现,不需要经过内核,所以速度很快
- 允许每个进程有自己的线程调度算法
- 每个线程需要有自己的线程控制块(TCB)列表,用来跟踪每个线程的状态信息(PC、栈指针、寄存器等),TCB由线程库函数维护
- 缺点:
- 当线程发起阻塞性系统调用时,整个进程都会进入阻塞状态
- 当一个线程开始运行后,除非它主动交出CPU使用权,否则进程内的其他线程无法运行(用户态线程库没有打断线程运行的特权,而OS可以通过管理中断(如时钟中断),强制切换到其他线程)
- 由于时间片分配到进程,所以与其他线程相比,多线程执行时,分配到每个线程的时间片较小,执行较慢
-
内核线程(在内核中实现)
- 用于Windows、Solaris、Linux
- 由内核维护线程和上下文信息
- 线程的创建、终止、切换均由系统调用/内核函数方式进行,由内核完成,系统开销较大
- 优点:
- 若某内核线程发起系统调用而阻塞,不会影响进程内其他线程的执行
- 时间片分配给线程,进程获得更多时间片
-
轻量级线程(内核中实现,支持用户线程)
- 用于Solaris
- 内核支持的用户线程(UT),一个进程可以包含多个轻量级进程(LWP),每个LWP由一个单独的内核线程KT管理
-
用户线程与内核线程对应关系
- 多对一 (n to 1)
- 一对一 (1 to 1)
- 多对多(n to m)
上下文切换
- 含义:停止当前运行的进程,暂时切换到其他进程的过程
- 切换之前存储很多的进程上下文
- 应能够恢复原来的状态,进程不能显示其曾被暂停过
- 切换必须快速(因为上下文切换是很频繁的)
- 需要保存的信息:PC(程序计数器)、SP(栈指针)、CPU状态等