文章目录
- 一、什么是程序?
- 二、什么是进程?
- 三、进程与程序有什么区别?
- 四、OS是如何管理进程的
- 4.1、使用 结构体 进行描述进程
- 4.2 、使用数据结构组织众多进程
- 4.3、PCB
- 4.3.1、PCB 里有哪些属性
- 4.3.1.1 pid
- 4.3.1.2 内存指针
- 4.3.1.3 文件描述符表
- 五、进程调度
- 5.1、进程调度的两种方式
- 5.1.1、并行
- 5.1.2、并发
- 5.2、PCB中关于进程调度的相关属性
- 5.2.1、状态
- 5.2.2 、优先级
- 5.2.3、上下文
- 5.2.4、记账信息
- 六、进程的隔离性
- 七、进程间通信
- 7.1、进程通信的两种常用方法
一、什么是程序?
以 .exe 为后缀的可执行文件就是一个程序,一般是存储在硬盘上的。
上图中,我们可以看到 QQ.exe 就是一个以.exe 为后缀的可执行文件,因此他就是一个程序,应用程序;图中其他以.exe结尾的文件,其类型也是应用程序。程序在没有双击运行时,是 静态的 存放在硬盘上的,此时并不会消耗系统资源。
二、什么是进程?
正在运行的程序就是进程。
譬如说:QQ这个程序没有运行时,以 .exe 作为后缀的文件静态的存放在硬盘上,并没有运行。双击运行时,同一个程序,可以产生多个进程。就像QQ只是一个程序,多次双击运行后就可以使多个不同的qq用户登录,每个qq用户登录之后产生的qq登录账号信息,就是多个进程在同时运行;譬如说浏览器,浏览器可以打开多个页面,这也是程序多进程的一中表现。
我们平常可以在电脑的 任务管理器 中查看 有哪些进程。
三、进程与程序有什么区别?
1、程序是以.exe结尾的可执行文件,一般存于硬盘上,是静态的、固定不变的。
2、进程是正在运行的程序。当我们双击运行程序时,操作系统就会将可执行文件里存有的 指令和数据 加载到内存中,让 cpu 从内存中取这些 指令与数据 进行执行,完成一系列的工作。那么此时这个程序就由静态的转为运行状态的 进程。
3、进程运行起来是为了完成一系列相关的工作,因此进程就会消耗一定的系统资源(譬如:cpu、内存资源、硬盘资源、IO资源、网络带宽…),而程序是静态的,只是占用了硬盘资源。
4、进程是 操作系统 分配硬件资源的基本单位。
怎么理解这句话呢??举个例子:在疫情封控期间,由于当时我们学校一天之内阳了3个同学,这个时候学校就将我们所在的南区宿舍封了。封楼期间,所有学生每天每时只能待在宿舍,学校会派工作人员定时定点投放饭菜,以 宿舍 为基本单位 分发食物。因此我们进程运行时,需要向系统申请硬件资源来支持运行时,系统就以 进程 为基本单位分配资源给进程。
可能还有同学感觉区分不开进程和程序,我再举个例子加深印象:程序 就像 我们每天做的 日程表,写在上面的诸多计划是静止的。进程 就是 我们开始执行日程表上的计划,消耗了一定 资源、精力、时间,才完成了 日程表上的 所有计划。
在我们学校,学生点外卖之后,外卖员是没办法提着外卖来到(这个符合那个 公共区域)
四、OS是如何管理进程的
一台正在运行的计算机中,大概率是包含了很多进程,不说成百上千,但也有百八十个。一旦东西多了起来,就需要进行管理,否则容易显得杂乱无章。因此对于计算机中进程的管理,也很重要。
4.1、使用 结构体 进行描述进程
1、描述:首先需要专门使用一个 结构体 来描述 一个进程,记录进程里含有的各个属性。(由于操作系统底层是由 C/C++ 实现的,因此对于进程的描述是使用结构体进行描述,结构体就像一个低配的类,能够含有各种属性,但类既可以含有属性,还可以含有各种方法)
4.2 、使用数据结构组织众多进程
2、组织:再使用一系列的数据结构把多个进程有效的组织起来,方便后续进行遍历、查找、汇总…
4.3、PCB
描述进程的结构体有一个专门的名字,叫做 PCB(进程控制块 process control block)。各大系统中用来描述进程的部分都可以称作 PCB,PCB 是一个通用叫法。
通常是使用 双向链表 这样的数据结构进行组织诸多 PCB 。(这是针对于 Linux 来说的,因为 Windows 并没有开源,因此对于 Windows 中的 PCB 是使用什么数据结构来组织的,我们不得而知)。
当使用 双向链表 来组织PCB时:
1)、查看进程列表,本质上就是在遍历该双向链表。
2)、创建一个进程,就是创建一个 PCB 结构体,并插入至链表中。
3)、销毁一个进程,就是把这个 PCB 结构体从链表上删除并释放。
4.3.1、PCB 里有哪些属性
那么想要进一步明确 PCB 的概念,就需要了解这个用于描述进程的结构体PCB,里边到底有哪些属性呢?
4.3.1.1 pid
pid 用来表示进程的唯一身份标识(区分不同的进程)。
在 任务管理器 中,我们可以看到不同的进程具有不同的pid。
有些程序是多进程运行,因此在 任务管理器 中,会看到某些程序是没有pid的,但是,一旦展开,就会看到此程序下含有许多个进程,这些进程都具有不同的pid。
我们可以看到上图圈红圈的地方,这两个程序其右边的 pid 是空的。
4.3.1.2 内存指针
前面我们提到过,进程运行时,需要消耗系统资源。因此当进程向系统申请资源时,操作系统肯定要为进程分配系统资源(cpu、硬盘资源、内存资源、网络带宽…),那么此时,内存指针就可以表示:当前进程从操作系统那里分来的对应内存资源是多少。 内存资源里存储什么内容:从.exe可执行文件处加载来的 指令和数据。
那可能会有同学疑惑什么是 指令(指令就是程序员开发程序时编写的代码,这些代码经过编译后转成cpu易识别的二进制指令),什么是数据。举个例子加深印象:指令就像剧本,数据就像剧本里的各种台词,进程就像一个演员。演员进行演戏,需要依靠剧本掌握整部戏的具体拍摄流程,具体场景怎么演,依靠数据支撑。譬如说:是一场打巴掌的戏,剧本上的数据说要打1个巴掌,演员不能擅自打10个巴掌。
4.3.1.3 文件描述符表
文件描述符表 与 硬盘资源 有关。
硬盘是硬件,应用程序(软件)一般是没办法直接操作 硬件 这一层的,因此操作系统将硬件抽象成 文件 这一概念,应用程序可以操作的是 文件,但是 文件 也是存储在硬盘上的,因此进程的硬盘资源使用 文件 来体现。操作系统打开一个文件,就会产生一个 文件描述符(类似于文件的唯一身份标识,只在进程内部生效),同时会使用文件描述符表将 文件描述符 组织起来。
每个进程都有一个 文件描述符表 来记录当前进程正在使用哪些文件。
五、进程调度
进程是需要到 cpu 上执行指令的。
像前面所形容的,如果进程是演员,那么 cpu 就相当于 拍摄场地,演员需要到拍摄场地进行拍戏工作。
那么每个进程,要想执行里面的指令,完成相应的工作,都需要到cpu上执行指令。对于一台机器来说,同一时刻所存在的进程有成百上千,但是cpu只有一个,那么此时cpu该如何操作那么多进程呢??
此时就涉及到一个关键问题:进程调度[重点,必须掌握]。
cpu 虽然只有一个,但是随着技术发展,现在的cpu不再是以前的单核cpu,而是多核cpu。
什么是单核cpu:单核cpu就是一个cpu上只有一个位置去执行一个进程里的指令。
多核cpu是:一个cpu上有多个位置去执行多个进程里的指令。
同时,现在由于超线程技术,cpu的一个核心,还能顶两个来用。
那么此时单核cpu就相当于:一个cpu上只有一个位置,只一个位置可以有两个座位,让两个进程同时在cpu里执行。
多核cpu就相当于:一个cpu上有多个核心,一个核心里有两个座位让很多进程同时在cpu里执行。
因此现在我们常常会听说cpu有这些叫法:六核十二线程、八核16线程…那是因为,一个cpu核心,是一个物理核心,一个物理核心,相当于两个逻辑核心。
譬如我电脑的cpu就是八核16线程:
但即使随着技术的发展,产生了多核cpu,也无法一次性将机器上 成百上千的进程执行完。因此还是需要进行 进程调度。
5.1、进程调度的两种方式
5.1.1、并行
同一时刻,两个进程,同时运行在 一个cpu的两个逻辑核心上。
5.1.2、并发
两个进程,在同一个物理核心上,轮流运行。(由于cpu切换进程的速度很快,微观上,两个进程是串行执行;宏观上,两个进程是“同时”执行)
cpu在进行进程调度的时候,既会按照并行的方式调度,也会按照并发的方式调度。这是因为,在应用程序这一层,我们无法感知到操作系统究竟是使用了并行的调度方法运行进程,还是使用了并发的调度方式运行进程。因此一般我们都是以 并发 来统称并行与并发。
5.2、PCB中关于进程调度的相关属性
这些属性描述了进程对应的cpu资源的使用情况。
5.2.1、状态
进程在进程调度中有2个重要的状态:
1、就绪状态:表示当前进程已经随时做好了在 cpu 上执行的准备。
2、阻塞状态(也称睡眠状态):表示 一个进程 没有做好调度到cpu上执行的准备
这些状态是可以相互转换的。
当然还有其他的状态,但是这两个是比较关键的。
5.2.2 、优先级
系统进行进程调度时,也不是完全公平的。也会根据进程优先级的不同,来决定优先将系统资源分配给哪个进程。
5.2.3、上下文
由于进程调度,进程是轮流在cpu上执行的,一次运行不完,就需要保证下次进程又被调度到cpu上执行的时候,能够让cpu从上次没执行完的指令处继续往后执行。就相当于我们玩游戏时的一个 读档/存档。
对于操作系统来说,记录的上下文是什么??即在进程执行过程中,cpu的寄存器中对应的数据。
寄存器一般是用来存储一些操作数、中间结果…那么当 当前进程要被调度离开cpu之前,寄存器中存储的当前进程的要执行的指令这样的数据,就需要保存到PCB的上下文字段中。下次该进程回到cpu执行时,就将PCB的上下文字段中存储的数据恢复到对应的寄存器中,此时就能够继续运行上回未运行完毕的进程了。
5.2.4、记账信息
相当于一个“统计信息”。会统计每个进程在cpu都执行了多久,都执行了那些指令。相当于是对进程的调度工作进行一个“兜底”。譬如说一些优先级高的进程一直在cpu上执行,优先级低的进程没办法执行一次,此时记账信息察觉到之后,就会将优先级低的进程放到cpu上执行,确保每个进程都能够有机会调度到cpu上执行。
六、进程的隔离性
每个进程都需要一定的内存资源,来存储PCB中包含的相关属性。早期时候,操作系统是直接将物理内存(电脑上的内存条)分配给进程使用。
这是一个很严重的问题:一旦某个进程内部的代码有bug,导致内存越界访问了,此时就会影响到别的进程执行。
因此操作系统就引入了 虚拟地址空间 这样的概念,解决上述有可能发生的内存越界访问问题。即给不同的进程分配相同的虚拟地址,这些虚拟地址对应了不同的物理地址。
这样设定之后,每个进程有效的虚拟地址都是固定范围的,进程使用该虚拟地址的内存,都需要操作系统转换成真正有效的物理地址。
此时就可以通过这个转换,针对虚拟地址是否有效做一个校验。当系统检查出了非法的地址使用时,就可以及时的通知该进程,或者直接关闭当前进程,避免其影响到别的进程运行。
七、进程间通信
在虚拟地址空间的加持下,进程就具有了独立性,即每个进程自己的内存空间,都是独立的,不能相互访问。即每个进程有自己的虚拟地址空间后,此时进程就无法直接访问或者修改其他进程虚拟地址空间里的内容,强化了系统的稳定性。
因此通过虚拟地址空间,把进程之间相互隔开了。但是有的时候,还是需要让进程之间产生一些配合/联系,以便更好地完成信息的交互。此时就产生了一个关键问题:进程间通信。
进程间通信可以有很多方法,但无论是哪一种方法,本质都是一样:就是找一个多个进程都能访问到的公共区域,借助公共区域来完成数据的交互。
7.1、进程通信的两种常用方法
1、基于文件(公共区域:硬盘)
2、基于网络 socket(公共区域:网卡)