目录
一个正在运行的程序,就是一个 进程,进程是一个重要的 "软件资源",是由操作系统内核负责管理的。每个进程都对应一些资源,在上图中每个进程都占用了内存,CPU,磁盘等,也可以认为进程是操作系统资源分配的基本单位。
我们通过组织+描述的方法来管理进程
描述: 使用结构体来描述进程属性,我们把这样的结构体叫做PCB(进程控制块)
组织: 通过双向链表来把多个PCB给连接在一起。
创建一个进程:本质上是创建一个PCB结构体,把它插入到链表中。
销毁一个进程:把链表上的PCB节点删除掉。
任务管理器查看进程列表: 本质上是遍历PCB链表。
1. pid 进程的身份标识(唯一的数字),每个进程都对应一个身份标识。
2. 内存指针 指向了自己的内存有那些,进程占用了那些资源。
3. 文件描述符表 硬盘上的文件等其他资源。
在资源分配中,进程有很多个,而我们的处理器又很少,在这种情况下,我们希望每个进程能够“同时运行”,就引入了并行和并发两个概念。
●并行:微观上同一时刻,两个核心上的进程,就是同时执行的
●并发: 微观上,同一时刻,一个核心上只能运行一个进程,但是它能够快速的切换(比如电灯闪烁的频率高了人就感觉电灯是常亮的)宏观上人们感知不到,我们感觉几个进程是在同时运行的。
并行和并发都是由内核负责处理的,应用程序感知不到,因此我们把并行和并发统称为并发。
操作系统中有一个重要的模块调度器,就让有限的CPU来调度执行多个进程
4.进程调度的相关属性
(1) 进程的状态
●就绪状态: 进程随时准备去CPU上执行
●运行状态: 正在运行的进程
●阻塞状态: 短时间无法到CPU上执行
(2) 优先级
进程也是有优先级的,操作系统在进行调度的时候,有的进程CPU就分配的多,有的分配的少,有的先分,有的后分,这就叫进程的优先级
(3) 上下文
操作系统在进行进程切换的时候,就需要把进程执行的"中间状态"记录下来,保存好,等下次这个进程在cpu上运行的时候,就可以回复上次的状态.,接着往下执行, 相当于 "存档,读档"。
(4) 记账信息
操作系统统计每个进程在CPU上占用的时间和执行的指令数目,根据这个来决定下个阶段如何调度。
早期的操作系统,程序运行时分配的内存,就是物理地址
针对进程使用的内存空间,进行隔离,引入了虚拟地址空间,代码里不在直接使用真实的物理地址,而是使用虚拟的地址,由操作系统和专门的硬件设备负责进行虚拟地址到物理地址的转换。
虚拟地址空间主要就是为了避免进程之间的相互影响。
在上面虽然进行了进程间的隔离,但有些时候,进程之间需要进行数据的交互,我们采用进程间通信来实现进程间的交互。我们需要一个多个进程都能访问到的“公共空间”,基于这个公共空间来进行数据的交互。
在如今,CPU已经进入到多核心时代,要想进一步提高程序的运行速度,就要充分利用CPU的多核心资源,其实,多进程已经可以解决并发编程的问题,已经可以利用CPU的多核资源了,但多进程也有一些弊端,进程太重了(多进程消耗的资源多,并且速度慢)。比如创建一个进程开销较大,销毁一个进程开销太大,调度一个进程,开销较大。因此线程应运而生,线程也叫轻量级编程,在解决并发编程的问题下,让创建,调度,销毁的速度更快。线程把申请资源,释放资源的操作给省下了。
1. 进程包含线程,一个进程可以包含一个线程,也可以包含多个线程(不能没有),只有在第一个线程启动的时候,开销较大,需要申请资源,后续线程就省事了
2. 同一个进程里的多个线程,共用了进程的同一份资源(主要是内存 和 文件描述符表)。操作系统在调度的时候是以线程为基本单位进行调度的。
3. 如果每个进程有多个线程,每个线程是独立在CPU上调度的,即线程是操作系统调度执行的基本单位。
4.每个线程也有自己的执行逻辑(执行流)。
接下来用吃100只的例子来看看多进程和多线程之间的差别
多进程需要两个房间,两个桌子,两个滑稽老铁~ ~ 这样成本比较高,需要很多额外的资源
多线程让两个滑稽老铁在同一个房间同一个桌子上吃,节省了资源
那我们在思考思考,让滑稽老铁更多,速度能否更快呢?
当滑稽老铁越来越多的时候,桌子的空间是有限度的,后面的滑稽老铁也会吃不上鸡,同理,线程也是一样,增加线程数量的时候,也不是可以一直增加速度,线程太多,核心数量有限,不少的开销反而会浪费在线程调度上了。
1. 多线程情况下,多个滑稽老铁,滑稽1和滑稽2共享同一份鸡肉,此时可能会打架,但在多进程中则不会出现这中情况,多进程中都是自己执行自己的。
2. 还是上面的问题,当滑稽1把鸡肉给抢走了,导致滑稽2吃不着生气了,滑稽2直接掀桌,那么大家都吃不了了。在多线程中也一样,如果一个线程抛异常,如果处理不好,很可能导致整个进程都异常了
当多个执行流访问到同一个共享资源的时候会出现安全问题
线程模型:天然就是资源共享,多线程争抢同一个资源很容易触发。
进程模型:天然是资源隔离的,不容易触发,进程间通信的时候,多个进程访问到同一个资源,可能会出现问题。