Linux 进程概念
学习 进程 是在理解 操作系统概念和管理 的基础之上的,所以前面使用大篇幅来讲讲 硬件 和 操作系统 是必要的,最好不要跳过
硬件理解
学习 操作系统 绕不开硬件,想要更深层次理解 操作系统 ,必须理解硬件的运行过程,接下来会首先介绍 冯 诺依曼体系结构
冯 诺依曼体系结构
传统意义上的计算机 非常简单,因为我们的大脑没有计算机效率高,所以我们会将要计算输入的数据送给计算机,计算机再给出我们想要的答案
但生产效率仍然有限,因为需要的不仅是计算数据,还要很多功能,诸如观影,存储,游戏,网络......
所以一个计算机注定由很多硬件构成,比如键盘,鼠标,显示器,网卡,显卡,CPU,主板,内存......
而 这些硬件必须按照一定规则组装在一起才能工作 。我们常见的计算机,如笔记本;我们不常见的计算机,如服务器,大部分都遵守 冯 诺依曼体系结构 ,它在我们 传统意义上的计算机 里新增了 存储器
五大组成部件
冯 诺依曼体系结构 的 五大组成部件 :
- 存储器:指的是主存(内存)!
- 运算器:中央处理器(芯片) CPU 运算组件
- 控制器:中央处理器(芯片) CPU 控制组件
- 输入设备:键盘,鼠标,摄像头,话筒,磁盘,网卡......
- 输出设备:显示器,声卡,磁盘,网卡......
强调
- 以上的组成部件并非独立,而是要用线连接起来才能工作,所以 设备之间是互相连接的,而设备可组装也就可拆卸
- 数据是要在计算机的体系结构中流动的,流动过程中进行加工处理 ,所以数据从一个设备到另一个设备的 流动本质 是一种 拷贝 !!!
- 数据在计算机中的处理无非就是两种情况:计算 和 流动中的拷贝 ;而 CPU 的运算效率极快,所以 计算机整机的基本效率取决于数据在设备间拷贝的效率
存储
拥有存储功能的部件有很多,但存数据是为了有朝一日可以拿出来,而 存取快慢 就是极大的讨论课题
而距离 CPU 越近的 存储器,效率越高,成本越高,容量也越小
如果没有 存储器 ,显然 CPU 要直接和 输入输出设备 打交道,而 输入输出设备 的速度对于 CPU 而言太慢,CPU 大部分时间不是在算,而是在等;所以 添加存储器是为了提高整机效率 ,此后 CPU 只要和 存储器 打交道,CPU 运算的同时 存储器 在做数据流动的拷贝,时间重叠,效率提高
所以有了以下 认知 :
- 不考虑缓存情况, CPU 能且只能对 内存 进行读写,不能访问外设(输入或输出设备)
- 外设(输入或输出设备)要输入或者输出数据,也只能写入 内存 或者从 内存 中读取
- 所有设备都只能直接和 内存 打交道
所以 冯 诺依曼体系结构 就能解决如下问题:
- 为什么 二进制可执行程序 要事先加载到 内存 中
- 首先 二进制可执行程序 是存放在 硬盘 上的数据,要想被执行,肯定需要 CPU 的参与;而硬盘 作为外设并不能被 CPU 直接访问,而所有设备都只能直接和 内存 打交道;所以必须要将程序相关数据事先加载到 内存 中
- QQ 聊天过程中的 数据流动过程
- 不管是你还是你朋友的电脑,都符合 冯 诺依曼体系结构 ,那么根据上一个问题的解答,二者利用 QQ 聊天时电脑会先将 QQ 加载到 内存 中,此时一切就绪:
- 如果是 聊天信息 "出来玩",且是你发信息给你的好友:那你电脑的 输入设备 就是 键盘 ,这条消息会先被送进 内存 (因为 QQ 是被加载在 内存 中),接下来再送进 CPU , CPU 会将你的聊天信息进行加密压缩,完事后再送回 内存 ,再刷新到你设备的 网卡 上(输出设备 ),通过网络传进你好友设备的 网卡 上( 输入设备 ),此时也会将加密压缩的数据送进你好友设备的 内存 ,再送给 CPU 解密读取,完事后再送回 内存 ,刷新到你好友的 屏幕 上(输出设备),被他看见
- 如果是 文件 是一样的流动过程,只是 输入输出设备 不一样罢了
- 不管是你还是你朋友的电脑,都符合 冯 诺依曼体系结构 ,那么根据上一个问题的解答,二者利用 QQ 聊天时电脑会先将 QQ 加载到 内存 中,此时一切就绪:
引子
上面说的轻松呀,事先将数据加载到 内存 的过程中 CPU 会帮忙搬运吗?
并不会,CPU 是指挥官,不可能做这种 "脏活" ,那数据的流动过程谁来拷贝?拷贝到 内存 的什么位置?内存 不足了怎么办?数据又什么时候从 内存 调度做计算?计算完又怎么被响应?什么时候再写回 内存 而后又把数据刷新出去?
上面一系列问题 硬件 能决定吗? 不能!!!
是操作系统!!!
操作系统(Operator System)
概念
任何 计算机系统 都包含一个基本的程序集合,称为操作系统(Operator System)
首先得理解 操作系统(Operator System) 是一款 软件 ,而且基本上是计算机启动后的第一个软件,计算机刚开机加载的东西就是 操作系统
作用
进行软硬件资源管理
举例子:
- 硬件
- 当你在电脑上插 U 盘后,硬件也识别到这个部件后,转而 操作系统 也会识别到此 U 盘,因为 操作系统 可以管理硬件的接入和使用情况;未来不想使用时,当你选择弹出后,操作系统 也会帮你安全弹出
- 软件
- 我们可以对电脑上的软件进行下载,使用,卸载等等,这些操作我们只要进行点击,而软件周期背后的一切都是 操作系统 在管理
认识
广义上 就是 操作系统 内核 + 操作系统 外壳周边程序
- 内核 包括但不限于:进程管理,内存管理,文件管理,驱动管理
- 外壳周边程序 包括但不限于:函数库,
shell
程序等等,是给用户提供使用 操作系统 的方式,再比如图形化界面,各种窗口等等
狭义上 就只是 操作系统 内核
而我们平时要调用 C 语言的 printf()
或者是 scanf()
都是在 访问外设 的行为,对于 操作系统 而言,允许用户直接越过它 访问外设 吗?不可能!!!数据出错怎么办,数据丢失怎么办? 操作系统 还怎么管理,所以你以为的所有 访问外设 的行为都是绕不开 操作系统 的,操作系统 不点头,你就访问不了外设
为什么要有操作系统?
这个很好解释;请问一个学校里,为什么要有一套完整的领导班子?很显然,如果没有,一个学校怎么会被更好的管理起来;所以 在整个计算机软硬件架构中,操作系统的定位是: 一款纯正的"搞管理"的软件,被管理的对象就是软硬件资源 ,而 管理 只是手段,目的是为用户提供一个良好(稳定,安全,高效)的运行环境
结构 示意图
理解操作系统
我们已经知道 操作系统 是专门 搞管理的软件 ,管理软硬件资源,但究竟是如何管理鼠标键盘这些实物组件设备的呢?
首先,管理任何事物,在本质上只是管理这些事物的属性数据;如果要管理公司里的人事,作为老板你会一个一个的去认识它们吗?根本不会,可能压根不会见面!!!那么 操作系统 只是作为软件,它凭什么能管理硬件?本质上就是在管理这些硬件的数据
那 操作系统 又真的能管理这些硬件的所有数据吗?换言之,作为老板你会将你公司员工的所有数据都收集到吗?你顶多只能收集管理员工的基本信息和与公司相关联的数据,员工是否上厕所老板管得着吗? 所以操作系统收集的是能够准确描述这个硬件的数据罢了 ,包括但不限于状态,来源,厂商,类型等等,这些 属性 数据对于每一个硬件都是存在的,于是对计算机而言就建模起来了,就是 结构体(类) ,管理这些硬件就是管理这些 结构体,在操作系统内部会将各种不同的硬件数据进行记录,保存,管理
收集到这些数据,操作系统 会一个一个的管理这些 结构体(类) 吗?可以,但太低效,我们可以 使用更高级更高效的数据结构来组织管理这些结构体,例如链表,顺序表,堆等等
所以在计算机世界里,像 管理 这种技术活,一定是对被管理的对象进行 先描述(建模),再组织(高效数据结构)
system call
从上面的 结构示意图 可看出,这是一个 系统调用接口 的软件层
在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做 系统调用
我们已经知道要访问外设绕不开 操作系统 ,而大量外设硬件的数据结构也都在 操作系统 里,那我们直接访问使用 操作系统 不就是在使用外设硬件了吗?
不可以!!!操作系统内核是不允许任何人来访问的,如果是因为你的操作不当导致外设信息错乱,系统信息有误,对于 操作系统 来说是致命的,为了保证系统稳定,安全,高效的前提下还能 提供用户想要的数据 , 操作系统 就提供了一系列接口:你要做什么,什么时候做,对谁做,无非就是 选择合适的接口为其传参 罢了!!!
库函数概念
系统调用 在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用 进行适度封装,从而形成库,有了 库 ,就很有利于更上层用户或者开发者进行二次开发
进程
还是要再补充一遍,上面所说的内容并非空穴来风,理解好 操作系统 才能更好学习 进程
什么是进程
这个比较抽象,先放一张图:
这不是应用软件吗?是,但它们都是以 进程 的形式跑在我们的电脑上
那这么说,在 操作系统 上可以 同时存在很多 进程 ,它们也都可以被启动,运行,终止等等
咱先不说 进程 的概念,如果在 操作系统 上要跑很多 进程 ,那么 进程 就需要被 操作系统 管理起来!如何管理?先描述,再组织
概念
程序的一个执行实例,正在执行的程序等
担当分配系统资源(CPU时间,内存)的实体(这是内核观点)
也就是说,当我们 正在运行 某个应用程序,或 正在运行 自己写出来的代码程序后,它们就已经成为 操作系统 上的一个 进程 ,正是因为它是 进程 ,才会被 操作系统 和 CPU 去调度运行
误区
不知道上面的 进程概念 大家看懂了没有,但我相信大家还是没有理解什么是 进程 ,因为这里有个误区:
当程序源文件被加载到 内存 里后就已经是一个 进程 了吗?
若存在程序 A ,程序 A 源文件原本是在 磁盘硬盘 上的,要想被运行,就得先将 A 的代码和数据加载到 内存 中,如果现在 被加载的 A 的代码和数据可以被叫做 进程 ,那 内存 里有很多已经被加载到 内存 中的程序,它们又都是 进程 吗?
如果 A 程序已然是 进程 ,那 操作系统 作为管理软硬件资源的老大,应该知道:
- 当前 A 这个 进程 已经累计被调度多长时间?
- 在内存里 代码部分 是从哪开始到哪结束,数据部分 是从哪开始到哪结束?
- A 程序堆空间在哪,栈空间在哪?
- 凭什么 A 程序得先被执行而不是别的程序,若现在不执行 A 程序,什么时候又可以执行呢?
- 是被执行中还是其他状态?
很显然,如果只是 将 A 程序的代码和数据加载到 内存 中,操作系统 并不知道上面关于 A 的信息,所以不好意思,只是在 内存 里的程序还不是 进程 !!!只是此进程对应的代码和数据
为什么敢这么说?因为 操作系统 是要管理 进程 的!!!
认识
首先请问 操作系统 是如何管理 进程 的?先描述,再组织
操作系统 要想描述每一个 进程 ,肯定要先建模,所以每一个 进程 都会有自己的 结构体(类) ,里面包含了 进程 的所有属性, 内存指针(指向此进程对应的代码和数据) 等等,这个 结构体(类) 的名字就是 PCB
!!!
每一个 进程 ,都有一个自己的 PCB
!!!
此时 操作系统 已经完成对 进程 的描述,如何组织? 数据结构 :链表,数组,树等等,哪个高效用哪个
那么从此刻开始,操作系统 对 进程 的管理就转化为 对选择的数据结构做增删查改!!!
结论 :进程 = PCB + 此进程对应的代码和数据
描述进程 - PCB
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合
PCB(process control block) Linux 操作系统下的 PCB 是: task_struct
简单来说就是 描述一个进程的结构体 , 而 结构体连同组织它们的数据结构 被称之为 内核数据结构
其实 操作系统 也是软件,开机的时候就会先将 操作系统 二进制文件加载 内存 中,而前面所提到的管理 进程 的结构体和数据结构都是在 操作系统内部 的
当开启一个 进程 ,会在 操作系统内部 malloc
一个结构体 PCB
,达到管理这个 PCB
从而管理这个 进程 的效果
所以为什么要有 PCB
,因为 操作系统 要管理,先描述再组织
task_struct - PCB 的一种
在 Linux 中描述 进程 的结构体叫做 task_struct
task_struct
是 Linux 内核的一种数据结构,它会被装载到 RAM(内存)里并且包含着 进程 的信息
进程动态运行
在 OS 里,进程 会有不同的状态:执行,等待等等,但 OS 要调度运行 进程 ,本质上就是让 task_struct
在 OS 里进行排队,不同的队列就能让 进程 访问不同的资源
当这个 进程节点 被调度时,频繁的被更改到其他队列里,也就是所谓的 进程动态运行