【JavaEE】详解 “进程”

1. 什么是进程

进程 (process),也叫做任务 (task),是一个抽象的概念。当我们双击一个应用程序,就会有一个进程在操作系统上运行,不妨打开你的任务管理器,里面就跑着一个个的进程。
在这里插入图片描述

进程屏蔽了一个程序运行的细节,实际上,一个应用程序运行起来需要各种文件的加载、调用各种硬件…这些操作系统都帮我们做好了,把它们都打包成了一个 “包”,也就是进程,这种假象正是通过抽象了一个进程的概念来完成的。因此我们平常要看一个应用程序是否正常运行,只需要观察这个进程即可,无需去观察它的底部细节。

同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。


2. 进程的管理

观察观察你的任务管理器,里面少说也同时跑着几十个进程。既然有这么多的进程在同时运行,就要把他们都安排明白了,这个活也交给了我们万能的操作系统。

首先,从何管理?

  1. 先描述:使用一个类 / 结构体,描述清楚这个东西的特征。
  2. 再组织:使用一个数据结构,把这些类 / 结构体都组织起来。

说到这里,你可能会有疑惑,类不是已经很好用了吗,为什么还要用结构体呢?

原因:类是面向对象语言的特征,在面向过程语言中是不存在的。进程管理是操作系统内核的功能,而操作系统内核又是 C 语言实现的,因此操作系统内核只认识 C 语言,C 语言中的结构体就是低配版的类。

这个结构体有一个专门的名字 -> PCB(进程控制块)(敲黑板,这个名字很重要,要牢记)。这个结构体里面就包含了一些进程的核心信息。

在操作系统内核中,又把若干的 PCB 通过双向链表的形式组织了起来。

至此,管理的宏观形式已经介绍完了,接下来,详细介绍一下 PCB 的内容(重点)。

PCB中的主要属性:

  1. 进程的身份表示 pid。这是用来区分不同进程的一个属性,每个进程都有唯一的 pid,就像我们每个人都有自己的身份证号。

    打开你的任务管理器,也可以看到各个进程的 pid。
    在这里插入图片描述

  2. 内存指针
    操作系统运行进程时,需要把一些必要的数据加载到内存中,这些数据有些是运行的指令,有些是运行时依赖的数据。
    内存指针就描述了,一个进程的内存中,哪些是运行指令,哪些是数据。

  3. 文件描述符表
    文件描述符表表示了当前进程都打开了哪些文件。
    文件描述符表其实就是一个顺序表,每个元素就代表一个打开的文件,对应的数组下标就是 “文件描述符”。当我们在代码中打开了一个文件,操作系统就会在该进程的文件描述符表里给这个文件分配一个表项。

内存指针 和 文件描述符表,共同描述了进程持有哪些系统的资源。(再次强调,进程是操作系统中资源分配的基本单位)

进程里还有一组比较关键的属性,用来实现进程的调度。

首先,我们要明确,什么是进程的调度?
我们当前的计算机,CPU 是有限的,但是进程数量是很多的。一般 CPU 核心数只有 6 核,但是进程数有几十个、上百个,这就造成了狼多肉少的本质问题。操作系统需要做到尽可能的公平,让每只狼都有肉吃,就需要进行进程调度,调度的手段就是轮流吃。一批狼吃一会,再换下一批狼吃。

下面介绍两个概念。

  1. 并发式的执行:CPU 的轮转速度是非常快的,因此调度的速度也很快。人感知不到这样的轮转,在宏观角度上,仿佛所有的进程都在同时进行(宏观上同时执行,微观上不是同时执行)。

  2. 并行式的执行:因为 CPU 上有多个核心,每个核心上都可以跑一个进程,因此某一时刻会有多个进程在 CPU 上同时执行(会有一批狼同时吃肉)(宏观上同时执行,微观上也是同时执行)。

实际开发中,并不会对这两个概念做明确的区分(因为我们程序猿的开发是站在应用层面上,从人的宏观角度是看不出区别的),往往使用 ”并发“ 来概括表示 并发 和 并行 -> 并发编程。

介绍完了进程调度,我们回过头来介绍进程的另外四个关键属性。
首先,为了方便大家理解,假设我是一个漂亮的妹子,我有很多的追求者,我的选男朋友的标准:有钱 + 帅。但是在我的追求者中,并没有同时满足这两个要求的。因此我决定要化身🍵,同时交往多个男朋友。在我的层层筛选下,我决定和 A、B、C 三个人同时交往。

A:有钱。 B:帅。 C:舔🐕(我作为女神有成就感)

因此我就要化身时间管理大师,规划好一张时间表,规划什么时间和谁干什么。把我当成一个 CPU,A、B、C 是三个进程,在时间表的安排下,就好像三个进程在 CPU 上并发执行。

