初识进程状态
🌎进程状态【上】
文章目录:
进程状态
发现进程的状态
运行队列
进程排队
进程状态的表述
状态在代码中的表示
运行状态
阻塞状态
挂起状态
总结
前言:
为了搞明白正在运行的进程是什么意思,我们有必要了解进程的不同状态,那么话不多说,开始我们今天的话题!
🚀发现进程的状态
我们按照上次所说的创建子进程,分别执行不同的工作:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 #include<sys/types.h>5 6 int main()7 {8 printf("before fork!\n");9 sleep(3);10 printf("start fork!\n");11 sleep(1);12 13 pid_t id = fork();14 if(id < 0)15 {16 perror("fork error!\n");17 exit(0);18 }19 20 if(id == 0)//子进程21 {22 int cnt = 6;23 while(cnt)24 {25 printf("I'm child process, pid=%d\n", getpid());26 sleep(1);27 cnt--; 28 }29 exit(0);30 }31 //父进程32 sleep(1);33 int cnt = 5;34 while(cnt)35 {36 printf("I'm father process, pid=%d\n", getpid());37 sleep(1);38 cnt--;39 }40 41 return 0;42 }
~
这里使用了 exit() 函数,我们以前可能在C语言里见到过它,只知道它可以退出程序。其实在Linux当中exit函数是 退出进程 接口:
它的作用是终止一个进程,而函数参数是 退出码(这个以后会谈),表示 退出状态。
那我们把程序运行起来之后,再使用监控脚本进行监控:
观察我们从监控脚本得出的结果,我们发现带有 STAT 的一栏里除了最后一项我标红的位置为 “Z” 外,其他的状态都是 “S+” 状态,并且在标红的这一行,的最后,出现了 <defunct> 的字样。
这个就是我们今天要说的——进程状态。
🚀运行队列
进程的状态,一定是与CPU如何执行有关的,所以在了解进程状态之前,有必要先了解CPU如何执行进程。
我们说过,程序运行起来时就是一个进程,进程需要被CPU给执行,并且进程是以 循环队列 的形式被CPU执行,但是进程在CPU上并不是一直在执行的。
每一个进程都有自己的 时间片 ,也就是 每个进程运行最大时间,超过这个时间如果程序还没有被执行完毕,则强制退出,执行下一个进程,这个进程则重新排队等待CPU资源。
当然,有些情况下进程也许是在等待某些硬件资源,所以并不会一直执行,比如:
#include<stdio.h>int main()
{int ind = 0;scanf("%d", &ind);printf("%d", ind);return 0;
}
这个时候,程序此时就在等待我们硬件资源,也就是键盘的写入。
我们知道,进程 = task_struct + 可执行程序 ,那我们进程在排队的时候是 task_struct 在排队,还是可执行程序在排队,亦或是两者都排队呢?我们不妨讲个故事:
有一天,阿熊自信满满,觉得自己实力已经可以去闯闯了,于是阿熊连夜写了一份简历,第二天就向自己心仪的公司投递了过去,每天期待着答复。
这天,面试官手里拿着10份简历,按照面试官对应聘者的评价依次排放,筛选出自一半交给了hr,很幸运,阿熊居然没被刷下来,hr按照这个顺序依次比较,最后hr看着阿熊的简历坦然一笑…[未完]
其实,阿熊可以看为进程的代码和数据,而简历可以看作进程的PCB,而阿熊的简历被hr拿到的简历在一起的时候,其实就是进程排队的过程。
所以我们可以得出 结论:进程排队不是进程的可执行程序在排队,而是进程的PCB在排队!
于是就在当天晚上,阿熊收到了一封短信:“尊敬的阿熊,介于您出色的表现,已经进入我司人才库…” 然而就在阿熊一个人偷抹眼泪的时候,某个面试官正在骂骂咧咧投递自己的简历到另一家公司…[结束]
🚀进程排队
那么如何理解进程排队这件事情,进程排队本质上就是数据结构的双向链表,但是稍稍不同的是,这个指针指向的并不是下一个PCB的开始,而是PCB内部的一个指针。
那么如何通过PCB的中间链表去访问链表以上的属性信息呢?其实很简单:
struct task_struct
{char ch1;char ch2;char ch3;
}
假如我们要从 ch3 访问 ch1,只需要ch3 - 2,也就是根据ch3到ch1的 偏移量 来确定ch1的位置,同样,在PCB的内部也是根据偏移量来确定位置的。
那么在我们Linux内核中是如何确定偏移量的呢?
话说回来,进程排队的意义是什么?我们应该已经清楚了:只要是在排队,就一定是在等待某种资源!
🚀进程状态的表述
✈️状态在代码中的表示
我们都知道,Linux是使用C语言写的,而如何描述进程状态,其实就是使用 宏 来表示对应的状态,比如:
#define NEW 0
#define READY 1
#defien RUNNING 2
#define BLOCK 3
//...struct task_struct
{int status;//就是上面定义的宏//...
}
现在,我们能把各个状态都具象化成宏了,而这些 状态决定了进程的后续动作,Linux中可能同时运行多个进程,OS就要根据进程的状态来决定下一步做什么。
以上可能是某个教材的进程状态图,我们接下来介绍的就是,运行、阻塞、和挂起 状态。
✈️运行状态
进程有一个状态叫做 运行状态,很多人以为只有当CPU执行到当前进程时,才能称为当前进程为运行状态,实则不然。
每一个CPU其实都有一个运行队列,比如:
struct runqueue{//运行队列int count;task_struct *p;//指向进程
}
此时,整个队列的进程运行状态都为运行状态,而运行状态的意思是:
R(Running): 准备好被CPU随时调度。
✈️阻塞状态
进程有时会处于一种特殊的状态,阻塞状态 我们前面scanf等待硬件资源就会把进程拉入到一个 阻塞队列(Blocked Queue) 当中,表示正在阻塞等待某种硬件资源,当获得硬件资源后就会从阻塞队列中退出,链入到运行队列当中。
操作系统对下管理硬件资源,那么操作系统是如何管理这些硬件资源的?还是那六个字:先描述,再组织!
将硬件资源描述为一个个属性,将这些属性组织起来称为结构体,那么从此以后,操作系统对硬件的管理就变为了对这个结构体对象的管理。
struct device//硬件设备
{size_t type;//硬件类型,键盘、鼠标、磁盘,网卡等...//设备的操作方法//状态struct listnode node;task_struct *p;//指向进程//...
}
所以我们能得出的结论是:
当我们的进程在等待 软硬件资源 的时候,资源如果没有就绪,我们的进程PCB就只能: 1.将自己设置为阻塞状态。2.将自己的PCB链入等待资源的等待队列 (通常是资源竞争)。
✈️挂起状态
进程还存在一种挂起状态,这种状态与计算机内存有关系,当 计算机内存非常吃紧的时候,操作系统为了 保证向上提供良好的运行环境,所以操作系统一定会把需要等待资源的进程进行特殊处理,将内存资源释放一些,以便于 向上提供良好的环境。
比如说阻塞队列和等待队列,这些需要等待软硬件资源的进程,此时,这些进程不用我们的资源但是还占用我们的资源,所以OS就会将这些进程的代码和数据 唤入 到磁盘中的 swap分区。
其实这种挂起状态为 阻塞挂起,当然不排除有些教材里有其他挂起,但是我们就谈这一种。
唤出 仅仅是将进程的 代码和数据 唤出,进程的 task_struct 一定要保留在内存中,不然OS就没法确定这个进程的状态了。
可能在有些书里还有其他挂起,但是挂起的原因只有一个:一定是因为某种资源的紧缺才会挂起。
📒✏️总结
- 每个进程都有自己的进程状态,在C语言中以 宏 的方式体现,有了状态操作系统就知道下一步要做什么。
- 进程中存在许多队列,CPU执行的队列叫做 运行队列,阻塞等待软硬件资源的叫做 阻塞队列 和 等待队列。
- 进程排队是进程的 task_struct 在排队,而不是可执行程序在排队。并且只要是排队,就 一定是在等待某种资源分配。
- 挂起状态跟 内存有关,当内存状态吃紧时,将需要等待软硬件资源的进程的代码和数据唤出到 硬盘的 swap分区,需要时再唤出。
创作不易,如果这篇文章对您有帮助的话,还望留下一个小小的三连呀~~
相关文章:

