当前位置: 首页 > article >正文

Linux系列-进程的状态

🌈个人主页:羽晨同学 

💫个人格言:“成为自己未来的主人~”  

操作系统就是计算机领域的哲学,是为了保证在所有情况下都适用,加载到内存叫做新建状态。

并行和并发

计算机同时进行多个任务,在用户感知的时候,每个任务都在跑,但实际上我的电脑是单CPU。跑一个程序,然后放下去,再跑下一个,构成循环,一次类推。

一个CPU执行进程代码,不是把进程代码执行完毕,才开始执行下一个代码。而是给每一个进程。

而是给每一个进程预分配一个短暂的时间片。

基于时间片,进行调度轮转,这个叫做并发。

为什么当进程进入死循环,但是电脑不会卡死,因为CPU会当进程时间到了之后执行下一个进程。

CPU切换和运行的速度非常快,用户感知不到。

CPU的效率非常快,有一个进程,其实相当于每一个进程用的都是25分的CPU。

并行:多个进程在多个CPU下面同时运行。

时间片:

Linux/Windows操作系统,民用级别的,大部分都是分时操作系统。

这个分时操作系统就是给每一个任务分配一个时间片,每一个进程运行耗尽时间片,从CPU下来,然后下一个上去。

与分时操作系统相对应的是实时操作系统,其中,分时操作系统追求调度任务的尽量公平。

而实时操作系统追求高优先级的任务尽快完成。

等待的本质

内存中存在操作系统,灭一个操作系统都得向CPU提供一个运行队列的东西(requeue)。

struct runqueue,两个CPU,有两个runqueue的结构。

队列里面有:

Int nums;//几个进程
.......其他属性
task_struct *head;

执行的时候,head指向的第一个task_struct从链表上剥离下来,放到CPU中执行,然后head指向下一个task_struct,时间片到了之后,然后这个task_struct就放到链表的最后面。

先进先出的时间片轮转。

进程的运行状态:

只要该进程在运行队列中,该进程就叫做运行状态,这个运行状态指的是已经准备好了,可以被CPU随时调度。

其实在进程的执行过程当中,少不了外设的访问,比如如果代码中有scanf,当执行到这个的时候需要访问键盘,但如果这个时候键盘的数据没有准备好,这个被CPU运行的进程,就会被设置为阻塞状态。

scanf内部封装了系统调用(让操作系统去查看键盘有没有数据),如果没有,操作系统会把这个进程直接放到设备的运行队列当中,不放到调度队列里,把当前的进程的PCB连入设备的wait_queue中,不要等待CPU的资源,等待设备的数据,这个时候就处于阻塞状态。

CPU有自己的运行队列

我们可以用先描述在组织来反映进程的管理,也可以反映出对底层硬件的管理。操作系统要管理底层的硬件吗,当然是要管理的,那怎么管理呢?,先描述,在组织。

操作系统会创建一个device的结构体,最终形成一个队列来对其进行管理。

struct device
{
    int type;
    int status;
    //管理时间
    //其他属性
    struct device *next;
    task_struct *wait_queue;//等待队列
}

然后我们将不同硬件之间采用链表进行连接。

构成

struct device*devices;

只有操作系统知道键盘有数据,

当硬件上有数据了,硬件会通过一定的方式告诉操作系统,操作系统是硬件的管理者。

当操作系统发现键盘上有数据,只需要把设备上等待的第一个进程重新放入调度队列当中。

所谓的运行状态,阻塞状态,本质就是让PCB处在不同的队列当中。

而CPU基于时间片进行轮转,所以会重新调度起来。

在操作系统上调度这个进程可以通过队列的尾插算法,队列的头部删除等队列的增删查改。

进程会卡住,是因为CPU不调度它了(等待外设/进程太多)

如果启动的应用特别多,手机会特别卡,CPU调度一个进程的周期变长了。

等待的本质是:连入目标外部设备,CPU不调度。

状态

常见的状态是在结构体中表达出来的,如:

#define RUNNING 1
#define BLOCK 2
    struct task_struct
    {
         int status;
     }

挂起

挂起的情况发生的背景主要就是当内存资源严重不足时。

当阻塞的时候,代码和数据仍在CPU,但是不会调度(因为要等待外设的响应),若是这个时候内存资源严重不足,为了保护系统资源的安全,把指定的特殊进程的数据,换出到磁盘,等待外设就绪,把这个代码和输出换入到内存,然后把PCB加到内存的运行队列中,磁盘中有一个专门换入换出的区,叫做swap分区。

换出不止换出一个进程,所有等待的外设进程,都有可能被换出。

阻塞挂起状态

