暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一文搞透进程底层原理-操作系统

阿斌Java之路 2022-06-18
1036

操作系统中最重要的一个概念,就是进程,也是对于应用程序员最重要的一块知识点。本章将刨析进程相关的所有知识点,将进程串联起来。

进程创建

进程在创建的时候,操作系统会将磁盘上的程序和数据加载进内存

进程的内存结构大致如下

img

我们可以通过**fork()**调用创建一个新的进程,子进程创建之初,基本拷贝了父进程的运行环境,包括后续的代码,唯一不同的是fork返回值,返回为0的是子进程,父进程会返回子进程的pid。我们可以根据返回值让父子进程走到不同逻辑的 代码段上。

img

运行以上代码段,将看到如下输出

img

进程状态

img

进程状态常分为五种:

  • 创建态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态
  • 就绪态:进程已经准备好,已分配到所需资源,只要分配到CPU就能够立即运行
  • 运行态:进程处于就绪状态,进入就绪队列,被调度后,进程进入执行状态
  • 阻塞态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞,进入阻塞队列。在满足请求时进入就绪状态等待系统调用
  • 终止态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行。

PCB (Process Control Block)被称作进程控制块,也是操作系统对进程进行控制与管理的唯一方式。PCB存放了有关进程的相关信息:

1.程序ID(PID、进程句柄):它是唯一的,一个进程都必须对应一个PID。PID一般是整形数字

2.特征信息:一般分系统进程、用户进程、或者内核进程等

3.进程状态:运行、就绪、阻塞,表示进程现的运行情况

4.优先级:表示获得CPU控制权的优先级大小

5.通信信息:进程之间的通信关系的反映,由于操作系统会提供通信信道

6.现场保护区:保护阻塞的进程用

7.资源需求、分配控制信息

8.进程实体信息,指明程序路径和名称,进程数据在物理内存还是在交换分区(分页)中

9.其他信息:工作单位,工作区,文件信息等

操作系统对进程的控制 ,实际上是对PCB的控制,进程状态的转换,实际上也是PCB中状态标志位的变换,相关的就绪队列,阻塞队列,以及上下文切换的环境保存,实际上都是通过PCB实现

img

用户态内核态切换

凡是涉及到IO读写、内存分配等硬件资源的操作时,往往不能直接操作,而是通过一种叫系统调用的过程,让程序从用户态陷入到内核态运行。

这是因为在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。

这一类指令,我们称为特权指令,在执行特权指令,我们需要从用户态切换到内核态进行系统调用。

而用户态到内核态的切换是有一定的开销的,具体来说有以下几点

  • 保留用户态现场(上下文、寄存器、用户栈等)
  • 复制用户态参数,用户栈切到内核栈,进入内核态
  • 额外的检查(因为内核代码对用户不信任)
  • 执行内核态代码
  • 复制内核态代码执行结果,回到用户态
  • 恢复用户态现场(上下文、寄存器、用户栈等)

上下文切换

img

cpu切换

就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。

系统调用

在执行特权指令时,需要从用户态切换成内核态。就发生了 CPU 上下文切换,整个过程是这样的:1、保存 CPU 寄存器里原来用户态的指令位 2、为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。3、跳转到内核态运行内核任务。4、当系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。

所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。(用户态-内核态-用户态)。

系统调用的切换,也叫特权模式切换。

进程上下文切换

首先,进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。

因此,进程的上下文切换就比系统调用时多了一步:在保存内核态资源(当前进程的内核状态和 CPU 寄存器)之前,需要先把该进程的用户态资源(虚拟内存、栈等)保存下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。

虚拟内存,就是逻辑内存到实际内存的一种映射关系,也可以理解为是 页表

线程上下文切换

相同进程间的线程,是共享页表(虚拟内存)的。所以线程间的上下文切换,省去了虚拟内存的切换 ,线程有自己私有的栈,的寄存器。切换这些即可。

进程的调度

