目录
什么是进程/任务(Process/Task)
PCB的具体信息
1.pid 进程的身份标识
2.内存指针
3.文件描述符表
4.进程状态
5.进程优先级
6.进程上下文
7.进程 记账信息
虚拟地址空间
我的GitHub:Powerveil · GitHub
我的Gitee:Powercs12 (powercs12) - Gitee.com
皮卡丘每天学Java
什么是进程/任务(Process/Task)
每个应用程序运行于现代操作系统之上时,操作系统会提供一种抽象,好像系统上只有这个程序在运 行,所有的硬件资源都被这个程序在使用。这种假象是通过抽象了一个进程的概念来完成的,进程可以 说是计算机科学中最重要和最成功的概念之一。
进程是操作系统对一个正在运行的程序的一种抽象,换言之,可以把进程看做程序的一次运行过程; 同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。
对进程的管理
-
描述:详细的表示清楚一个进程有哪些属性/信息
使用一种结构体来描述,结构体(PCB,进程控制块)里面包含一个进程的各种信息,
-
组织:通过一定的数据结构,把若干个用来描述的实体,放到一起,进行增删改查
系统通常会使用 双向链表 这样的结构来把这些 PCB 组织在一起
创建一个进程,本质上就是创建 PCB ,并且加入到链表上
销毁一个进程,本质上就是从链表上删除对应的 PCB 节点
查看任务管理器的进程列表,本质上就是在遍历这个 链表
注意:
一个进程可能是一个 PCB 也可能对应多个
系统这里管理 PCB 的链表也不一定是一个
PCB的具体信息
任务管理器中查看
命令行窗口查看
1.pid 进程的身份标识
一个主机,同一时刻,这些进程的 pid 是唯一的 通过 pid 来区分一个进程
2.内存指针
描述进程持有的 内存资源 一个可执行文件双击后开始运行,操作系统把文件中的核心数据(要执行的指令和指令依赖的数据)加载到内存中 既然要创建进程,势必要给进程分配空间,然后这个内存空间上就有很多区域。有的区域存放指令,有的区域存放数据,还有的用来维护运行状态
3.文件描述符表
描述进程持有的 文件资源 每个进程都可以打开一些文件(文件其实是存储在硬盘上的数据) 文件描述符表里面就记录了当前进程都打开了哪些文件
上面两条可以说明 进程 是操作系统分配资源的基本单位
以下几个属性都和“进程调度”有关系
为什么要有“进程调度”
资源有限,需要合理安排 CPU 资源。进程可以有很多个,但是 CPU 只有几个(例如8核CPU,只能同时跑8个进程)
“进程调度”是什么
所谓的进程调度就是通过“并行”和“并发”的方式让计算机可以“同时”执行多个进程(任务)
“并行”和“并发”
并行执行 每个 CPU 核心上都可以独立的运行一个进程(运行进程的相关指令),多个 CPU 就可以同时独立运行多个进程
并发执行 一个 CPU 核心 先运行一个进程1,再运行进程2,再运行进程3,只要微观上切换的速度足够快,宏观上看起来就好像3个进程同时运行一样
4.进程状态
一个进程的生命周期可以划分为一组状态,这些状态刻画了整个进程。进程状态即体现一个进程的生命状态。
进程状态大致可以分为三个状态(也可以细分为五个状态)
(1)运行(running)态:进程占有处理器正在运行。
(2)就绪(ready)态:进程具备运行条件,等待系统分配处理器以便运行。
(3)等待(wait)态:又称为阻塞(blocked)态或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成。
5.进程优先级
系统调度的时候就会根据优先级,来给进程安排时间 创建进程的时候可以通过一些系统调用来干预优先级的(相对的)
6.进程上下文
进程在 CPU 上执行了一会之后,要切换给别的进程,就需要保存当前运行的中间结果(存档),下次再轮到它执行的时候,就恢复之前的中间结果(读档),继续往下执行
对于进程来说,上下文 就是 CPU 中间的寄存器的值(寄存器的值就包含了运行的中间结果,需要把这些结果保存到 PCB 的上下文信息中(内存))
7.进程 记账信息
每个进程在 CPU 上执行了多久,统计信息,辅助调度的效果 执行进程的时候,虽然有优先级,但是还是不希望让有的进程完全受到 CPU 的 青睐
记账信息的单位不是时间为单位,而是执行指令的条数
这样使得进程调度更加均衡,避免发生 CPU 完全没有执行某个进程
虚拟地址空间
虚拟地址空间会给每个进程安排一些内存资源
看一下直接分配内存会有什么问题
假设出现极端的情况,线程1 中,出现了 内存访问越界 这样的操作就可能影响其它进程。保存了一个无效的内存地址(野指针),通过解引用对该块内存进行操作。
即不能让 进程1 这里的指针越界操作,影响到进程2
上述操作会产生进程间的相互影响 为了解决这个问题,就需要让每个进程都有各自的内存空间(活动范围)不要让这些进程的活动范围重叠 给每个进程划分内存空间,都叫做“虚拟地址空间”(不是真是的物理内存地址),通过专门的设备 MMU 来完成 虚拟地址 到物理地址之间的 映射。
MMU 就可以针对这里的地址进行校验,如果是非法地址,直接就通知进程(比如把进程给杀死)从而及时止损,避免影响到其他进程的运行
针对 进程1 和 进程2 来说,能够访问的内存空间,就只是0x0000-0xFFFF 这一段 如果不小心访问了更大的内存空间,在 MMU 映射的时候就能及时发现,从而避免对物理内存产生影响
使用虚拟地址空间,就认为进程之间存在了“隔离性” 一个进程是不能直接访问另一个进程内存数据的,防止干扰的操作,提高了系统的稳定性。不会说某个进程出现bug影响到其他进程
新的问题
有了隔离性之后,虽然进程是稳定了,但是也有新的问题
有些需求场景,就是需要多个进程相互配合的 进程隔离了,此时进程之间就很难进程交互了
所以系统又引入了一个机制 进程间通信
找一块 多个线程 都可以访问到的 公共资源,然后基于公共资源来交换数据
这块公共资源可以是一块内存,也可以是一个文件,还可以是网卡......
进程是要求要有独立性的(相互之间不影响) 进程如果需要进程通信,就需要使用特定的进程间通信机制(基于文件,基于 socket(网卡))
虚拟地址空间(进程独立性)和进程间通信的配合类似面向对象中的“封装” 对于程序员的“自由”的限制
这种限制其实是有益的,条条框框越不容易出错,自由会出现各种错误