初识进程状态
🌎进程状态【上】 文章目录: 进程状态 发现进程的状态 运行队列 进程排队 进程状态的表述 状态在代码中的表示 运行状态 阻塞状态 挂起状态 总结 前言: 为了搞明白正在运行的进程是什么意思…...
线程的使用
目录 1,创建线程的几种方式 2,示例 3,线程常用方法 3.1 std::thread类 3.1.1 成员变量 3.1.2 thread成员函数 3.1.2.1 thread 构造函数 3.1.2.2 thread 析构函数 3.1.2.3 get_id 获取线程id 3.1.2.4 joinable 3.1.2.5 join 加入 …...

flutter选择国家或地区的电话号码区号
1.国家区号列表(带字母索引侧边栏) import package:generated/l10n.dart; import package:widget/login/area_index_bar_widget.dart; import package:flutter/material.dart; import package:flutter_screenutil/flutter_screenutil.dart;class LoginA…...

信号隔离器在PLC/DCS控制系统的应用
彭姝麟 Acrelpsl 概述: 随着工业自动化程度的不断提高,变频器也得到了非常广泛的应用。作为电力电子器件,变频器中要进行大功率二极管整流,大功率晶体管变压,在输入输出回路产生电流高次谐波,干扰供电系统、负载以及附…...

