进程的概念,组成特征
知识总览
定义
程序段、数据段、PCB三部分组成了进程实体(进程映像)。
我们一般把进程实体简称为进程。
PCB是进程存在的唯一标志
如:创建进程,是创建进程实体中的PCB;撤销实体是撤销PCB。
从不同的角度,进程可以有不同的定义:
1.进程是程序的一次执行过程
2.进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
3.进程是具有独立功能的程序在数据集合上运行的过程(强调“动态性”它是系统进行资源分配和调度的一个独立单位。
引入进程实体的概念后,可把进程定义为:
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
注:严格来说,进程实体和进程不同。进程实体是静态的,进程是动态的。不过,除非题目专门考察二者区别,否则可以认为进程实体就是进程。
组成
进程由程序段、数据段、PCB组成。
组成:
组织
链接方式:
索引方式:
特征
总结
进程的控制
知识总览
什么是进程控制
进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。
简化理解:进程控制是要实现进程状态转换。
如何实现进程控制
原语
用原语实现进程控制。
原语的特点是:执行期间不允许中断,只能一气呵成。
原语采用“关中断指令”和“开中断指令”实现。
原语运行在核心态。
开/关 中断指令权限很大,是只能在核心态下执行的特权指令。
程序开头->程序结尾开关中短指令
控制相关的原语
进程创建原语:
进程终止原语:
进程阻塞和唤醒原语:成对使用
切换原语:
结合程序是如何运行的来理解:
通过PCB 保存信息, 来达到防止切换进程,导致PSW, PC, IR内容被覆盖,
(这里的PCB有点像程序计数器的意思?)
总结
无论哪个进程控制原语,要做的无非三类事情:
- 更新PCB中的信息
- 将PCB插入合适的队列
- 分配/回收资源
进程通信
进程间通信(Inter-ProcessCommunication,IPC)是指两个进程之间产生数据交互。
为什么需要操作系统支持
一个进程不能访问其他进程的空间,比如垃圾软件访问你微信,不久g了。
共享存储
通过一个共享存储区来实现共享存储
基干存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信:
基于数据结构的天享:比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式
消息传递
- 直接通信方式
进程P发消息到操作系统的内核中, Q在其中找P的消息,找到之后放到进程Q的地址空间中。
- 间接通信方式
进程P将信息发送到信箱A中, 进程Q从信箱取出来。
相比直接通信方式,间接通信方式可以在一个信箱recive来自多个进程的消息,而直接通信是点名到姓的方式来进行。
- 管道通信方式
FIFO,类似于队列。本质就是在内存中开辟一个大小固定的缓冲区。
这里的管道缓冲区可以理解为一个循环队列。
和共享内存有什么区别呢?
管道通信是先进先出。
- 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
- 各进程要互斥地访问管道(由操作系统实现)
- 当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
- 当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
- 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:①一个管道允许多个写进程,(1个读进程2014年408真题高教社官方答案);②允许有多个写进程,多个读进程,但系统会让各个个读进程轮流从管道中读数据(Linux 的方案)。
知识点梳理
内存缓冲区
半双工通信
互斥访问管道
写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据 读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据
线程的概念
为什么引入线程
传统的进程,只能串行的去处理程序,程序执行流的最小单位是进程。
引入线程后,线程成为执行流的最小单位,增加了并发度。
可以把线程理解“轻量级进程”。 线程是一个基本的CPU执行单元,也是程序执行流的最小单位。 引入线程之后,不仅是进程之间 可以并发,进程内的各线程之间 也可以并发,从而进一步提升了 系统的并发度,使得一个进程内 也可以并发处理各种任务(如QQ视频、文字聊天、传文件) 引入线程后,进程只作为除CPU之 外的系统资源的分配单元(如打 印机、内存地址空间等都是分配给进程的)
引入线程机制后有什么变化
线程的属性
线程的实现方式和多线程模型
线程的实现方式
早期
早期没有_线程,通过线程库来实现“逻辑”的的线程。比如:_
用户级线程管理操作不是由操作系统完成的,而是通过程序来完成的。
- 用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)
- 用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
- 在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。“用户级线程” 就是“从用户视角看能看到的线程”
- 优缺点
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞, 并发度不高。多个线程不可在多核处理机上并行运行。
现代
- 一对一
- 多对一
- 多对多
知识回顾
线程的状态与转换
状态与转换
组织与控制
主要根进程的PCB类似。
堆栈指针 主要记录,比如a调用b, 值赋给c这些,
堆栈指针,指的是内存中的堆栈。
处理机调度
当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。这就需要确定某种规则来决定处理
这些任务的顺序,这就是“调度”研究的问题。
高级调度
低级调度
低级调度(进程调度/处理机调度)一—按照某种策略从就绪队列中选取一个进程,将处理机分配
给它。
进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。
进程调度的频率很高,一般几十毫秒一次。
轮流的去cpu执行,用户感觉不到
中级调度
内存不够时,可将某些进程的数据调出外存。等内存空闲或者进程需要运行时再重新调入内存。暂时调到外存等待的进程状态为挂起状态。被挂起的进程PCB会被组织成挂起队列
中级调度(内存调度)一一按照某种策略诀定将哪个处上的进程重新调入内存。
补充
进程调度的时机切换与过程调度方式
进程调度时机
进程调度就是按照某种算法从就绪队列选择一个进程为其分配处理机。
注意什么时候需要进程调度,(主动放弃?/被动放弃?)
什么时候不能进行进程调度?
进程调度的时机
在内核临界区,访问资源会进行加锁,期间不能进行调度和切换。
在普通临界区,比如打印机,可以进行调度与切换。
所以真题说临界区不能进行处理机调度是错的,以偏概全。
进程调度的方式
进程的切换与过程
总结
进程的切换是有代价的,还有就是注意临界区的理解
调度器,闲逛进程
调度算法的评价指标
- CPU利用率
忙碌时间(CPU运行时间) / 总时间。
- 系统吞吐量
- 周转时间
作业完成时间 - 作业提交时间 越短越好
- 等待时间
对于进程来说,等待时间就是指进程建立后等待被服务的时间之和,在等待I/0完成的期间其实进程也是在被服务的,所以不计入等待时间。
- 响应时间
提交请求到首次产生响应
调度算法
- 运行态→等待态:等待使用资源;
- 如等待外设传输;等待人工干预。
- 等待态→就绪态:资源得到满足;
- 如外设传输结束;人工干预完成。
- 运行态→就绪态:运行时间片到;
先来先服务
公平,先来的先服务,不会导致后来的还跟先来的去一样的抢锁。
进程同步、互斥
进程同步、异步、临界区
进程同步就是为了解决异步读写操作带来的问题。
两种资源共享方式:
- 互斥共享(一段时间只允许一个进程)
- 同时共享(宏观上同时)
我们把一个时间段内只允许一个进程使用的资源称为临界资源。许多物理设备(比如摄像头、打印机)都属于临界资源。此外还有许多变量、数据、内存缓冲区等都属于临界资源。 对临界资源的访问,必须互斥地进行。互斥,亦称间接制约关系。进程互斥指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束,释放该资源之后,另一个进程才能去访问临界资源。
注意:临界区是进程中访问临界资源的代码段。进入区和退出区是负责实现互斥的代码段。临界区也可称为“临界段”。
为了实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则:
- 空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区;
- 忙则等待。当已有进程进入临界区时,其他试图进入临界区的进程必须等待;
- 有限等待。对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饥饿);
- 让权等待。当进程不能进入临界区时,应立即释放处理机,防止进程忙等待。
知识回顾
进程互斥的软件实现方法
知识点
如果没有进程互斥
如果两个进程同时操作一个资源,那么两个进程就混在一起了! 那么如何通过软件来避免进程互斥?
单标志法
但是这样会有一个问题。
如果P0进程执行完成,turn变为1
那么当临界区再次空闲, P0却出不去, 违反了空闲让进的原则
双标志先检查法
因为1,2 。 5,6 。 两步不是原子性,可能导致两个进程同时进入临界区
可以用硬件的方式保证这两步一气呵成!
双标志后检查法
可能P0,P1都无法进入临界区
Peterson算法
如果p0执行到3进不了临界区就应该立马放弃CPU资源, 但是这里会一直占用CPU资源,违反了让权等待的原则;
知识回顾
进程互斥方法
中断屏蔽方法
缺点是需要在同一个处理机上。
testAndSet
有点类似于CAS
若刚开始lock 是false,则TSL返回的old 值次false,while 循环条件不满足,直接跳过循环,述入临界区。若刚开始lock 是true,则执行TLS后old 返回的值为 true,while 循环条件满足,会一直循环,直到当前访问临界区的进程在退出区进行“解锁”。
相比软件实现方法,TSL指令把“上锁”和“检查”操作用硬件的方式变成了一气呵成的原子操作(while(TSL))。
优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境
缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。
Swap指令
跟TSL基本一样
自旋锁
知识回顾
信号量机制
总揽
很好的解决进程互斥/同步问题
信号量机制
用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。 信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。 原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。软件解决方案的主要问题是由“进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作都用“原语”实现,使这些操作能“一气呵成”就能避免问题。 一对原语:wait(S) 原语和 signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和 signal,括号里的信号量s其实就是函数调用时传入的一个参数。 wait、signal 原语常简称为P、V操作(来自荷兰语 proberen 和verhogen)。因此,做题的时候常把wait(S)、Signal(S) 两个操作分别写为P(S)、V(S)
整型信号量
有点类似于双标志先检查法,但是这里的while 和 s = s-1 是原语实现的,原语是通过开关中断指令实现的,所以这里就完美解决了双标志先检查法带来的判断和执行不能一气呵成的问题
记录型信号量
多了一个阻塞队列,资源足够,就从阻塞队列获取一个。
解决了让权等待的问题。
梳理
用信号量实现同步,互斥,前驱关系
总揽
信号量实现进程互斥
信号量实现进程同步
让各个并发进程顺序的进行
前V 后 P
实现前驱关系
应该是在实现同步关系之后的改进版
知识回顾
生产者-消费者问题
问题描述
主要是以缓冲区为媒介来实现生产消费的。
但是如果两个生产者进程同时放入缓冲区,可能就会导致覆盖。
full 和 empty都是信号量
对这些临界区来执行PV操作
如何解决问题
会发生死锁,因为当缓冲区已经放慢产品,生产者就不会再去放了, 但是mutex已经变为0了, 所以消费者也没有办法去消费, 所以就会导致发生死锁。
知识回顾
PV 操作题目的解题思路:
- 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
- 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
3.'设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为 1,同步信号量的初始值要看对应资源的初始值是多少)生产者消费者问题是一个互斥、同步的综合问题。 对于初学者来说最难的是发现题目中隐含的两对同步关系。 有时候是消费者需要等待生产者生产,有时候是生产者要等待消费者消费,这是两个不同的“一前一后问题”,因此也需要设置两个同步信号量。
多生产者-多消费者
管程
总揽
为什么引入管程
管程是一种特殊的软件模块,有这些部分组成:
- 局部于管程的共享数据结构说明;
- 对该数据结构进行操作的一组过程;
- 对局部于管程的共享数据设置初始值的语句;
- 管程有一个名字。 跨考Tips:“过程〞其实就是“函数” 管程的基本特征:
- 局部于管程的数据只能被局部于管程的过程所访问;
- 一个进程只有通过调用管程内的过程才能进入管程访问共享数据;
- 每次仅允许一个进程在管程内执行某个内部过程。
用管程解决生产者消费者问题
总之就是避免发生并发问题。
来点跟Java有关的
- sychronized其实就事管程实现的
知识回顾
死锁
什么是死锁
在并发环境下,各进程因竞争资源而造成的一种互相等待对方手里的资源,导致各进程都阻塞,都无法向前推进的现象,就是“死锁”发生死锁后若无外力干涉,这些进程都将无法向前推进。 比如:经典的哲学家进餐问题
死锁、死循环、饥饿的区别
什么时候会发生死锁
-
对系统资源的竟争。各进程对不可剥夺的资源(如打印机)的竞争可能引起死锁,对可剥夺的资 原(CPU)的竟争是不会引起死锁的。 2.进程推进顺序非法。请求和释放资源的顺序不当,也同样会导致死锁。例如,并发执行的进程P1、 P2 分别申请并占有了资源 R1、R2,之后进程P1又紧接着申请资源R2,而进程P2又申请资源R1, 两者会因为申请的资源被对方占有而阻塞,从而发生死锁。
-
信号量的使用不当也会造成死锁。如生产者-消贵者问题中,如果实现互斥的P操作在实现同步的
p操作之前,就有可能导致死锁。(可以把互斥信号量、同步信号量也看做是一种抽象的系统资 源) 总之,对不可剥夺资源的不合理分配,可能导致死锁。
梳理
预防死锁
死锁必须满足四个条件
最常见的并且可行的就是使用资源有序分配法,来破环环路等待条件。
Java中怎么排查死锁?
步骤一:使用jsp查找程序进行 jps:jdk提供的一个工具,可以查看到正在运行的java进程
步骤二:使用jstack查看线程堆栈信息 jstack:jdk提供的一个工具,可以查看java进程中线程堆栈信息。 更详细的用法见文档最后。
$ jstack 96521复制代码 从上面的堆栈信息中我们可以发现这个内容:“Found one Java-level deadlock”,表示程序中发现了一个死锁,后面包含更多详细的信息,重点下面: 死
锁的代码是在DeadLock.java的32行和18行,此时我们就可以去优化代码,解决死锁问题。
还可以通过jconsole