进程管理-基础知识
进程和线程的区别是什么?并行和并发的区别是什么?进程的状态有哪些?
进程
进程状态
- 运行状态:进程正在占用CPU;
- 就绪状态:可运行,由于等待CPU时间片;
- 阻塞状态:进程正在等待某一时间的发生而暂时停止运行,这个时候即使给它CPU控制权也不能运行;
- 创建状态:进程正在被创建时的状态;
- 结束状态:进程正在从系统中消失时的状态;
为了避免被阻塞的进程一直占用物理内存造成资源浪费,操作系统通常会把阻塞状态的进程的物理内存空间换出到磁盘,等需要再次运行的时候,再从磁盘换入到物理内存;
- 阻塞挂起状态:进程在磁盘中,并等待某个事件的出现;
- 就绪挂起状态:进程在磁盘中,并且只要进入内存就立即运行;
导致进程被挂起的原因有:
- 进程所使用的内存空间不在物理内存,而在磁盘中;
- 通过sleep让进程间歇性挂起;
- 用户通过
Ctrl+Z挂起一个程序的执行;
进程控制
操作系统中,通过进程控制块(PCB)数据结构来描述进程;PCB是进程的唯一标识;PCB包含以下信息:
- 进程描述信息
- 进程标识符:每个进程都有一个并且唯一的表示符;
- 用户标识符:标识进程所属的用户,用于共享和保护;
- 进程控制和管理信息
- 进程当前的状态:运行/就绪/阻塞/创建/结束;
- 进程优先级:进程抢占CPU时的优先级;
- 资源分配清单
- 有关内存地址空间或者虚拟地址空间的信息,打开的文件列表以及使用的I/O设备信息;
- CPU相关信息
- CPU中各个寄存器的值,当进程切换的时候,CPU的状态信息会保存在相应的PCB中,用于上下文切换;
PCB是怎么组织和控制的?
- 通过链表的方式组织,把具有相同状态的进程链接在一起,组成队列;
- 所有处于就绪状态的进程链接在一起组成就绪队列;
- 所有处于阻塞状态的进程链接在一起组成阻塞队列;
进程是怎么控制的?
- 创建进程
- 申请一个空白的PCB,并向PCB中填写一些控制和管理进程的信息;
- 为进程分配运行时所需要的资源,如内存资源;
- 将PCB插入到就绪状态,等待被调度;
- 终止进程
- 查找需要终止进程的PCB;
- 如果进程处于执行状态,则立即终于进程的运行,并将CPU资源分配给其他进程;
- 如果该进程有其他的子进程,则将子进程交给1号进程接管;
- 将该进程的所有资源归还给操作系统;
- 将其从PCB所在队列中删除;
- 阻塞进程
- 找到将要被阻塞进程标识号对应的PCB;
- 如果进程正在运行,则保护现场,并将状态转为阻塞态,停止运行;
- 将PCB插入到阻塞队列中;
- 唤醒进程
- 在事件的阻塞队列中找到相应进程的PCB;
- 将其从阻塞队列中移除,并将状态改为就绪状态;
- 将PCB插入到就绪状态中,等待系统调度运行;
进程的创建
- 操作系统运行程序的第一件事是将代码和所有的静态数据加载(load)到内存中,加载到进程的地址空间中。
- 为程序的运行时栈,分配一些内存。C程序使用栈存放局部变量,函数参数,返回值。操作系统分配这些内存,并提供给进程。
- 操作系统也可能为程序的堆分配一些内存。
- 操作系统还将执行一些其他初始化任务,比如输入/输出相关的任务。
进程上下文切换
将进程的上下文信息保存到进程的PCB,当要运行另一个进程的时候,先从这个进程的PCB中取出上下文信息,恢复到CPU中,从而使得这个进程可以继续运行;
进程上下文包含:
- 虚拟内存,栈,全局变量等用户空间的资源;
- 内核堆栈,寄存器等内核空间资源;
进程上下文切换场景:
- 当某个进程的时间片用完时,进程从运行状态转换为就绪状态,系统从就绪队列选择另一个进程运行;
- 当系统资源不足时,要等到资源满足后才可以运行,此时进程被挂起,操作系统调度其他进程运行;
- 当进程通过睡眠函数sleep方法将自己主动挂起时,操作系统调度其他进程;
- 当优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程被挂起,运行高优先级进程;
- 当发生硬件中断时,CPU上的进程被中断挂起,转而执行内核中的中断服务程序;
线程
- 线程是进程中的一条执行流程,线程之间可以并发运行且共享相同的地址空间;
- 同一个进程内多个线程可以共享代码段,数据段,打开的文件等资源;
- 每个线程各自有一套独立的寄存器和栈,用来确保线程的控制流是相对独立的;
线程崩溃导致进程崩溃
线程比进程开销小
- 线程的创建时间比进程的快
- 进程在创建过程中需要资源管理信息,如内存管理信息,文件管理信息;
- 进程在创建过程中不涉及资源管理信息,而是共享它们;
- 线程的终止时间比进程的快
- 线程释放的资源比进程释放的资源少很多;
- 同一个进程的线程切换比进程切换快
- 进程在切换的时候,需要切换页表;
- 线程具有相同的虚拟地址空间,同一个进程的线程都具有同一个页表,切换时不需要切换页表;
- 同一个进程的各线程之间共享内存和文件资源
- 线程之间传递数据不需要经过内核,交换数据的效率更高;
进程的上下文切换
- 当两个线程不属于同一个进程的时候,上下文切换过程同进程的上下文切换过程;
- 当两个线程属于同一个进程的时候,虚拟内存这样的资源保持不动,只切换线程的私有数据,寄存器这些不共享的资源;
线程的实现
- 用户线程
- 内核线程
- 轻量级进程
用户线程
基于用户态的线程库实现,线程控制块也是在库中实现,对于操作系统而言看到这个线程控制块,只能看到整个进程的PCB;用户线程的整个线程的调度和管理,操作系统不直接参与,而是由用户级线程库来完成;
优点:
- 线程控制块由用户级线程库函数完成,可用于不支持线程技术的操作系统;
- 用户线程的切换也是由线程库函数来完成的,不需要用户态与内核态的切换,所以速度比较快;
缺点:
- 由于操作系统不参与线程的调度,当一个线程发起系统调用而阻塞,进程包含的其他用户线程也都不能执行了;
- 当一个线程开始运行后,除非它主动交出CPU使用权,否则他所在的进程当中的其他线程不能运行,因为用户态线程不能打断当前运行中的线程;
- 由于时间片分给进程,所以多线程执行的时候,每个线程得到的时间片比较少,执行会比较慢;
内核线程
由内核直接管理,每个线程对应一个内核调度实体;线程的创建/切换需要通过系统调用,需要内核的参与;
优点:
- 多核下同一进程的线程可并发执行;
- 线程阻塞不会影响其他线程;
缺点:
- 线程切换设计内核态切换,开销比较大;
- 每个线程需要独立的内核栈和TCP;
轻量级进程
轻量级进程(LWP)是建立在内核之上并由内核支持的用户线程,它是内核线程的高度抽象,每个轻量级进程都与一个特定的内核线程关联;本质是用户线程,所以轻量级线程可以共享地址空间,打开的文件等;并且与内核进程相关联,所以每个轻量级进程都可以作为独立单元由内核独立调度;
线程与进程之间的区别
- 线程是调度的基本单位,进程是资源调度的基本单位;
调度
进程的调度一般会有几个考虑因素,没有十全十美的调度算法,每个调度算法都有优缺点,根据应用场景的不同,选择合适的调度算法;
Linux系统:
- 默认采用完全公平调度器(CFS),基于红黑树动态管理进程的虚拟运行时间,优先调度累计CPU时间较少的进程;
- 实时任务支持两种策略:
- SCHED_FIFO:严格按优先级抢占,高优先级任务独占CPU直到完成;
- SCHED_RR:相同优先级任务按时间片轮转,避免饥饿;
Windows系统;
- 结合优先级调度和多级反馈队列,进程分为0-31优先级级别,动态调整优先级避免低优先级任务饥饿;
- 普通进程采用时间片轮转,实时任务可以抢占CPU控制权;
调度算法分类
- 抢占式调度算法:选择一个进程,只让该进程运行一个时间段,如果时间段结束时该进程还在运行,则会把该进程挂起,接着调度程序从就绪队列中挑选另一个进程运行,抢占式调度算法依赖时钟中断;
- 时间片轮转算法
- 优先级调度算法
- 多级反馈队列算法
- 非抢占式调度算法:选择一个进程,让这个进程运行直到被阻塞,或者直到退出才会调用另一个进程,非抢占式调度算法不依赖时钟中断;
- 先来先服务算法
- 短作业优先算法
- 高响应比优先算法
调度原则
- CPU利用率:CPU执行非空闲任务的时间占总时间的百分比;CPU繁忙时间比上总时间;
- 系统吞吐量:单位时间内完成的进程或事务数量;
- 周转时间:进程从提交到完成的总时间,包括运行,等待,阻塞时间;
- 等待时间:进程在就绪队列中的累计等待时间,不包含阻塞时间;
- 响应时间:用户请求到系统首次相应的时间间隔;
调度算法
- 先来先服务调度算法
- 最短作业优先调度算法
- 高响应比优先调度算法
- 时间片轮转调度算法
- 最高优先级调度算法
- 多级反馈队列调度算法
先来先服务算法
每次从就绪队列中选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行;
- 对长作业有利,适用于CPU繁忙型作业的系统
- 不适用于短作业,不适用于I/O繁忙型系统
最短作业优先调度算法
优先选择运行时间最短的进程来运行;
运行之前怎么知道进程的运行时间???
高响应比优先调度算法
每次进行进程的调度时,先计算响应比优先级,然后选择优先级最高的进程运行;
优先权 = (等待时间+要求服务时间)/要求服务时间
- 如果两个进程的等待时间相同,那么要求服务时间越短,响应比就越高,优先运行短作业进程;
- 如果两个进程的要求服务时间相同,那么等待时间越长,响应比就越高,使得长作业进程得以运行;