探索Linux世界:基本指令(文件查看、时间相关、grep、打包压缩及相关知识)
今天继续介绍一些指令 文章目录 1.cat - 查看文件1.1输出重定向和追加重定向1.2指令echo 2.more 指令3.less - 逐页查看文本文件内容4.head- 显示文件开头部分内容5.tail - 显示文件末尾部分内容5.1输入重定向(<)5.2管道(|) 6.…...

简单使用国产数据库—达梦
达梦数据库是一款由中国的达梦软件公司开发的关系数据库管理系统(RDBMS),它在业界以其高性能、可扩展性和安全性而著称。该系统广泛应用于各种应用程序的数据存储和管理,满足用户对于数据处理和管理的多样化需求。 安装好的达梦数…...

STM32点亮LED灯与蜂鸣器发声
STM32之GPIO GPIO在输出模式时可以控制端口输出高低电平,用以驱动Led蜂鸣器等外设,以及模拟通信协议输出时序等。 输入模式时可以读取端口的高低电平或电压,用于读取按键输入,外接模块电平信号输入,ADC电压采集灯 GP…...
Android UI: 自定义控件:可换行的布局控件
文章目录 继承ViewGroup重写onMeasure方法:计算并设置布局控件的高度重写onLayout方法:计算并设置每个子控件的位置具体的代码实现小结 继承ViewGroup 重写generateLayoutParams,设置子控件的LayoutParams为MarginLayoutParams类型 Overridep…...

Linux(Ubuntu)中安装vscode
①首先去vscode的官网下载.deb文件 网址:https://code.visualstudio.com/docs/?dvlinuxarm64_deb 注:如果linux端无法打开网页下载文件,可以在Windows端下载好用WinSCP传输到Linux。下载前注意下你的系统架构是arm还是amd,系统…...

MQTT Topic通配符
🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…...
负载均衡 dubbo
1 自定义负载均衡 dubbo 在 Dubbo 中,用户可以自定义负载均衡策略以满足特定场景的需求。Dubbo 提供了扩展接口 com.alibaba.dubbo.rpc.cluster.LoadBalance 来支持自定义负载均衡算法。 要实现自定义的负载均衡策略,需要完成以下步骤: 创建…...

(含代码)利用NVIDIA Triton加速Stable Diffusion XL推理速度
在 NVIDIA AI 推理平台上使用 Stable Diffusion XL 生成令人惊叹的图像 扩散模型正在改变跨行业的创意工作流程。 这些模型通过去噪扩散技术迭代地将随机噪声塑造成人工智能生成的艺术,从而基于简单的文本或图像输入生成令人惊叹的图像。 这可以应用于许多企业用例&…...

【Spring】学习Spring框架那点小事儿
Spring作者:Rod Johnson Rod Johnson 是一位软件开发人员和作家,他在软件开发领域有着广泛的影响力。他出生于澳大利亚,拥有计算机科学和音乐双学位(能写出有优雅的代码一定有艺术细胞)。 Rod Johnson 在 2002 年出版…...

L2-035 完全二叉树的层序遍历(Python)
L2-035 完全二叉树的层序遍历 分数 25 全屏浏览 切换布局 作者 陈越 单位 浙江大学 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度…...
get命令使用提交代码
当你想要通过Git提交代码时,以下是一个详细的案例,包括从创建更改到推送到远程仓库的整个过程: 首先,确保你已经在本地仓库目录中进行了需要的更改。 添加更改到暂存区: git add . 这会将所有更改添加到Git的暂存区&…...

矩阵乘积知识
参考:矩阵点乘【矩阵点乘计算公式】_万动力 矩阵乘 矩阵相乘最重要的方法是一般矩阵乘积。它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有意义 [1] 。 哈达码积 别名:矩阵点乘&…...

10、设计模式之外观模式(Facade)
一、什么是外观模式 这个大家一定是经常使用的,外观模式(门面模式)是一种结构型设计模式。它提供一个统一的接口,用于访问子系统中的一组接口,隐藏了系统的复杂性。最简单的应用就是,当controller层的逻辑处…...
小程序APP为什么要选择游戏盾SDK防护DDOS
小程序APP为什么要选择游戏盾SDK防护DDOS?在移动互联网高速发展的今天,小程序APP已经成为了人们日常生活中不可或缺的一部分。无论是购物、娱乐还是社交,小程序APP都为我们提供了极大的便利。然而,随着小程序APP的普及,…...

STL之deque容器代码详解
1 基础概念 功能: 双端数组,可以对头端进行插入删除操作。 deque与vector区别: vector对于头部的插入删除效率低,数据量越大,效率越低。 deque相对而言,对头部的插入删除速度回比vector快。 vector访问…...

Liunx文件系统和基础IO
文件系统和基础IO 基础IOc语言基础IO函数当前路径和标准流系统IO系统调用函数重定向FILE文件结构体 在谈缓存区问题理解文件系统初识inode 基础IO c语言基础IO函数 打开与关闭 FILE *fopen(char *filename, const char *mode);选项还可以是 r/w/a 意味着为可读可写打开。 2…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...

李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...