目录
上篇细谈了Linux中对OS进程状态的具体实现,那本篇谈谈OS的进程状态的指导思想。
OS的进程状态
- 前文的Linux中进程的状态到底如何在LinuxOS内核中如何理解。
- OS是指导思想,OS的进程状态放在任何一款OS上都适用。
- 上篇我们讲解的RSZXDTt都是Linux在指定思想下的具体实现。
- 不同OS对进程状态的实现是不同,大体方向作用一样。
- 下面具体讲解三种进程状态:运行 / 阻塞 /挂起
R运行
运行状态:并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- 进程的运行一定是在CPU上运行的。所以CPU中央处理器在OS中也有自己的PCB内核数据结构。
- task_struct 包含进程的属性信息 和 链接信息(调度算法,后面讲)
- 每个CPU在OS中,都要维护一个运行队列的结构体。struct runqueue
❗❗❗❗进程在运行前,前提条件是:进程所在的内核数据结构必须在CPU在OS中的运行队列中。懂!之后进程才能被OS调度进入CPU运行。
- 所以严格意义来讲,一个进程的代码和数据被调度到CPU中才算这个进程处于R状态。
- 但是一般而言,只要这个进程在运行队列中,该进程的状态就是R状态。(进程我已经准备好了,准备被随时调度)
轮转调度&时间片
❓一个进程一旦持有一个CPU,会一直运行到进程结束吗。一个CPU会一直执行完一个进程再执行下一个吗?
- 当然不会。如果遇到一个进程是死循环,那么其他进程全部都不运行了吗。
❓我们发现无论是Linux还是windowsOS都是多个进程可以同时运行的。 是因为一个CPU可以运行多个进程吗
- 当然不是。一个CPU只能运行一个进程。
这是因为OS调度的原理:OS内核是基于时间片进行轮转调度的。(CPU运行的速度极快,所以在我们的用户层面看起来像多个进程同时运行,同一时间内多个进程同时运行)
- 进程=task_struct+代码和数据
- task_struct除了属性和链接信息
- task_struct存在调度相关的信息:时间片
- 并发:让多个进程以切换的方式进行调度,在一段时间内同时得以推进代码。
- 并发是逻辑上的同时发生,指两个或多个事件在同一时间间隔发生,是在同一实体上的多个事件。
- 并行:任何时刻,都同时有多个进程在真的同时运行。
- 并行是指多个处理器或者是多核的处理器同时处理多个不同的任务,物理上同时发生。
- 时间片轮转切换调度是教材OS中最简单的一种,Linux不是这样调度的,后面讲。
假设时间片是2ms。若进程在CPU中运行2ms未结束,时间片一到,OS自动把CPU上的进程剥离下来,放到运行队列的尾部。让CPU运行下一个进程。循环往复,轮转调度。让每个进程在一段时间内得到调度。(切换速度非常快)
【并发&轮转调度】
【并行&双核CPU】
进程切换
x86_64的CPU寄存器有哪些?>>>大模型查一下
- 进程A被OS调度到CPU运行
- CPU中存在大量的寄存器
- 进程A的上下文都被保存在CPU内的寄存器里面
- 若时间片到了,进程A执行完毕即可
- 若时间片到了,进程A没有执行完,OS切换调度下一个进程B
- 此刻从CPU上剥离进程A的时候,进程A的上下文都被保存在寄存器里面,这些被保存的信息全被A进程带走。(上下文信息保存再A进程的PCB里面,OS中的任务状态段)
- OS再次调度A进程到CPU运行的时候,上下文信息又被恢复到CPU的寄存器,历史上执行过的代码不会再次执行,会根据上下文信息,从上次运行结束地方开始再次运行。
- 进程的上下文:CPU内部所有的寄存器中的临时数据。
- 进程的上下文保存在进程控制块PCB里面
- PCB中的tss是任务状态段,用来保存进程的上下文的
- CPU内部的会有非常多的寄存器
- CPU内的寄存器:寄存器本身时硬件,具有数据存储能力,CPU寄存器硬件只有一套!
- CPU内部的数据:可以有多套,有几个进程就有几套与该进程对应的上下文数据!
- 综上:寄存器 !=寄存器数据(内容)
- 运行>>>>>保存上下文到PCB>>>>在运行队列排队>>>>恢复上下文
S阻塞
❓C语言中使用了scanf函数来从键盘获取数据,如果用户不输入数据,此时这个进程处于什么状态
❓为什么处于这种状态,这个进程在等待什么资源
- 处于阻塞态
- 阻塞态相当于Linux中的S态,在等待键盘资源
- 等待键盘资源就是还未被调度,不在运行队列里面,处于S态
- S浅度睡眠
- D深度睡眠,等待磁盘资源
❓OS对硬件如何做管理的。
- 先描述再组织
- 每个硬件在OS中都有自己的PCB内核数据结构。struct device
- 不是只有CPU才有自己的运行队列,各种硬件设备都有自己的等待队列。wait_queue
❓进程此刻在哪里等待外设资源呢
- 综上所述,进程没有被调度,不在运行队列,在键盘的等待队列中。
- 阻塞的数据和代码还是存在于内存中。
S阻塞&R运行&唤醒
- 阻塞和运行的状态变化,往往是伴随着PCB被连入不同的队列中!
- 入队列的不是进程的代码和数据而是进程的task_struct
- 深入理解进程的状态变量从R到S,不仅仅是进程的状态发生变量,而是进程的task_struct被列入不同的队列(等待队列/运行队列)
- R运行:就是进程的task_struct处于运行的队列,或者处于CPU中运行
- S阻塞:阻塞状态,是进程的task_strcut处于等待队列,未被调度。
- 进程的task_struct从等待队列到运行队列叫唤醒。
T/t阻塞
T/t阻塞:
程序Debug等待另外一个进程是否发消息给当前在等待的进程,算是一种特殊的阻塞状态。
挂起(挂起阻塞)
关于挂起有很多类型:挂起阻塞,挂起就绪等等。这里主谈阻塞挂起,因为阻塞所以挂起。
在我们用软盘装一个OS的时候,对整个磁盘需要分区,其中有一个分区叫Swap分区。在磁盘中单独开辟的空间,和内存大小一样大,或者是内存的1.5~2倍,不能太大也不能太小。
Swap space交换空间,是虚拟内存的表现形式。系统为了应付一些需要大量内存的应用,而将磁盘上的空间做内存使用,当物理内存不够用时,将其中一些暂时不需要的数据交换到交换空间,也叫交换文件或页面文件中。
实际上,进程在内存中处于R运行的时候,OS内存空间是非常紧张的。
进程申请内存空间都是向OS申请。这个时候就会出现申请不通过的情况,因为OS内存空间严重不足。
一部分原因是:一部分进程处于阻塞状态(在等待队列中等待资源)
这些进程处于阻塞状态,就意味着这个进程不会被调度运行,原则上这个进程的代码和数据是不会被访问的。
- 处于阻塞态的进程的数据和代码不会被OS访问,所以可以把进程的代码和数据唤出内存,到磁盘的Swap分区当中。
- OS就可以腾出一些内存空间存放处于R状态的进程的数据和代码了(解燃眉之急)
- 当处于阻塞态的进程等待的资源就绪,进程处于运行态了,再把放在磁盘中的代码和数据,唤入内存。
❓请问唤出的进程还存在吗
- 当然还存在。因为PCB依旧存在于OS的内核当中,只不过代码和数据放到了Swap当中
- 这种情况就叫阻塞挂起态。
- 挂起状态也往往喜欢和其他状态相结合。阻塞挂起,新建挂起,就绪挂起等等.....
- 挂起态是为了更加合理的使用内存资源。
- 无论是任何OS都会保留Swap分区,相当于无形之中拥有了两倍的内存。
- Swap分区适中即可,不可太大大小,OS过度依赖Swap分区,导致频繁的唤入唤出,整个OS调度的效率就降低了。合理使用Swap分区
- 唤出唤入是非常快的,用户层是感知不的。
- 频繁的唤出唤入也会降低效率,是以时间换空间的做法。
- 进程调度增加了唤入唤出这样的逻辑,相当于增加了IO,导致进程的调度周期变长,牺牲了效率换了空间。
- 小tips>>>运维>>>>fdisk磁盘的区域划分和写入文件系统的函数
查看进程的PCB(Linux中的task_struct)
非常多的内部属性(pid,ppid,退出信息等等) 。
🙂感谢大家的阅读,若有错误和不足,欢迎指正。