操作系统第二章:进程与线程
进程
包含PCB,程序段,内存
包含五个状态:
- 创建态
- 就绪态:等待CPU
- 运行态
- 阻塞态:等待其他资源
- 结束态
进程控制
原语是特殊的程序,执行必须一气呵成,不可中断,通过原语实现进程控制
具有关中断和开中断指令,在这个范围内不会去看是否有中断指令
进程创建
原语内容:
- 申请空白PCB
- 为新进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列
进程撤销
原语内容:
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立刻剥夺CPU,将CPU分配给其他进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB
进程的阻塞和唤醒
阻塞:
- 找到要阻塞进程的PCB
- 保护进程运行现场,将PCB状态信息设置为阻塞态,暂时停止进程运行
- 将PCB插入相应事件的等待队列
唤醒:
- 在事件等待队列种找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度
进程的切换
- 将运行环境信息存入PCB
- PCB移入相应队列
- 选择另一个进程执行,并更新其PCB
- 根据PCB恢复新进程所需的运行环境
进程通信
共享存储
申请共享存储区/数据结构,可以被其他进程所共享,但各个进程对共享空间的访问是互斥的,由进程本身的PV操作来实现。
分为基于存储区的共享和基于数据结构的共享
消息传递
进程间的数据交换以格式化的消息为单位,进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
消息由消息头和消息体构成,消息头包括发送进程ID、接受进程的ID、消息长度等格式化信息
分为直接通信方式和间接通信方式,间接通信方式即通过信箱进行传递
管道通信
管道是一个特殊的共享文件(pipe),再内存中开辟了一个大小固定的内存缓冲区,是一个循环队列
单个管道只能单向传输,称为半双工通信,两个管道可实现双向通信,称为全双工通信
互斥由操作系统来进行,只要管道没写满就可以往里面写,只要没读完就可以继续读取,读取看作出队
信号
用于通知进程某个特定事件已经发生,进程收到一个新号后,对该信号进行处理
信号的发送与保存
信号处理时机
线程
是基本的CPU的执行单元,是程序执行流的最小单位
进程是资源分配的基本单位,线程是调度的基本单位
线程控制块TCB
线程的实现方式
只有内核级线程才是处理机的分配单位
用户级线程
应用程序创建线程库来管理各个线程,切换在用户态当中进行即可,不需要切换到内核态,不需要CPU变态,但是一个进程阻塞,其他线程也会被阻塞
内核级线程
一个被阻塞,其他的还能正常运行,多核的情况下可以将不同进程分派到不同核心进运行
线程切换需要操作系统来实现,先要用户->内核,再切换内核级线程,再从内核->用户,运行用户级线程切换成本高
多线程模型
- 一对一:一个用户级线程对应一个内核级线程,开销大,不会阻塞
- 多对一:多个用户级线程对应一个内核级线程,就相当于一个内核级线程管理线程库
- 多对多:将n个用户级线程映射到m个内核级线程,每个内核级线程有n个用户级线程,就是多对一的批量版,不会阻塞
线程状态转化
分为:就绪,阻塞,运行
线程控制块(TCB)
调度
三层调度
高级/作业调度:
中级/内存调度:
挂起可分为就绪挂起、阻塞挂起
低级/进程/处理机调度
进程调度时机
进程调度方式
- 非剥夺式调度/非抢占式调度,只允许进程主动放弃处理机
- 剥夺式调度/抢占式调度,可以强制停止正在执行的进程,将处理机分配给更重要紧迫的进程
包含选择一个进程和进程切换两个步骤
进程切换完成了
- 对原来运行进程各种数据的保存
- 对新的进程各种数据的恢复
调度指标
CPU利用率
CPU忙碌的时间,$利用率=\frac{忙碌时间}{总时间}$,其他设备的利用率也是如此
系统吞吐量
单位时间内完成作业的数量,$系统吞吐量=\frac{总共完成的作业数}{总共花费的时间}$
周转时间
作业被提交给系统开始,到作业完成的时间
具体包含
- 作业再外存等待作业调度的时间
- 进程再就绪队列上等待进程调度的时间,就绪
- 进程再CPU上执行的时间,运行
- 进程等待I/O操作完成的时间,阻塞
$平均周转时间=\frac{各作业周转时间之和}{作业数}$
$带权周转时间=\frac{作业周转时间}{作业实际运行时间}$
$平均带权周转时间=\frac{各作业带权周转时间之和}{作业数}$
等待时间
进程/作业等待处理机状态时间之和,对进程来说就是一开始就绪队列等待的时间,对于作业来说还要加上在作业后备队列的等待时间
$平均等待时间=\frac{各作业/进程等待时间}{作业/进程数}$
响应时间
从用户提交到首次产生响应所用的时间
调度算法
先来先服务(FCFS)
按照作业/进程到达的先后顺序进行服务,作业按到达后备队列的顺序,进程按到达就绪队列的顺序
为非抢占式算法,公平,但是短作业的等待时间可能过长,不会导致饥饿(长期得不到服务)
短作业优先(SJF)
最短的作业和进程优先得到服务,用于进程调度时是短进程优先算法(SPF)
默认为非抢占式,也有抢占式的版本:最短剩余时间优先算法(SRTN)
“最短的”平均等待时间,,平均周转时间,平均带权周转时间,但是对长作业不利,可能导致饥饿现象
高响应比优先(HRRN)
同时考虑到等待和要求服务的时间,$响应比=\frac{等待时间+要求服务时间}{要求服务时间}$,计算当前时刻的响应比,让最大的上
非抢占式,整合了先来先服务和短作业优先的优点,适用于早期的批处理系统
若要求服务时间相同,则相当于先来先服务,若等待时间相同,就是短作业优先
时间片轮转调度算法(RR)
按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片,分时系统用于进程调度
抢占式算法,公平,响应快,适用于分时系统,高频的切换有一定的开销且不区分任务紧急程度,不会导致饥饿
默认先到达的进程先插入就绪队列,然后再是又阻塞转为就绪的,或者运行转为就绪的
时间片要让千幻进程的开销占比不超过1%
在分时操作系统当中更注重于响应时间,而不是周转时间
优先级调度算法
调度时选择优先级最高的作业/进程,优先级是否发生改变可分为动态优先级和静态优先级
抢占式和非抢占式都有,可以灵活区分优先级,但是如果一直有高优先级进来会导致饥饿
多级反馈队列调度算法
- 设计多级就绪队列,各个队列时间片从小到大,从第一级开始处理
- 新进程到达后进入第一级队列队尾,按照先来先服务等待分配时间片,若一次未结束则进入下一级队列队尾,若已经在最后一级,则放到这一级的末尾
- 在运行当中有更高优先级的到达则会被抢占,被抢占的会放到本级队尾
用于进程调度,抢占式算法,一直有进程进来会导致饥饿
多级队列调度算法
设置多个队列,不同进程插入对应队列,可采取固定优先级或时间片划分
- 高优先级空时低优先级进程才能被调度
- 给不同队列的时间片划分不同
各个队列里可以采用不同的调度策略
多处理机调度
多处理机——多核CPU
负载均衡:尽可能让每一个CPU都同等忙碌
处理机亲和性:尽可能让一个进程调度到同一CPU上运行
通过公共就绪队列,私有就绪队列实现
公共就绪队列
所有CPU共享一个就绪进程队列(位于内核区)
每个CPU调度的时候从这个队列里取,调用后上锁保证互斥访问
天然实现负载均衡,但是各个进程频繁切换CPU运行
私有就绪队列
每个CPU都有一个私有就绪队列
推迁移策略:一个特定的系统程序周期性检查每个处理器的负载,负载不平衡时候从繁忙的队列调到空闲队列
拉迁移:每个CPU运行调度程序时,周期性检查自身负载与其他CPU负载,其他的忙,自己闲则会拉一些过来