目录
1 进程
1.1 进程的定义
一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。(运行的程序)
1.2 进程的组成
- 程序的代码
- 程序处理的数据
- 程序计数器的值,指示下一条将运行的指令
- 一组通用的寄存器的当前值,堆,栈
- 一组系统资源(如打开的文件)
- 总之,进程包含了正在运行的一个程序的所有状态信息。
1.3 进程和程序的关系
- 程序是产生进程的基础
- 程序的每次运行构成不同的进程
- 进程是程序功能的体现
- 通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。
1.4 进程和程序的区别
- 进程是动态的,程序是静态的:程序是有序代码的集合;进程是程序的执行,进程有核心态/用户态
- 进程是暂时的,程序是永久的:进程是一个状态变化的过程,程序可长久保存
- 进程与程序的组成不同:进程的组成包括程序,数据和进程控制块(进程的状态信息)
1.5 进程的特点
- 动态性:可动态地创建,结束进程
- 并发性:进程可以被独立调度并占用处理机运行
- 独立性:不同进程的工作不互相影响
- 制约性:因访问共享数据/资源或进程间同步而产生制约
1.6 进程控制块
- 程序 = 算法 + 数据结构
- 进程控制块(process control block, PCB): 描述进程的数据结构,操作系统管理控制进程运行所用的信息集合。
- 操作系统为每个进程都维护了一个PCB,用来保存与该进程有关的各种状态信息,PCB是进程存在的唯一标志。
1.6.1 进程控制块的使用
- 进程的创建:为该进程生成一个PCB;
- 进程的终止:回收它的PCB;
- 进程的组织管理:通过对PCB的组织管理来实现;
1.6.2 PCB含有的三大信息
- 进程的标识信息:如本进程的标识,本进程的产生者标识(父进程标识);用户标识
处理机状态信息保存区,保存进程的运行现场信息
用户可见寄存器,用户程序可以使用的数据,地址等寄存器
控制和状态寄存器,如程序寄存器(PC),程序状态字(PSW)
栈指针,过程调用/系统调用/中断处理和返回时需要用到它。
进程的控制信息
调度和状态信息:用于操作系统调度进程并占用处理机使用;
进程间通信信息:为支持进程间的与通信相关的各种标识,信号,信件等,这些信息存在接收方的PCB中;
存储管理信息:包含有指向本进程映像存储空间的数据结构;
进程所用资源:说明由进程打开,使用的系统资源,如打开的文件等;
有关数据结构等连接信息:进程可以连接到一个进程队列中,或连接到相关的其它进程的PCB。
1.6.3 PCB的组织方式
- 链表:统一状态的进程其PCB成一脸表,多个状态对应多个不同的链表,各状态的进程形成不同的链表,例如就绪链表和阻塞链表
- 索引表:同一状态的进程归入一个index表(由index指向PCB),多个状态对应多个不同的index,各状态的进程形成不同的索引表,例如就绪索引表,阻塞索引表。
1.7 进程的生命周期管理
进程创建-进程运行-进程等待-进程唤醒-进程结束
1.7.1 进程创建
引起进程创建的三个主要事件:
- 系统初始化
- 用户请求创建一个新进程
- 正在运行的进程执行了创建进程的系统调用
1.7.2 进程等待
以下情况,进程等待:
- 请求并等待系统服务,无法马上完成;
- 启动某种操作,无法马上完成;
- 需要的数据没有到达。
进程只能自己阻塞自己,因为只有进程自身才能知道何时需要等待某种事件的发生。
1.7.3 进程唤醒
唤醒进程的原因如下:
- 被阻塞进程需要的资源可被满足;
- 被阻塞进程等待的事件到达;
- 将该进程的PCB插入到就绪队列中。
进程只能被别的进程或操作系统唤醒。
1.7.4 进程结束
包括以下四种情形:
- 正常退出(自愿)
- 错误推出(自愿)
- 致命错误(强制性)
- 被其它进程所杀(强制性)
1.8 进程的状态变化模型
进程的三种基本状态:
进程在生命结束前处于且仅处于三种基本状态之一,不用系统设置的进程状态数目不同。
- 运行状态(running):当一个进程正在处理机上运行时;
- 就绪状态(ready):一个进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行;
- 等待状态(或阻塞状态blocked):一个进程正在等待某一事件而暂停运行时的状态,如等待资源,等待I/O完成。
1.8.1 状态变化图
1.8.2 状态变化的原因
- NULL → New: 一个新进程被产生出来执行一个程序。
- New → Ready:当进程被创建完成并初始化后,一切就绪准备运行时,变为就绪状态。是否会持续很久?
- Ready→Running:处于就绪状态的进程被进程调度程序选中后,就分配到处理机上来运行。
- Running → Exit:当进程表示它已经完成或者因出错,当前运行进程会由操作系统作结束处理。
- Running → Ready:处于运行状态的进程在其运行过程中,由于分配给它的处理机时间片用完而让出处理机。谁完成?
- Runing → Blocked:当进程请求某样东西且必须等待时。例如?
- Blocked → Ready:当进程要等待某事件到来时,它从阻塞状态变到
- 就绪状态。例如?
1.9 进程挂起
1.9.1 解释
进程挂起是一种合理且充分地利用系统资源的方式。挂起时,进程没有占用内存空间,处于挂起状态的吧进程映像在磁盘上。
- 阻塞挂起状态(blocked-suspend):进程在外存并等待某事件的出现
- 就绪挂起状态(ready-suspend):进程在外存,但只要进入内存,即可运行
1.9.2 状态队列
- (1)状态队列是由操作系统来维护的一组队列,用来表示系统当中所有进程的当前状态;
- (2)不同的状态分别用不同的队列来表示(就绪队列,各种类型的阻塞队列等);
- (3)每个进程的PCB都根据它的状态加入到相应的队列当中,当一个进程的状态发生变化时,它的PCB从一个状态队列中脱离,加入到另一个状态队列里。
图示
2 线程
2.1 为什么使用线程
- 实体间能够并发地执行;
- 实体之间共享相同的地址空间。
2.2 线程的定义
线程:进程中的一条执行流程。
进程 = 资源管理 + 线程
2.3 线程的优点:
- 一个进程中可以同时存在多个线程;
- 各个线程之间可以并发的执行;
- 各个线程之间可以共享地址空间和文件等资源。
2.4 线程的缺点:
一个线程崩溃,该进程的所有线程崩溃。
2.5 线程和进程的比较
- 进程是资源分配的单位,线程是CPU调度单位;
- 进程拥有完整的资源平台,而线程只占有必须的资源,如寄存器,栈。
- 线程同样由就绪,阻塞,执行三种基本状态,同样具有状态之间的转换关系。
- 线程能减少并发执行的时间和空间开销:
- (线程的创建时间/终止时间/(同一进程内)切换时间更小;同一进程内各线程共享内存和文件资源,可直接进行不通过内核的通信)。
2.6 线程的实现
有三种线程实现的方法,
- 用户线程:在用户空间实现,例如POSIX Pthreads, Mach C-threads, Solaris threads。
- 内核线程:在内核中实现,例如Windows, Solaris, Linux。
- 轻量级线程:在内核中实现,支持用户线程,例如Solaris。
2.6.1 用户线程
- 在用户空间实现的线程机制,不依赖于操作系统的内核;
- 由一组用户级的线程库来完成线程的管理,包括创建/终止/同步/调度;
- .由于用户线程的维护由相应进程来完成(通过线程库函数),不需要操作系统内核了解用户线程的存在,可用于不支持线程技术的多进程操作系统;
- .每个进程都需要它自己私有的线程控制块(TCB) 列表,用来跟踪记录它的各个线程的状态信息(PC、 栈指针、寄存器),TCB由线程库函数来维护; .
- 用户线程的切换也是由线程库函数来完成,无需用户态/核心态切换,所以速度特别快;
- 允许每个进程拥有自定义的线程调度算法。
用户线程优点
- 不需要操作系统内核了解用户线程的存在,可用于不支持线程技术的多进程操作系统;
- 每个进程都需要它私有的线程控制块TCB列表,来跟踪记录它各个线程的状态信息(PC/栈指针/寄存器),TCB由线程库函数来维护;
- 用户线程的切换由线程库函数实现,无需 用户态/核心态切换,所以速度快;
- 允许每个进程有自定义的线程调度算法。
缺点
- 如果一个线程发起系统调用而阻塞,则整个进程都在等待;
- 如果一个线程开始运行,除非它主动交出CPU,否则该线程所在进程的其它线程都无法运行;
- 由于时间片分配给的是进程,所以与其它进程相比,在多线程执行时,每个线程得到的时间片较少,执行会较慢。
2.6.2 内核线程
是指在操作系统的内核中实现的一种线程机制,由操作系统的内核来完成线程的创建,终止和管理。
- 由内核维护进程和上下文信息,也就是进程/线程控制块PCB/TCB;
- 线程的创建/终止/切换都是通过系统调用或内核函数来实现(内核实现),所以系统开销大;
- 在一个进程中,如果某个内核线程发起系统调用而阻塞,不会影响其它内核线程的运行;
- 时间片分配给线程,多线程的进程能获得更多的CPU时间;
- Windows NT/2000/XP 支持内核线程。
2.6.3 轻量级线程
他是内核支持的用户线程。一个进程可以有一个或多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持(Solaris/Linux)。
3 上下文切换
上下文切换上停止当前运行的进程(从运行态改变成其它状态)并且调度其它进程(转变成运行态)。
- 必须在切换之前储存许多部分的进程上下文;
- 必须能够在之后恢复他们,所以进程不能显示它曾经被暂停过;
- 必须快速(因为上下文切换非常频繁)。
需要储存什么上下文:
- 例如寄存器(PC/SP/…),CPU状态,…
- 一些时候可能会费时,所以需要尽量避免。
4 进程控制
4.1 创建进程
4.2 加载和执行进程
总结:
- 就是通过fork创建一个子进程,子进程在拷贝父进程中内存和寄存器时,会出现时间开销,可以通过两个方法解决,一个是创建一个vfork ,就是不进行拷贝操作;第二个就是进行Copy On Write(写时复制,读时映射),如果不进行写操作,就读原进程的内容,只有当发生写操作时,才进行拷贝。
- 当执行了exec后,就会出现两个进程,加载新进程取代当前运行的进程,如此一来,main的执行结果就会发生改变。
4.3 等待和终止进程
子进程自己无法实现资源的全部释放,例如PCB(唯一标识进程的)就无法释放,因此在子进程结束后,也就是调用了exit后,会返回父进程,如果此时父进程正好在wait,那么父进程会帮助子进程完成资源的回收。
wait()
exit()
回顾来看流程图