2.1进程
2.1进程
进程的 概念、组成、 特征
"进程"和"程序“的区别
程序:是静态的,就是个存放在磁盘里的 可执行文件,如:QQ.exe。
进程:是动态的,是程序的一次执行过程, 如:可同时启动多次QQ程序 同一个程序多次执行会对应多个进程
进程控制块PCB
是进程存在的唯一标志,当进程被创建时,操作系统为它创建PCB,当进程结束时,会回收PCB
PCB里面记录的东西:
- 进程描述信息
- PID、UID
- 进程控制和管理信息
- CPU、磁盘、网络流量使用情况
- 进程当前的状态
- 资源分配清单
- 使用了哪些文件
- 使用了哪些内存区域
- 使用了哪些I/O设备
- 处理机相关信息:如PSW等寄存器的值
进程的组成
- PCB
- 程序段:程序的代码
- 数据段:运行过程中产生的各种数据
PCB 是给操作系统用的。 程序段、数据段是给进程自己用的。
进程被“调度”
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
一个进程被“调度”,就是指操作系统决定让这个进程上CPU运行
同时挂三个QQ号,会对应三个QQ进程,它们的PCB、数据段各不相同,但程序段的内容都是相同的(都是运行着相同的QQ程序)
进程的特征
- 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的(是进程的最基本的特性)
- 并发性:内存中有多个进程实体,各进程可并发执行
- 独立性:进程是能独立运行、独立获得资源、独立接受调度的基本单位
- 异步性:各进程按各自独立的、不可预知的速度前进,操作系统要提供“进程同步机制”来解决同步问题
- 结构性:每个进程会配置一个PCB。从结构上看,进程由程序段、数据段、PCB组成。
进程的 状态与转换
- 创建态:进程正在被创建,操作系统会为进 程分配资源、初始化PCB
- 就绪态:当进程创建完成后,便进入“就绪态”, 处于就绪态的进程已经具备运行条件, 但由于没有空闲CPU,就暂时不能运行【此时CPU×、其他所需资源√】
- 运行态:当CPU空闲时,操作系统 就会选择一个就绪进程, 让它上处理机运行。如果一个进程此时在CPU上运行,那么这个进程 处于“运行态”。 CPU会执行该进程对应的程序【此时CPU√、其他所需资源√】
- 阻塞态:在进程运行的过程中,可能会请求等待某个事件的发生(如等待 某种系统资源的分配,或者等待其他进程的响应)。 在这个事件发生之前,进程无法继续往下执行,此时操作系统会 让这个进程下CPU,并让它进入“阻塞态” 当CPU空闲时,又会选择另一个“就绪态”进程上CPU运行 【此时CPU×、其他所需资源×】
- 终止态:进程正在从系统中撤销,操作系统会回收进程拥有的资源、撤销PCB
其中,就绪态、运行态、阻塞态为三种基本状态,进程的整个生命周期中,大部分时间都处 于三种基本状态
进程状态的转换
单CPU情况下,同一时刻只会有一 个进程处于运行态,多核CPU情况 下,可能有多个进程处于运行态
进程的组织
- 链接方式:按照进程状态将PCB分为多个队列,操作系统持有指向各个队列的指针
- 索引方式:根据进程状态的不同,建立几张索引表,操作系统持有指向各个索引表的指针
链接方式
索引方式
进程控制
进程控制就是要实现进程状态转换
如何实现进程控制?
用原语实现。原语:是一种特殊的程序,它的执行具有原子性.也就是说,这段程序的运行必须一气呵成,不可中断。【下图:如果没有用原语实现”一气呵成“】
如何实现原语的“原子性”?
可以用 “关中断指令”和“开中断指令”这两个特权指令实现原子性。CPU执行了关中断指令之后,就不再例行 检查中断信号,直到执行开中断指令之后 才会恢复检查。 这样,关中断、开中断之间的这些指令序列就是不可被中断的,这就实现了“原子性”
进程控制相关的原语
无论哪个进程控制原语,要做的无非三类事情:
1.更新PCB中的信息--修改进程状态(state),保存/恢复运行环境
2.将PCB插入合适的队列
3.分配/回收资源
创建原语
- 申请空白PCB
- 为新进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列【创建态→就绪态】
引起进程创建的事件
- 用户登录:分时系统中,用户登录成功,系统会建立为其建立一个新的进程
- 作业调度:多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程
- 提供服务:用户向操作系统提出某些请求时,会新建一个进程处理该请求
- 应用请求:由用户进程主动请求创建一个子进程
撤销原语【进程终止】
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立即剥夺CPU,将CPU分配给其他进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB【就绪态/阻塞态/运行态→终止态→无】
引起进程终止的事件
- 正常结束:进程自己请求终止(exit系统调用)
- 异常结束:整数除以o、非法使用特权指令,然后被操作系统强行杀掉
- 外界干预:Ctrl+Alt+delete,用户选择杀掉进程
阻塞原语
-
找到要阻塞的进程对应的PCB
-
保护进程运行现场,将PCB状态信息设置为"阻塞态",暂时停止进程运行
-
将PCB插入相应事件的等待队列【运行态→阻塞态】
引起进程阻塞的事件
- 需要等待系统分配某种资源
- 需要等待相互合作的其他进程完成工作
唤醒原语
- 在事件等待队列中找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度【阻塞态→就绪态】
引起进程唤醒的事件
等待的事件发生:因何事阻塞,就应由何事唤醒
进程的切换:切换原语
- 将运行环境信息存入PCB
- PCB移入相应队列
- 选择另一个进程执行,并更新其PCB
- 根据PCB恢复新进程所需的运行环境
引起进程切换的事件
- 当前进程时间片到
- 有更高优先级的进程到达
- 当前进程主动阻塞
- 当前进程终止
进程通信 (IPC)
- 共享存储
- 基于数据结构的共享
- 基于存储区的共享
- 消息传递
- 直接通信方式
- 间接通信方式
- 管道通信
进程间通信(Inter-Process Communication, IPC):两个进程 之间产生数据交互。
为什么进程通信需要操作系统支持?
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立
为了保证安全,一个进程不能直接访问另一个进程的地址空间。(就像你家随时可以让邻居进来,这多瘆人啊)
共享存储
基于数据结构的共享:比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式
基于存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
消息传递
间接:通过“信箱”间接地通信。 因此又称“信箱通信方式”
直接:消息发送进程要指明接收进程的ID
管道通信
“管道”是一个特殊的共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存缓冲区
1.管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
2.各进程要互斥地访问管道(由操作系统实现);只要管道没空,读进程就可以从管道读数据 ;只要管道没满,写进程就可以往管道写数据
3.当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
4.当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
5.管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:①一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案)﹔②允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux的方案)。
线程
引入线程
- 资源分配、调度
- 传统进程机制中,进程是资源分配、调度的基本单位
- 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位
- 并发性
- 传统进程机制中,只能进程间并发
- 引入线程后,各线程间也能并发,提升了并发度
- 系统开销
- 传统的进程间并发,需要切换进程的运行环境,系统开销大
- 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小
- 引入线程后,并发所带来的系统开销小
还没引入进程之前,系统中各个程序只能串行执行。比如无法一边聊天一边听歌,只能先聊天再听歌。
传统的进程是程序执行流的最小单位。引入线程后,线程成为了程序执行流的最小单位
不仅是进程之间 可以并发,进程内的各线程之间 也可以并发,一个进程内 也可以并发处理各种任务(如QQ 视频、文字聊天、传文件) 引入线程后,进程只作为除CPU之 外的系统资源的分配单元(如打 印机、内存地址空间等都是分配 给进程的)。 线程则作为处理机的分配单元。
”开销大“类比: 去图书馆看书。桌子=处理机,人=进程,看不同的书=线程
切换进程运行环境:有一个不认识的人要用桌子,你需要把你的书收走,他把自己的书放到桌上
同一进程内的线程切换=你的舍友要用这张书桌,可以不把桌子上的书收走
线程的属性
- 线程是处理机调度的单位
- 多CPU计算机中,各个线程可占用不同的CPU
- 每个线程都有一个线程ID、线程控制块(TCB)
- 线程也有就绪、阻塞、运行三种基本状态
- 线程几乎不拥有系统资源
- 同一进程的不同线程间共享进程的资源
- 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
- 同一进程中的线程切换,不会引起进程切换
- 不同进程中的线程切换,会引起进程切换
- 切换同进程内的线程,系统开销很小
- 切换进程,系统开销较大
线程的实现方式 多线程模型
- 线程的实现方式
-
用户级线程
-
内核级线程
-
- 多线程模型
- 一对一模型
- 多对一模型
- 多对多模型
历史背景:早期的操作系统(如:早期Unix)只支持进程, 不支持线程。当时的“线程”是由线程库实现的
线程的实现方式
问:什么是用户线程?什么是内核线程?
内核线程: 切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态.
用户线程指: 不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。
用户级线程(User-Level Thread, ULT)
线程库完成了对线程的管理工作(如调度)
- 线程的管理工作由谁来完成? 用户级线程由应用程序通过线程库实现, 所有的线程管理工作都由应用程序负责(包括线程切换)
- 线程切换是否需要CPU变态? 用户级线程中,线程切换可以在用户态下 即可完成,无需操作系统干预。
- 操作系统是否能意识到用户级线程的存在? 在用户看来,是有多个线程。但是在操作 系统内核看来,并意识不到线程的存在。 “用户级线程”就是“从用户视角看能看到 的线程”
- 这种线程的实现方式有什么优点和缺点? 优点:用户级线程的切换在用户空间即可完 成,不需要切换到核心态,线程管理的系统 开销小,效率高 缺点:当一个用户级线程被阻塞后,整个进 程都会被阻塞,并发度不高。多个线程不可 在多核处理机上并行运行。
内核级线程(Kernel-Level Thread, KLT, 又称“内核支持的线程、由操作系统支持的线程”)
大多数现代操作系统都实现了内核级线程,如 Windows、Linux
- 线程的管理工作由谁来完成? ----内核级线程的管理工作由操作系统内核完 成。
- 线程切换是否需要CPU变态? ----线程调度、切换等工作都由内核负责,因 此内核级线程的切换必然需要在核心态下才 能完成。
- 操作系统是否能意识到内核级线程的存在? ----操作系统会为每个内核级线程建立相应的 TCB(Thread Control Block,线程控制块), 通过TCB对线程进行管理。“内核级线程”就 是“从操作系统内核视角看能看到的线程”
- 这种线程的实现方式有什么优点和缺点? ----优点:当一个线程被阻塞后,别的线程还可 以继续执行,并发能力强。多线程可在多核 处理机上并行执行。 缺点:一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到 核心态,因此线程管理的成本高,开销大
多线程模型
根据用户级线程和内核级线程的映射关 系,可以划分为几种多线程模型
一对一模型
一个用户级线程映射到一个内 核级线程。每个用户进程有与用户级线程同 数量的内核级线程。
优点:当一个线程被阻塞后,别的线程还可 以继续执行,并发能力强。多线程可在多核 处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到 核心态,因此线程管理的成本高,开销大。
多对一模型
多个用户级线程映射到一个内 核级线程。且一个进程只被分配一个内核级线程。
优点:用户级线程的切换在用户空间即可完 成,不需要切换到核心态,线程管理的系统 开销小,效率高
缺点:当一个用户级线程被阻塞后,整个进 程都会被阻塞,并发度不高。多个线程不可 在多核处理机上并行运行
重点重点重点: 操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的单位。
多对多模型
多对多模型:n用户及线程映射到m个内核级线程(n >= m)。每个用户进程对应m个内核级线程。
克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞),又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。
可以这么理解:用户级线程是“代码逻辑”的载体内核级线程是“运行机会”的载体
内核级线程才是处理机分配的单位。
例如:多核CPU环境下,左边这个进程最多能被分配两个核。一段“代码逻辑”只有获得了“运行机会”才能被CPU执行
内核级线程中可以运行任意一个有映射关系的用户级线程代码,只有两个内核级线程中正在运行的代码逻辑都阻塞时,这个进程才会阻塞
题
2、如果采用基于优先级可抢占的调度机制,请问在哪些情况下需要启动调度程序?也就是调度时机有哪些?至少说出4种。(4分)
1)一个新进程被创建,并进入就绪队列
2)当前执行进程因为I/O被阻塞
3)当前执行进程挂起自己
4)当前执行进程调用exit,return等函数退出执行
5)一个阻塞进程被唤醒
6)一个挂起进程被激活
3、论述操作系统中的系统调用函数是如何实现的?(4分)
系统调用利用软中断实现(1分),操作系统初始化过程中,会产生一张中断向量表,其中保存了中断服务程序的入口地址,发生软中断后通过中断号找到对应的中断服务程序(2分),从而找到注册到操作系统中的服务系统调用的函数,完成功能。(1分)