1.进程
1.1 进程的概念
进程是指正在运行的程序
进程是系统分配硬件资源的基本单位
如下图所示:
- 我们平时所说的程序,指的是一些exe的可执行文件,程序必须运行起来,才会涉及到进程
比如:
- 同一个程序,运行多次,就可能会产生出多个进程
比如:
1.2 程序和进程区分
- 程序,是可执行文件,是在硬盘上的一个东西(静态的) 当双击程序,操作系统就会把可执行文件中的数据和指令,加载到内存,并且让CPU去执行这个指令,完成一系列相关的工作,运行起来的(动态的),就是进程
- 进程是运行中的程序,说明进程能消耗一定的硬盘资源 可执行程序,只是占用了硬盘空间,而进程,会消耗CPU资源,内存资源,硬盘,网络宽带
老师布置了作业,我把作业抄在了本子上,这个是我要执行的程序
当我开始写作业时,我需要消耗时间和精力去完成,这个过程就是进程
2.进程如何被调度
一台计算机,是包含很多进程的,进程多了,自然就需要管理.
针对计算机中"进程"的管理,是由操作系统内核进行的
管理的核心思路是先描述,再管理
(举个例子,当一批货物被运来,我们要先统计它们的信息特征,然后再根据种类等进行分配)
2.1 描述
使用一个专门的结构体来记录一个进程里面的各个属性(和C语言的结构体很像)
PCB(进程控制块)(Linux中的PCB,在源码中是一个task_struct结构体)
2.2 组织
本质上是使用一系列的数据结构,把多个进程进行一个有效的组织,随时方便进行遍历,查找,汇总数据(对于Linux来说,通常是使用双向链表这样的方式来进行组织的)
当使用双向链表来组织时:
1)查看进程的列表,本质上就是在遍历这个链表
2)创建一个进程,就是创建了一个PCB结构体,并且插入到链表上
3)销毁一个进程,就是把这个PCB结构体从链表上删除并释放
2.3 PCB中描述的进程特征
2.3.1 pid(进程的标识)
同一个系统上,同一时刻中,每个进程的pid一定是不同的
如下:
2.3.2 内存指针
- 内存指针表示了该进程对应的内存资源,是什么样的
那么内存资源中要存什么呢?
主要存储的就是从exe可执行文件中加载出来的指令和数据,还有一些运行过程中的中间结果之类的数据
指令:是以二进制形式存储的,是程序员开发程序时,代码最终编译生成的结果,进一步再交给CPU处理
数据:执行指令时依赖的一些数据
举个例子:
演员演戏的时候,剧本说A要和B打一架,这时候怎么打,一些打的动作,姿态就要依赖数据了,
指令,就相当于一个剧本,进程就是一个演员
2.3.3 文件描述符表
文件描述符表和硬盘资源有关
- 硬盘是硬件,应用程序一般不会直接接触到"硬件"这一层
- 实际上是操作系统抽象成"文件"这样的概念,程序操作的是文件,文件实际上是存储在硬盘上的
- 每个进程都会有一个"文件描述符表"来记录,记录当前这个进程正在使用哪些文件
- 操作系统每打开一个文件,就会产生一个"文件描述符"(相当于一个身份标识)
- 同时使用文件描述符表(类似于数组),将文件描述符给组织起来
2.2.4 如何在CPU上执行
每个进程是在CPU上来执行指令的
(进程如果是演员,CPU就是剧场)
但是一台机器上,同一时刻就有很多进程,但是CPU只有一个,怎么办??
2.2.4.1 并行
同一时刻,两个进程,同时运行在两个CPU逻辑核心上
2.2.4.2 并发
两个进程,在同一CPU,轮着执行
- 由于CPU切换进程速度极快,微观上,这两个进程是串行执行的,宏观上,看起来是"同时"执行的
- 操作系统,在调度这些进程时,可能是按照并行的方式,也可能是并发方式
- 当然在应用层序上,是无法感知操作系统用了哪个方式,并且这两个方式在宏观上的体现效果一样,所以通常也会用"并发"代指"并行"和"并发"
2.4 PCB中关于进程调度相关的属性
(这些属性描述了进程对应的CPU资源的使用情况)
2.4.1 状态
下面描述一些主要的状态:
就绪:进程已经做好了在CPU上执行的准备,随叫随到
阻塞:进程没有准备好被调度到CPU上
2.4.2 优先级
- 系统给进程进行调度时,并不是完全公平的,会根据优先级的不同,来决定时间分配的权衡,这样就可以把系统资源调度给更重要的进程上了
就比如打游戏的时候,有的游戏很吃硬件资源
2.4.3 上下文
- 这些进程是轮流上的,有时候一次性无法运行完,就需要保证在下一次运行时,能够接着上一次继续运行(相当于读档存档)
- 对于操作系统来说,所记录的上下文就是该进程在执行过程中,CPU的寄存器中的数据!!
- 这些寄存器,有的存的是一些中间结果,有的存的是一些特定含义的数据(比如下一条指令在哪等等)(比如当前函数的调用关系)
- 这些寄存器中的数据就需要在进程离开CPU之前,都保存好,保存在对应进程的PCB的上下文字段中(内存)
- 下次该进程回到CPU执行时,就可以把CPU中的上下文里的数据恢复到对应的寄存器中,这个时候,进程就是和上次执行的状态一模一样了
2.4.4 记账信息
- 相当于一个统计信息,统计每个进程在CPU上执行了多久,执行了多少指令 (是对进程的调度工作进行一个兜底)
2.4.5 虚拟地址空间
当然,每个进程,都需要一定的内存资源
早期的操作系统,就是直接把物理内存分配给进程,这时就会有一个严重的问题:
一旦某个进程内部代码有了bug,内存越界访问了,就会影响别的进程.影响系统的稳定性
这时,就引入了"虚拟地址空间"这个概念
这样设定之后,每个进程的有效的虚拟地址,都是固定范围.
- 进程使用该虚拟地址的内存,都需要操作系统转换为物理地址,在转换过程中,就可以针对虚拟地址是否有效做出一个校验,当校验出问题时,就可以及时通知到这个进程,避免影响其它进程,提高了系统的稳定性
- 在虚拟地址空间下,进程就具有了独立性,每个进程都有自己的虚拟地址空间,一个进程无法直接访问或者修改其它进程虚拟地址空间的内容,强化了系统的稳定性
进程间通信:虽然通过虚拟地址空间,把进程隔离开了,但是有时候还需要让进程之间,产生配合/联系,那该如何做呢?
本质:找一个公共区域,即多个进程都能访问到的区域,借助公共区域来完成数据的交换