操作系统其实也是一个程序,如果一个程序在cpu上运行,那么就意味着操作系统没有运行。那么操作系统如果重新获得cpu的控制权?

实际上这个问题很早就有了答案 ,通过时钟中断。有了时钟中断,操作系统重新获得了控制权,就可以做它想做的任何事,比如切换进程。

回顾上文的图,就绪队列中那么多等待运行的进程,操作系统改如何调度,能让它们看起来像并行一样的运行,是本节需要讨论的问题。

调度指标:

  • 周转时间=任务完成时间-到达时间
  • 响应时间=首次运行时间-到达时间

基于周转时间:

  • 先进先出-FIFO

  • 最短任务优先-SJF

  • 最短完成时间优先-STCF

基于响应时间:

  • 时间片轮转-RR

以上的算法各有优缺点,所以一个综合的调度算法出现了多级反馈队列-MLFQ,该算法将进程分为了多个优先级的队列。

img

多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。

他有以下规则

就绪队列1的优先级大于就绪队列2

  1. 如果在相同的就绪队列上,轮转运行
  2. 工作 放入系统时,会在最高优先级(最上层队列)
  3. 工作用完整个时间片后,降低优先级(移入下一层队列)
  4. 如果在时间片内主动释放cpu,优先级不变
  5. 一段时间后,所有队列都重新加入最高优先级(避免进程饥饿)

其实根据作业完成的过程中是否会被打断,又分为非抢占式和抢占式调度 。JVM采用的是抢占式调度策略。

多处理器调度

前面我们讨论的进程调度都基于单cpu单核的情况下,然而在现实中,单个cpu会有多核的处理器,多处理器的调度更加复杂。

为了加速cpu的运行,cpu都配备了高速缓存,缓存中有的数据就不需要去内存中读取了。

img

有了缓存就涉及到缓存一致性的问题

通过监控内存访问,在基于总线的系统中 ,通过总线窥探(bus snooping)的方式监听 链接所有的缓存的内存的总线,如果cpu发现他们缓存中的数据被更新,就会 作废本地缓存,或者重新更新本地缓存。

在进行上下文切换的情况下,我们还需要考虑不同cpu中,缓存的亲和度问题。比如我们会更偏向同一进程,在相同的cpu中调度和切换,避免高速缓存的命中率下降。还有同一进程中的线程,也尽量在相同cpu下调度。

进程通信

img

一,共享存储:

1,什么是共享存储

操作系统提供了一个共享空间可以被进程1,2互斥的访问

2,分类

1)基于数据结构的共享:比如共享空间只能存放一个长度为10的数组。这种共享方式速度慢,限制多,是一种低级的通信方式

2)基于存储区的共享:在内存中画出一块共享存储区,数据的形式,存放的位置都由进程控制,而不是操作系统。相比之下它的速度更快,是一种高级通信方式

二,消息传递:

1,什么是消息传递

进程中的数据交换以“格式化消息“为单位,进程通过操作系统提供的”发送消息、接收消息“两个源语进行数据交换

2,格式化消息的结构:

1)消息头:包括发送进程的ID,接收进程的ID,消息类型,消息长度等格式化信息

2)消息体:记录被发送的信息

3,分类:

1)直接通信方式:比如进程1,给进程2发信息,就把信息挂到进程2的信息缓存队列上

2)间接通信方式:进程1把消息放到一个中间实体上,等待需要它的进程2取走

三,管道通信:

1,什么是管道

是指用于连接读写进程的一个共享文件,是在内存中开辟了一个固定大小的缓冲区

2,特点:

1)管道只能采用半双工通信,在一段时间只能单向传输,如果要实现双向传输,就需要设置两个管道

2)各个进程需要互斥的访问管道

3)数据以字符流的形式写入管道,当管道写满时,写进程将被堵塞,等待数据被取走。当数据全部被取出后,管道变空,此时写进程的系统调用将被堵塞。

4)如果没写满,就不允许读,没有读空,就不允许写