阻塞挂起状态就是在阻塞的背景下,把进程挂起。

除了阻塞挂起,还有运行时挂起最尾部的相关进程,甚至可能把调度的放到调度分区,以后用到的时候再换入。

swap分区做挂起,是在用时间换空间。

swap分区不会太大,应该是和内存等量大小的。

如果换入换出解决不了,那就可能把某些进程直接干掉。所以就出现了闪退的情况。这种情况再Linux中尤其常见。

Linux中的状态

R

运行状态

S

休眠,阻塞等待状态。

printf是在云服务器上跑的,可以被信号直接中断,所以这个s也叫做,可中断睡眠,浅睡眠。

D

disk sleep 磁盘休眠,也是阻塞等待的状态的一种。

不可中断睡眠,深度睡眠。

磁盘,存取数据,是永久存储的,不可以中断等待,禁止操作系统删除这个进程。

等待磁盘的时候必须设置为D状态,D状态也是一种瞬时的状态,若是查到了一个D状态,一般都是磁盘/系统快挂掉了。

T

kill -18/19

19是暂停一个进程

18是继续一个进程,这个时候继续的时候,是杀不掉这个进程的,因为这个时候状态显示的是S,后面是没有加号的,这个时候只能使用kill命令来杀掉进程。

ctrl c能终止的叫做前台进程,杀不掉的叫做后台进程。

前台进程的时候,输入ls pwd是没有影响的。

若是我们想要这个进程直接变成后台进程,应该怎么操作呢?

运行的时候,使用这个命令:

./code &

为什么要把命令放在后台呢,因为耗时的操作,让系统自动完成,所以把他放在后台(比如下载页面的时候最小化,就是后台)。

现在的APP,退出的时候还存在,但是处于暂停的状态,这个时候就处于后台,不影响前台的任务。

t

进程做了非法但是不致命的操作,被OS暂停了。

当一个进程被追踪的时候,断点停下。

X

死亡状态,杀掉了或者跑完了,进程最开始为什么要被创建,是为了完成用户的任务的,通过进程执行的结果,来告知父进程或者操作系统,我把任务完成的如何了。

我们可以使用下面的这个命令来查看进程执行的结果。

echo $?

这个程序查看的是最近程序退出时候的退出码。

0表示执行成功,非0表示这个程序是错误的。 

我们在执行C语言当中的main函数的时候,main函数的返回值是为了告诉父进程这个进程的执行结果是不正确的。

返回0是因为自己总认为自己执行的是正确的。

该状态就是改PCB当中的属性。

比如说我们写一个程序,当有printf的时候是S状态,是因为根据冯诺依曼体系,它是要往缓存上写的,而且要等待外设准备就绪,所以要一直处于IO状态。去了printf就是R状态。

Z

也叫做僵尸状态,先得进入Z状态,才会进入X状态,进入Z状态,维持退出信息,方便父进程和操作系统来进行查询,X状态是不需要队列的,Z状态是不需要队列的。

 好了,本次的文章就到这里了,我们下次再见。 


http://www.kler.cn/a/383672.html

相关文章:

  • 知乎 PB 级别 TiDB 数据库集群管控实践
  • Gin-vue-admin(1):环境配置和安装
  • esp8266_TFTST7735语音识别UI界面虚拟小助手
  • 使用Vue+Django开发的旅游路书应用
  • Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器
  • 【视觉SLAM:八叉树地图(Octree Map)概述】
  • 动态规划理论基础和习题【力扣】【算法学习day.25】
  • apache poi 实现下拉框联动校验
  • MySQL表转移数据的三种方式
  • 【Python进阶】Python中的网络爬虫策略:高效数据抓取与解析
  • 数据库优化指南:如何将基本功能运用到极致?
  • Qt(程序打包)
  • ubuntu 异常 断电 日志 查看
  • 半导体设备行业,多单收购
  • 微信小程序大学生闲置物品交易平台+ssm(lw+演示+源码+运行)
  • 势不可挡 创新引领 | 生信科技SOLIDWORKS 2025新品发布会·苏州站精彩回顾
  • vue实现websocket实时短消息通知
  • 完全背包模板总结
  • 设计者模式之策略模式
  • 《构建一个具备从后端数据库获取数据并再前端显示的内容页面:前后端实现解析》
  • 集中管理用户名和密码,定期修改密码快捷方便
  • 参数跟丢了之JS生成器和包装器
  • PostgreSQL核心揭秘(三)-元组结构
  • 【科普】conda、virtualenv, venv分别是什么?它们之间有什么区别?
  • 讲讲RabbitMQ 性能优化
  • Qt中弹出窗口的实现与鼠标事件处理