1 简介
进程:系统进行资源分配的最小单位
一个进程拥有的资源有⾃⼰的堆、栈、虚存空间(页表)、文件描述符等信息。
进程是操作系统对一个正在运行的程序的一种抽象,可以把进程看作程序运行的一次运行过程。
程序VS进程:
· 程序是在一个静态磁盘上的一个可执行文件。
· 进程是将可执行文件加载到系统中。加载就是将信息放在内存中,分配一些资源,并且执行程序中所有指令。
进程的本质:PCB(Process Control Block),包含以下内容:
- PID:进程ID,进程唯一身份标识,不固定,每次启动进程时动态分配
- 进程状态:①新建状态(NEW) ②就绪状态 ③运行状态 ④阻塞状态 ⑤销毁状态
- 优先级:决定进程的执行顺序
- 记账信息:保证进程执行的公平性,它记录CPU调用次数和执行间隔,为进程调度器提供数据支持,规避进程饿死
- 上下文信息:保存本次的执行状态,以便下次执行
- 一组内存:指定进程需要使用的资源
线程:系统进行CPU 调度、独立运算的最小单位
是进程中实际运行的单位。一个进程中可以并发多个线程,每个线程执行不同的任务 。
2 进程和线程的区别
- 地址空间:不同进程的地址空间相互独立,同一进程内的线程共享同一地址空间;一个进程的线程在另一个进程内是不可见的
- 开销不同:进程的创建、销毁和切换的开销都远大于线程
- 资源不同:每个进程有自己的内存和资源,一个进程中的线程会共享这些内存和资源
- 控制和影响能力不同:子进程无法影响父进程,而子线程可以影响父线程,如果主线程发生异常会影响其所在进程和子线程。
- CPU利用率不同:进程的CPU利用率较低,因为上下文切换开销较大,而线程的CPU的利用率较高,上下文的切换速度快。
- 操纵者不同:进程的操纵者一般是操作系统,线程的操纵者一般是编程人员
3 通信
不同进程之间的通信:管道、消息队列、共享内存、信号量(PV操作)、信号、套接字
同一进程中线程之间的通信:互斥锁、读写锁、条件变量、信号量
3.1 线程共享资源
注:线程运行的本质是函数的执行
线程私有:线程上下文
- 栈区:保存函数的返回值、调用其他函数的参数、该函数使用的局部变量以及函数使用的寄存器信息
- 程序计数器:保存指令地址,通过程序计数器可以知道下一条需要执行的指令
- 每个线程用户独立的线程ID、独立的调度优先级、错误返回码
- 线程局部存储(Thread Local Storage,TLS)
- 存放在该区域的变量是全局变量,所有线程都可以访问
- 但该全局变量独属于一个线程,一个线程的对此变量的修改对其他线程不可见
- 即线程局部存储可以让线程拥有一个独属于线程的全局变量
- 虽然该变量可以被所有线程访问,但是该变量在每个线程中都有副本,一个线程对变量的修改不会影响其他线程
线程共享进程地址空间中除线程上下文信息中的所有内容
线程共享:
- 代码区:程序中任何一个函数都可以放在线程中执行,不存在某个函数只能放在特定线程中执行的情况
- 数据区:存放全局变量和静态变量
- 在程序员运行期间,也就是run time,数据区中的全局变量有且仅有一个实例,所有的线程都可以访问到该全局变量
- 堆区:malloc或new出来的数据。
- 只要知道变量地址(指针),任何线程可以访问指针指向的数据
- 栈区:虽然抽象概念上,栈区是线程私有,但是实际实现上,也有共享的可能(不常见)
- 线程的栈区没有严格的隔离机制
- 如果一个线程能获得另一个线程栈帧的指针,则该线程可以改变另一个线程的栈区,即可以修改另一个栈区的变量
- 虽然该方法可以带来便利,但是极难排查BUG
- 动态链接库:进程中所有线程都可以使用动态链接库中的代码
- 打开的文件:程序在运行时打开的文件
- 线程共享当前工作目录、以及用户ID和组ID
4 进程调度算法
注:注意进程调度算法和磁盘调度算法的不同
4.1 先来先服务算法(FCFS,First Come First Service)
- 算法规则:按照作业/进程先后顺序进行服务。顾名思义,就是先来的先为你服务,类似于生活中的银行叫号排队,和排队买奶茶。
- 算法思想:从公平的角度考虑
- 优点:公平
缺点:没有考虑作业的运行时间,不利于短作业进程
4.2 短作业优先算法(SJF,Short Job First)
- 算法规则:要求服务时间短的进程优先得到服务。
- 算法思想:追求最少的平均等待时间,平均周转时间和平均带权周转时间。
- 优点:平均等待时间,平均周转时间更短。
缺点:没有考虑等待时间,对短作业有利,对长作业不利,如果有短进程不断加入就绪队列,长进程会长时间得不到服务,会产生饥饿现象,如果一直得不到服务则服务被“饿死”。
4.3 高响应比优先算法
- 算法规则:在每次准备调度时,计算各进程的响应比(响应比:等待时间+服务时间 /服务时间)
- 算法思想:总和考虑进程的等待时间和服务时间。
- 优缺点:总和考虑了等待时间和服务时间的问题。
等待时间相同时,服务时间短的优先(短作业优先的优点),
服务时间相同时,等待时间长的优先(先来先服务的优点),对于长作业来说随着等待时间越来长,响应比也回越来越大,避免了长作业饥饿的问题。
总结:这三种算法只根据公平,平均等待时间,平均周转时间等来评价系统的整体性能指标,不关心响应时间和任务的紧急陈程度,对于用户来说,交互性很差,所以这三种算法只适用于早期的批处理系统。
4.4 优先级调度算法
- 算法规则:调度时选择优先级最高的进程或者作业。
- 算法思想:要根据任务的紧急程度来决定处理顺序。
4.4.1 进程优先级
优先级种类:
- 静态优先级
- 优先级是在创建进程时确定的,且在进程的整个运行期间保持不变。确定静态优先级的主要依据有进程类型、进程对资源的要求、用户要求。
- 动态优先级
- 在进程运行过程中,根据进程情况的变化动态调整优先级。动态调整优先级的主要依据有进程占有 CPU 时间的长短、就绪进程等待 CPU 时间的长短。
- 在进程运行过程中,根据进程情况的变化动态调整优先级。动态调整优先级的主要依据有进程占有 CPU 时间的长短、就绪进程等待 CPU 时间的长短。
优先级进程调度算法,是把处理机分配给就绪队列中优先级最高的进程。
- 非抢占式(非剥夺式)优先级调度算法
- 当一个进程正在处理机上运行时,即使有优先级更高进程进入就绪队列,仍然让正在进行的进程继续运行,直到由于其自身原因而主动让出处理机(任务完成或等待事件),才把处理机分配给更为重要或紧迫的进程
- 抢占式(剥夺式)优先级调度算法
- 当一个进程正在处理机上运行时,若有某个更为重要或紧迫的进程进入就绪队列,则立即暂停正在运行的进程,将处理机分配给更重要或紧迫的进程
4.5 时间片轮转算法
- 算法规则:按照各进程到达就绪队列的顺序,轮流让每个进程执行一个时间片,如果进程在一个时间片内没有执行完,则剥夺处理器,将进程重新放到就绪队列的尾部。
- 算法思想:公平地,轮流地为某个进程服务,让每一个进程在一定时间内都能得到响应。
4.6 多级反馈队列算法
- 算法规则:
- 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。
- 新进程到达时,放入第一级队列,按照先来先服务原则排队等待被分配时间片,若时间片用完进程还未执行完,则放到下一级就绪队列尾部,如果已经实在最低级队列,则重新放到队列尾。
- 只有第k级队列为空时,才会为k+1对头的进程分配时间片。
- 算法思想:对其他算法的权衡。
5 死锁
5.1 死锁产生条件
- 互斥条件:资源具有排他性,即同一时间只能有一个进程可以占据该资源
- 请求保持条件:当进程因申请资源而阻塞时,对已获得的资源保持不放
- 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时自己释放
- 环路等待条件:在发送死锁时,必定存在一个进程-资源的环形链路
5.2 解决死锁的方法
- 预防死锁
- 避免死锁
- 检查死锁
- 解除死锁