5)速度一旦读出,就从管道中被抛弃,这就意味着读进程只能有一个,否则可能会发生读错数据的情况

进程同步

上文的进程通信,我们需要保证进程间互斥的访问共享存储。以及在多进程并发的情况下,我们需要做到进程间的互斥以及同步,控制 进程执行的顺序,这要怎么实现呢?

可以通过信号量来实现进程同步

(1) 信号量就是一个变量,表示系统中某种资源的数量

(2) 用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作

(3) 一对原语是:wait(S)原语和signal(S)原语,S是信号量 (将此对原语理解为函数)

(4) 通常将wait(S)称为P操作,写为P(S);通常将signal(S)称为V操作,写为V(S)

img

我们也可以通过操作系统提供的互斥量Mutex实现互斥。java  synchronize底层用的就是互斥量。

信号量和互斥量的区别

  1. 互斥量用于线程的互斥,信号量用于线程的同步
  2. 互斥量值只能为0/1,信号量值可以为非负整数
  3. 互斥量的加锁和解锁必须由同一线程分别对应使用(解铃还须系铃人),信号量可以由一个线程释放,另一个线程得到
  4. 信号量也可以实现互斥效果

死锁

形成死锁的四大必要条件:

1、 互斥条件

进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

2、不可剥夺条件:

进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。

3、 请求与保持条件

进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

4、循环等待条件:

存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, …, pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, …, n-1),Pn等待的资源被P0占有,

死锁,死锁条件,死锁策略,死锁检测,死锁恢复

处理死锁的方法

预防死锁
:通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来防止死锁的发生。

避免死锁
:在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免死锁的发生。

检测死锁
:允许系统在运行过程中发生死锁,但可设置检测机构及时检测死锁的发生,并采取适当措施加以清除。

解除死锁
:当检测出死锁后,便采取适当措施将进程从死锁状态中解脱出来。

预防死锁

破坏“互斥”条件:

就是在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。但一般来说在所列的四个条件中,“互斥”条件是无法破坏的。

破坏“占有并等待”条件:

破坏“占有并等待”条件,就是在系统中不允许进程在已获得某种资源的情况下,申请其他资源。即要想出一个办法,阻止进程在持有资源的同时申请其他资源。

方法一
:一次申请所需的全部资源,即 “ 一次性分配”。

方法二
:要求每个进程提出新的资源申请前,释放它所占有的资源。即“先释放后申请”。

破坏“不可抢占”条件

破坏“不可抢占”条件就是允许对资源实行抢夺。

方法一
:占有某些资源的同时再请求被拒绝,则该进程必须释放已占有的资源,如果有必要,可再次请求这些资源和另外的资源。

方法二
:设置进程优先级,优先级高的可以抢占资源。

破坏“循环等待”条件

将系统中的所有资源统一编号,所有进程必须按照资源编号顺序提出申请。

避免死锁

加锁顺序
:线程按照一定的顺序加锁。

加锁时限
:线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁。

死锁检测
:每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

检测死锁

一般来说,由于操作系统有并发,共享以及随机性等特点,通过预防和避免的手段达到排除死锁的目的是很困难的。这需要较大的系统开销,而且不能充分利用资源。为此,一种简便的方法是系统为进程分配资源时,不采取任何限制性措施,但是提供了检测和解脱死锁的手段:能发现死锁并从死锁状态中恢复出来。因此,在实际的操作系统中往往采用死锁的检测与恢复方法来排除死锁。

可了解相关的死锁检测算法

解除死锁

资源剥夺法
:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。

撤销进程法
:强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。

进程回退法
:让一(多)个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点

参考

https://zhuanlan.zhihu.com/p/52845869






END



后台回复关键词 操作系统 获取今日推荐资料

微信8.0新增了一万的好友数,之前没加上好友的可以加一下我的个人微信,再晚又满了,一起抱团取暖结伴内卷。



扫码拉群,学习打卡,交流经验


每周一读




文章转载自阿斌Java之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论