四个属性:

  1. 进程的优先级
    安排时间表时,先排谁,后排谁。
    A 很有钱,不缺女朋友,我为了稳住他,就优先给 A 排时间,给 A 最佳的体验。其次给 B 安排时间,至于 C 嘛,看我剩余多少时间了(舔到最后一无所有)。

  2. 进程的状态
    安排时间表时要考虑到每个人的当前的特定情况。比如 A 这周要出差,那我这周的时间只安排给 B 和 C就行了。
    进程就有很多的状态,其中最典型的:
    就绪状态:进程准备就绪,随时可以上 CPU 干活(C:只要女神需要,我随叫随到)。
    阻塞状态:进程在等待某个任务完成,完成之前无法上 CPU 干活。
    正常情况下,A、B、C 都是就绪状态,此时 A 出差了,就相当于进入了阻塞状态。

  3. 进程的记账信息:
    安排时间表时,需要考虑到一些历史记录。
    比如,连续好几个礼拜,我都 C 安排的时间都太少了,再这么下去,我可能就要失去 C 这个小可 (s)爱 (b) 了。因此,下一周排时间的时候,我就可以给 C 多排一点时间。
    操作系统在安排进程的时候,也会记录每个进程以往在 CPU 上执行的时间,如果发现某个进程被安排的太少,就会适当的调整策略。不一定是以执行时间为单位,也可能是以执行的指令数为单位。

  4. 进程的上下文
    某一次和 A 约会的时候,A 说两周后要带我去旅游。某一次和 B 约会的时候,B 说下次见面要给我带礼物。因此下次和 A 见面的时候,我就可以问 A:我们的旅游策划的怎么样了?和 B 见面的时候,我就可以问 B :我的礼物呢?
    为了防止穿帮(记错 A 和 B),就需要记录好上次约会的一些信息,防止把 A 和 B 搞混了。
    进程在调度的时候也是一样的,进程很可能执行了某个操作,执行一半就被调度走了,过一段时间,进程还是要回来的。回来就需要从之前上次执行到的位置继续往下执行(存档和读档)。
    对于进程来说,上下文,具体指的就是 CPU 里的一堆寄存器里的值。上下文会在进程被切出 CPU 的时候,把寄存器的状态保存到 PCB 里(内存),下次进程回到 CPU 上,就把 PCB 里的上下文读取出来,恢复到 CPU 寄存器中。

上述四个关键属性,都是为了辅助进程的调度。


3. 进程的虚拟地址空间

我们期望每个进程都用自己的内存,不同的内存之间不要相互干扰。
但是,在 C 语言中,我们学过一个操作叫 指针解引用。解引用的时候需要保证指针里的地址,是一个合法的地址,否则就是一个野指针。当前指针指向的内存是否合法,是要程序猿来保证的,但是靠人来保证,并不靠谱(宁可相信世上有鬼,也不相信男人的那张臭嘴)。

有没有可能指针指歪了,指向一块非法内存呢?这是非常有可能的(相信写过 C 语言代码的人,肯定都受过野指针的折磨吧)。很可能伴随着这个操作,就直接把别的进程给搞挂了。这种行为就会让整个操作系统都很不稳定(操作系统要给应用程序提供稳定的运行环境)。

为了让各个进程之间不要相互干扰,操作系统就引入了 “虚拟地址空间”
这样的概念。每个进程都只能访问到自己的地址空间,相互之间不会影响,哪怕指针指错,操作系统也能及时发现,不会影响到其他的进程。就算出问题,问题也被限制到进程的内部了。

在这里插入图片描述
比如在进程 3 里,*p = xxx,p成了野指针,指到错误的地址上了,进行操作 p 指向的内存的时候需要经过 MMU 进行映射,MMU 就知道,当前访问的是一个有问题的地址,于是就会向操作系统告状:有进程访问内存错了。操作系统就会给对应的进程发一个 “信号”,告诉它你的内存访问出错。这个信号的默认处理行为就是让进程终止运行(程序崩溃)。windows中会弹个框,提示 xxx 程序已经终止运行…,安卓就会直接 app 闪退。

因为虚拟地址空间,进程就有了一个重要的特性:隔离性。

隔离性:一个程序的运行,一般不会影响到另一个进程,尤其是一个进程崩溃也不会影响到另一个进程。

每个进程都会有自己的 ”虚拟地址空间”,一个系统中又有这么多的进程,如果这些虚拟地址空间加起来比真实的物理内存大了怎么办呢?
虽然系统里的进程很多,但实际上

  1. 进程是并发执行的,同一时刻执行的进程并不会很多
  2. 即使同一时刻,有好几个进程在跑,这些进程也不是同时把所有的虚拟地址空间的内存都使用上了。虽然每个进程的虚拟地址空间很大,但是实际使用的内存可能只有一小部分,物理内存只需要把真实使用的这部分内存数据给标识出来即可。
  3. 极端情况下,确实同时跑的这几个进程同时吃了很多的真实内存,确实会导致物理内存不够(出现这种情况,算 bug,因此程序员就需要想办法优化一下内存占用,或者扩容换一个内存更大的机器)。

4. 进程间通信

进程引入隔离性后,确实让操作系统更稳定,进程更安全了 。但是也存在一个新的问题,多个进程之间的配合工作,变得麻烦了。

因此,操作系统又引入了 “进程间通信”,在隔离性的前提下,又留了一条路,让多个进程之间能够相互通信。

操作系统提供的进程间通信方式有很多种,但是本质上都是一样的,搞一个多个进程之间都能访问到的公共资源,借助公共资源来进行通信(如 “无接触配送”,外卖小哥直接把外卖放到一个专门的集中放置的地点,如小区门口)。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏.冬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值