网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
当然,进程还有 创建、结束 两个状态:
我们细节性的描述下状态变迁的过程:
- **NULL --> 创建状态:**一个新进程被创建的第一个状态
- **创建状态 --> 就绪状态:**当一个进程被创建完成并完成初始化后,一切准备就绪
- **就绪状态 --> 运行状态:**当前进程被操作系统的进程调度器选中,得到 CPU 的时间片,分配给 CPU 运行
- **运行状态 --> 阻塞状态:**当进程请求某个事件且必须等待时,例如 请求 I/O 事件
- **运行状态 --> 就绪状态:**当前 CPU 分配给该进程的时间片已用完
- **运行状态 --> 结束状态:**当前进程已经运行完成或出错
- **阻塞状态 --> 就绪状态:**当前进程等待的事件已完成,进程由阻塞状态切换到就绪状态
另外,为了防止 大量处于阻塞的线程影响内存的使用,需要一个新的状态:来描述进程没有占用实际的物理内存空间的情况,这个状态就是挂起状态,继而变成如下:
2. 进程的控制结构
在操作系统中,使用 进程控制块(Process control block,PCB) 的数据结构来描述进程的
PCB 是进程存在的唯一标识,这意味着一个进程的存在,必然会有一个 PCB,如果进程消失了,那么 PCB 也会随之消失。
PCB 具体包含什么信息呢?
进程描述信息
- 进程标识符:每一个进程拥有一个标识符
- 用户标识符:进程归属的用户
进程控制和管理信息
- 进程当前状态:如 new、ready、running、waiting等状态
- 进程优先级:进程抢占 CPU 的优先级
资源分配清单
- 有关内存地址空间或虚拟空间的信息,使用的 I/O 设备
CPU相关信息
- CPU 各个寄存器的值,当进程被切换时,CPU 的状态信息都会被保存在相应的 PCB 中,以便进程重新执行时,能从断点处继续执行
PCB 是如何组织的呢?
以链表的方式,把具有相同状态的进程连接在一起,组成各种队列。
- 将所有处于有绪状态的进程链在一起,称为就绪队列
- 因等待事件而处于阻塞状态的进程链在一起,称为阻塞队列
除了链接的组织方式,还有索引方式,他的工作原理:将同一状态的进程组织在一个索引表中,索引表项指向相应的 PCB,不同状态对应不同的索引表。
因为我们的进程不断的创建、销毁,所以链表更加灵活的实现插入和删除的功能。
3. 进程的控制
我们来看一下进程创建、终止、阻塞、唤醒的过程
第一步:创建进程
操作系统允许一个进程创建另一个进程,而且允许子进程继承父进程所拥有的资源,当子进程被终止时,会将资源返还给父进程。同时,终止父进程的同时也会终止其所有的子进程(PS:这里不同的操作系统实现不同)
创建进程的过程:
- 为新进程分配唯一的进程标识号,申请一个空白的PCB
- 为进程分配资源,如果资源不足,进程进入等待状态,等待资源
- 初始化 PCB
- 将当前的进程放入到 就绪队列 中,等待被 CPU 调度运行
第二步:终止进程
进程可以有 3 种终止方式:正常结束、异常结束以及外界干预(信号 kill
掉)。
终止进程的过程:
- 查找该进程的PCB
- 如果处于执行状态,则立即终止执行,并将 CPU资源分配给别的进程
- 如果拥有子进程,则终止子进程
- 将该进程所拥有的资源返还给父进程或操作系统,然后将其 PCB 从队列中删除掉
第三步:阻塞进程
当进程需要等待某一事件完成时,它可以调用阻塞语句把自己阻塞等待。而一旦被阻塞等待,它只能由另一个进程唤醒。
阻塞进程的过程:
- 找到将要被阻塞进程标记的 PCB
- 如果该进程为运行状态,保护其现场,变为阻塞状态,停止运行
- 将该 PCB 插入到阻塞队列中去
第四步:唤醒进程
如果某进程正在等待 I/O 事件,需由别的进程发消息给它,则只有当该进程所期待的事件出现时,才由发现者进程用唤醒语句叫醒它。
唤醒进程的过程:
- 在阻塞队列中找到该进程的 PCB,将其从阻塞队列移除,并将其置为就绪状态
- 放入就绪队列中,等待 CPU 的调度
4. 进程的上下文切换
各个进程共享CPU的资源,进程之间互相切换,让不同的进程可以在CPU执行,一个进程切换到另一个进程运行,称为:进程的上下文切换
CPU 上下文切换是什么?
我们的任务是交给 CPU 来执行的,每个任务运行之前,CPU 需要知道任务从哪里加载,又从哪里开始运行。
所以,操作系统需要事先帮 CPU 设置好 CPU 寄存器和程序计数器
- CPU 寄存器:存储指令、数据的地方
- 程序计数器:存储当前CPU执行指令的地址或是即将执行的下一条指令的地址
CPU的上下文指的就是CPU寄存器和程序计数器及其所在的环境,而上下文的切换指的就是:CPU保存当前任务的寄存器和程序计数器的信息,然后加载新的寄存器和程序计数器,最后跳转到该程序计数器所指的新的指令位置,开始新的任务。
当然,这里提到的任务,主要包含进程、线程、中断。
所以,根据任务的不同,把CPU的上下文切换分为:进程上下文切换、线程上下文切换、中断上下文切换
进程的上下文切换到底是切换什么呢?
进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源。
发生进程上下文切换的场景?
- 进程分配的时间片已经用完,需要轮换到下一个进程
- 系统当前的资源不足,不足以支持该进程的运行
- 进程通过
sleep
将自己主动挂起 - 比自己更高优先级的进程需要运行时
- 发生硬件中断时,当前进程会被挂起
二、线程
早期科学家们以进程为基本单位,后来发现进程的一些资源过于庞大,不太利于维护,于是出现了更小能独立运行的单位: 线程
1. 为什么使用线程?
我们举个例子,假设你要编写一个视频播放器软件,那么该软件功能的核心模块有三个:
- 从视频文件当中读取数据(I/O)
- 对读取的数据进行解压缩(CPU)
- 把解压缩后的视频数据播放出来(显卡)
对于单进程的实现方式,我想大家都会是以下这个方式:
main(){
while(1){
// 读取数据,主要使用I/O进行操作
Read();
// 数据解压缩,主要使用CPU进行操作
Decompress();
// 播放视频数据
Play();
}
}
这样会造成 CPU解压缩这个操作,有可能在等待着读取数据的进行,毕竟读取数据是一个I/O操作,有可能会进行堵塞。同样,由于不是并发执行,浪费了资源的使用效率。
而多并发的进程也会存在一下问题:
- 资源开销大,毕竟需要创建虚拟内存,分配资源,切换PCB所在的队列类型,还有回收资源,保存现场
- 进程间如何频繁进行通信,共享数据?
2. 什么是线程?
线程是进程当中的一条执行流程。
同一个进程内多个线程之间可以共享代码段、数据段、打开的文件等资源,但每个线程各自都有一套独立的寄存器和栈,这样可以确保线程的控制流是相对独立的。
3. 线程与进程的比较
- 进程是资源分配的单位,线程是CPU调度的单位
- 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如:寄存器和栈
线程相对进程能减少开销,体现在:
- 进程在创建的过程中,需要资源管理信息,比如:内存管理信息、文件管理信息等,而线程仅仅是共享他们
- 同一进程线程切换比进程切换的开销小,因为线程占用同样的虚拟内存,不需要重新切页表,只需要保存自己的寄存器和栈即可
- 由于同一进程的各线程共享内存和文件资源,在数据传递的过程中,不需要内核的参与,效率变高
4. 线程的上下文切换
操作系统的任务调度,实际上的调度对象是线程,而进程只是给线程提供了虚拟内存、全局变量等资源。
对于线程和进程,我们可以这么理解:
- 当进程只有一个线程时,可以认为进程就等于线程;
- 当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源,这些资源在上下文切换时是不需要修改的;
另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保存的。
线程上下文切换指什么?
- 当两个线程不是属于同一个进程,则切换的过程就跟进程上下文切换一样;
- 当两个线程是属于同一个进程,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据;
5. 线程的实现
- 用户线程:在用户空间进行实现,由用户控制 TCB 的信息。
- 内核线程:在内核中实现的线程,由内核控制
- 轻量级线程:内核支持用户线程
三、调度
之前讲过的进程时间片用完之后,怎么分配时间片就被称为:调度算法
1. 调度时机
- 就绪态 —> 运行态
- 运行态 —> 阻塞态
- 运行态 —> 结束态
根据时钟的中断可以把调度算法分为两类:
- 非抢占式中断调度算法:挑选一个进程,直到该进程运行完毕
- 抢占式调度算法:每个进程分配相应的时间片,当时间片用完之后,轮到下一个进程
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
时间片,当时间片用完之后,轮到下一个进程
[外链图片转存中…(img-L5e3zkC4-1715637209785)]
[外链图片转存中…(img-JgHbCGLP-1715637209785)]
[外链图片转存中…(img-rkMOfMrA-1715637209785)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新