【Linux学习】深入了解Linux中进程状态及其转换
文章目录
- 进程状态
- 进程排队
- 进程的状态(运行,阻塞,挂起)
- 进程的七个状态
- 孤儿进程
进程状态
进程 = task_struct + 可执行程序
进程不是一 直在运行的,可能在等待软硬件资源,比如scanf后,程序停止运行了,在等待用户输入。进程放在CPU上,也不是一直在运行的。时间片:进程在CPU上的时间,过了就会被拿下。
进程排队
先简单看看进程排队:
所谓的进程排队,一定是在等待某种资源,排队是进程的PCB(task_struct)在排队,而不是进程的可执行程序在排队。
一个task_struct(进程的PCB)可以被连入多种数据结构中, 在Linux内核中,每一个进程的PCB不是连入到单链表中的,而是连入到双链表的(队列可以用链表实现),这个结构和书本上学习的双链表结构一样的但用法不同而已,请看图解:
图一:
注释:如果像下图这样管理PCB的话(也就是每一个进程PCB中包含两个指针,但是这样只能连入一到一个数据结构中,如果想要连入到多种数据结构中,必须加指针,浪费空间,并且难维护),所以这种结构是不合适的。
图二:
注解:每一个进程的PCB中,包含特殊的结构体,然后将这个结构体指针放入双链表中进行管理,这样,就可以通过这个结构体指针找到进程的PCB,这个结构体指针也可以连入多种数据结构中。(利用struct listnode在对应进程的PCB中偏移量计算PCB的地址:(task_struct*)(&n-&((task_struct)0-> n)。如果PCB中存在很多个特殊的结构体,就可以将PCB连入到很多不用的数据结构中进行管理。
进程的状态(运行,阻塞,挂起)
所谓的状态,其实就是一个整型变量,在task_struct里面的一个整型变量:
状态决定了什么?
状态决定了下一步的后续动作。
一个CPU一个运行队列。
如简图:
-
运行状态:一个进程的PCB在CPU的运行队列上,不一定正在运行,把该进程的状态成为运行状态;
-
阻塞状态 :
每一个设备为了操作系统能够管理。都会被先描述,后组织。将设备用一个结构体描述,结构体里面可能会包含设备类型,状态,以及当前设备的等待队列等。
当一个进程在等待软硬件资源的时候,如果资源没有就绪,例如scanf时,操作系统会将该进程PCB从与逆行队列拿下来,状态由运行改为阻塞,连入到等待的资源提供的的等待队列中,等待资源;
- 其中,状态的变迁引起的是PCB会被OS变迁到不同的队列中。
- 挂起状态:
前提:当计算机资源已经很吃紧了;
阻塞挂起:已经很吃紧了,但是有一些进程暂时不会被调度,操作系统会将该进程的代码与数据写入到外设(磁盘)中去,也就是腾空间。(磁盘有一个固定的区域,叫做swap分区,是用来给操作系统在资源紧张的时候,用来和磁盘进行数据的唤入与唤出)
注意:进程的PCB不会被唤入(将数据拷贝到外设)唤出(将数据从外设唤入到内存)。
创建一个进程的时候,先创建进程的对应的内核数据结构(PCB),再将代码与数据加载到内存(可以一部分一部分的加载,按需加载) 。
进程的七个状态
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(阻塞状态)。crtl+c可以终止进程。
- D磁盘休眠状态(Disk sleep),有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。(阻塞状态)crtl+c不可以终止进程。
- T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
- t(停止状态):在调试的时候可以看见。
- Z(zombine):僵尸状态。
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
Linux进程状态转换图:
测试:使用指令
# ps ajx | head -1 && ps ajx | grep myprocess
测试代码1:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 5 int main()6 {7 while(1)8 {9 printf("i am a proces id:%d\n",getpid());10 sleep(1); 11 }12 return 0;13 }
运行结果:
- 问题:为什么我的代码在运行,但是确是S状态呢?
答:因为CPU执行你的代码非常快,剩下的还执行了sleep函数,导致该进程大多时间处于sleep状态,只有很少量的时间被调度了一次,导致很难观察到运行状态。
测试代码2:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 5 int main()6 {7 while(1)8 {9 printf("i am a proces id:%d\n",getpid());10 //sleep(1); 11 }12 return 0;13 }
运行结果:
- 问题:为什么我的代码将sleep注释掉了再运行,但是确还是S状态呢?
代码中使用的printf函数,是要访问外设的,但是要访问这个设备,这个设备的资源不一定准备就绪了,但是CPU的执行速度很快,但是硬件的速度很慢,导致大部分时间也是在等待状态的。
测试代码3:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 5 int main()6 {7 while(1)8 {9 //printf("i am a proces id:%d\n",getpid());10 //sleep(1); 11 }12 return 0;13 }
运行结果:
- 为什么状态后有+呢,比如:S+
后面带有+,说明是前台进程,没有代表为后台进程:
例如:
指令(前台进程变为后台进程)
# ./myprocess &
可以将前台进程变为后台进程,后台进程使用键盘ctrl+c不能杀掉,只能用命令kill -9 杀掉;
例如:
测试代码:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 5 int main()6 {7 while(1)8 {9 printf("i am a proces id:%d\n",getpid());10 sleep(1); 11 }12 return 0;13 }
T状态的测试:
测试代码:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 5 int main()6 {7 while(1)8 {9 printf("i am a proces id:%d\n",getpid());10 sleep(1); 11 }12 return 0;13 }
运行结果:
T状态:让进程处于暂停状态。
t状态的测试:
当我们调试代码的时候,在每次单步执行的时候,程序会处于t状态(停止状态);
示例:
Z状态,僵尸状态:当一个进程退出后,但是该进程的状态需要自己维持住,供上层读取。也就是进程从退出到资源被清理的这个时间段,进程所处于的状态。
- 当一个进程退出过后,代码和数据可以被直接释放,因为已经没有用了,但是,当前进程所对应的PCB,还不能被释放,里面还有记录进程的退出信息,是为了让系统或者其他进程能够读取到该进程的的退出信息进而执行下一步动作。只有该数据被拿走过后,这个进程才是真正的死亡状态。PCB才会被清理释放。
- 如果父进程不读取子进程的退出信息,僵尸状态的进程,会一直存在,task_struct对象也会一直存在,都是要暂用内存的,会有内存泄漏。在Linux系统中,所有的进程退出后都是Z状态。只有被别人读取完成后,才会变为X状态。
测试代码:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h> 45 int main()6 {7 pid_t id = fork();8 if(id==0) 9 { 10 int cnt = 5; 11 while(cnt) 12 { 13 printf("i is child id:%d pid:%d\n",getpid(),getppid());14 sleep(1);15 cnt--;16 } 17 exit(0); //让子进程直接退出 18 }19 //father 20 while(1) 21 {22 printf("i is father id:%d pid:%d\n",getpid(),getppid());23 sleep(1);24 }25 return 0;26 }
结果:5秒过后子进程状态变为Z(僵尸状态):因为进程退出后,退出信息你没有被读取;怎么读取后续文章再给出。
孤儿进程
如果一个进程的父进程已经退出,但是子进程还没有退出,这个子进程就被叫做孤儿进程。
这是孤儿进程会变为后台进程,只有不能ctrl+c杀掉,可以通过kill命令。
这个进程会被1号进程(操作系统)所领养;如果不被领养,就变成没有主的进程,当程序退出时,就会一直为僵尸进程,就会一直暂用资源(空间),所以孤儿进程会被1号进程领养,这样该进程的资源还可以被操作系统所回收。
测试代码:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h> 4 5 int main()6 {7 pid_t id = fork();8 if(id==0)9 {10 int cnt = 50;11 while(cnt)12 {13 printf("i is child id:%d pid:%d\n",getpid(),getppi d());14 sleep(1);15 cnt--;16 }17 exit(0); //让子进程直接退出18 }19 //father20 int cnt = 5;21 while(cnt)22 {23 printf("i is father id:%d pid:%d\n",getpid(),getppid ());24 sleep(1);25 cnt--;26 }27 printf("父进程退出\n");28 return 0;29 }
相关文章:

【Linux学习】深入了解Linux中进程状态及其转换
文章目录 进程状态进程排队进程的状态(运行,阻塞,挂起)进程的七个状态 孤儿进程 进程状态 进程 task_struct 可执行程序 进程不是一 直在运行的,可能在等待软硬件资源,比如scanf后,程序停止运…...

【Python设计模式11】建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建过程分离出来,使得同样的构建过程可以创建不同的表示。建造者模式通过使用多个简单的对象一步一步构建成一个复杂的对象。 建造者模式的结构 建造者模式…...

coredump文件生成配置
1.打开coredump文件生成开关 查看开关是否打开:ulimit -a 如果core file size 为0,则为关闭。 执行:ulimit -c 10240 将其coredump文件大小设置。 2.coredump文件保存位置: /proc/sys/kernel/core_pattern文件可以控制core文…...

jmeter线程组(下篇)
线程组 线程组作为JMeter测试计划的核心组件之一,对于模拟并发用户的行为至关重要。线程组元件是整个测试计划的入口,所有的取样器和控制器必须放置在线程组下。 可以将线程组视为一个虚拟用户池,其中每个线程可被理解为一个虚拟用户&#x…...

Stable Diffusion【写实模型】:逼真,逼真,超级逼真的国产超写实摄影大模型万享XL
今天和大家分享的是一个国产万享系列中使用量最高的大模型:万享XL_超写实摄影,顾名思义,该大模型主要是面向写实摄影,一方面生成的图片人物皮肤纹理细节超级逼真,另一方面对于光影效果的处理也非常到位。对于万享XL超写实摄影大模…...

Android 13 配置默认DN
需求: 如果存在用户配置的DNS服务器,则切面拦截运行商下发的DNS,替换为用户自己配置的DNS. 实现: 直接上代码: 1:TelephonyProperties 内新增属性保存用户设置的dns //QSSI.13/frameworks/base/telephony/java/com/android/in…...

系统开发与运行知识
系统开发与运行知识 导航 文章目录 系统开发与运行知识导航一、软件工程二、软件生命周期三、开发模型四、开发方法五、需求分析结构化分析 六、数据流图分层数据流图的画法设计注意事项 七、数据字典数据字典的内容 八、系统设计九、结构化设计常用工具十、面向对象十一、UML…...

算法训练 | 二叉树Part1 | 递归遍历、迭代遍历、统一迭代
目录 递归遍历 前序遍历 迭代遍历 前序遍历(迭代法) 中序遍历(迭代法) 后序遍历(迭代法) 统一迭代法 统一迭代 嵌入式学习分享个人主页:Orion嵌入式随想录 - 小红书 (xiaohongshu.com) …...
AcWing 2568:树链剖分 ← 线段树+DFS
【题目来源】https://www.acwing.com/problem/content/2570/【题目描述】 给定一棵树,树中包含 n 个节点(编号 1∼n),其中第 i 个节点的权值为 ai。 初始时,1 号节点为树的根节点。 现在要对该树进行 m 次操作…...

PCIe协议之-DLLP详解
✨前言: 🌟数据链路层的功能 数据链路层将从物理层中获得报文, 并将其传递给事务层; 同时接收事务层的报文, 并将其转发到物理层; 核心的功能有以下三点 1.保证TLP在 PCIe 链路中的正确传递; 2.数据链路层使用了容错…...

Jmeter+prometheus+grafana性能测试
文章目录 Jmeterprometheusgrafana性能测试背景目标设计思路原理案例启发 Jmeterprometheusgrafana性能测试 背景 在现代社会中,人们对于应用程序的响应速度和性能体验提出了越来越高的要求。无论是电子商务网站、社交媒体平台还是企业级软件系统,都…...

Hololens 2 新建自定义按钮
官方链接地址 1、创建Cube 2、添加PressableButton脚本,并点击AddNearin… 3、把Cube拖入到MovingButtonVisuals变量中 4、点击NearInteractionTouchable组件(这个组件是添加和上一个脚本绑定的,自动添加上来的)上的Fix… 5、…...

景源畅信:抖音小店新手小白如何做好运营?
在数字时代的浪潮中,抖音小店成为了众多创业者和商家的新宠。但面对激烈的市场竞争和不断变化的平台规则,新手小白如何才能在抖音小店的海洋里稳健航行,捕捉到属于自己的商机呢?接下来的内容将为你揭晓答案。 一、精准定位,明确目…...

力扣 42. 接雨水 python AC
双指针 class Solution:def trap(self, heights):l, r 0, len(heights) - 1maxl, maxr 0, 0ans 0while l < r:maxl, maxr max(maxl, heights[l]), max(maxr, heights[r])if maxl < maxr:ans maxl - heights[l]l 1else:ans maxr - heights[r]r - 1return ans单调栈…...

The 2022 ICPC Asia Nanjing Regional Contest - External D
G题 赛题补充 D题的题目来源 https://codeforces.com/gym/104128/problem/D 文章目录 题意思路代码 题意 给一个长度为n的数组,问对一段区间添加等差数列后的最大的第 k 大是多少 思路 通过观察题目可以发现答案的范围符合单调性,因此我们可以考虑二分…...

2024年蓝桥杯B组C++——复盘
1、握手问题 知识点:模拟 这道题很简单。但是不知道考试的时候有没有写错。一开始的43个人握手,仅需要两两握手,也就是从42个握手开始,而非43.很可惜。这道题没有拿稳这5分。也很有可能是这5分导致没有进决赛。 总结:…...

微调Llama3实现在线搜索引擎和RAG检索增强生成功能
视频中所出现的代码 Tavily SearchRAG 微调Llama3实现在线搜索引擎和RAG检索增强生成功能!打造自己的perplexity和GPTs!用PDF实现本地知识库_哔哩哔哩_bilibili 一.准备工作 1.安装环境 conda create --name unsloth_env python3.10 conda activate …...

【软件工程】【23.04】p1
关键字: 软件模型、提炼、加工表达工具、通信内聚、访问依赖、边界类交互分析、RUP核心工作流、首先测试数据流、软件验证过程、CMMI过程域分类工程类; 软件工程目的、功能需求是需求的主体、结构化方法、耦合、详细设计工具、类、类图、RUP采用用例技…...

Flutter 中的 ColoredBox 小部件:全面指南
Flutter 中的 ColoredBox 小部件:全面指南 在 Flutter 的世界中,ColoredBox 是一个用于填充颜色的简单而强大的小部件。它是一个不透明的矩形,可以用来创建颜色块,作为布局的占位符,或者简单地改变某个区域的背景色。…...

【LeetCode 随笔】面试经典 150 题【中等+困难】持续更新中。。。
文章目录 12.【中等】整数转罗马数字151.【中等】反转字符串中的单词6.【中等】Z 字形变换68.【困难】文本左右对齐167.【中等】两数之和 II - 输入有序数组 🌈你好呀!我是 山顶风景独好 💝欢迎来到我的博客,很高兴能够在这里和您…...

SwiftUI中AppStorage的介绍使用
在Swift中,AppStorage是SwiftUI中引入的一个属性包装器,在这之前我们要存储一些轻量级的数据采用UserDefaults进行存取。而AppStorage用于从UserDefaults中读取值,当值改变时,它会自动重新调用视图的body属性。也就是说࿰…...

iCloud 照片到 Android 指南:帮助您快速将照片从 iCloud 传输到安卓手机
概括 iOS 和 Android 之间的传输是一个复杂的老问题。将 iCloud 照片传输到 Android 似乎是不可能的。放心。现在的高科技已经解决了这个问题。尽管 Apple 和 Android 不提供传输工具,但您仍然有其他有用的选项。这篇文章与您分享了 5 个技巧。因此,…...

知识点总结
1、Uboot的流程调用: 1.1、cmd_process函数是怎么被调用到的: cmd_process在common/command.c 1.2、uboot阶段断电,后续起不来,可能要换线去使用,也许和电源线有关 2、git 相关使用 2.1 .gitignore相关的使用 1、…...

Python并发与异步编程
Python的并发与异步编程是两个不同的概念,但它们经常一起使用,以提高程序的性能和响应能力。以下是对这两个概念的详细讲解: 并发编程 (Concurrency) 并发编程是指在程序中同时执行多个任务的能力。Python提供了几种实现并发的机制ÿ…...

动态内存管理—C语言通讯录
目录 一,动态内存函数的介绍 1.1 malloc和free 1.2 calloc 1.3 realloc 1.4C/C程序的内存开辟 二,通讯录管理系统 动态内存函数的介绍 malloc free calloc realloc 一,动态内存函数的介绍 1.1 malloc和free void* malloc (…...

美光EMMC芯片丝印型号查询 8LK17/D9PSK, OXA17/JY997
问题说明 最近在使用美光EMMC的时候,发现通过芯片丝印查询不到 芯片的规格说明书; 经过查阅资料,发现美光的EMMC芯片 “由于空间限制,FBGA 封装组件具有与部件号不同的缩写部件标记”,需要通过官网查询丝印的FBGA cod…...

win32-鼠标消息、键盘消息、计时器消息、菜单资源
承接前文: win32窗口编程windows 开发基础win32-注册窗口类、创建窗口win32-显示窗口、消息循环、消息队列 本文目录 键盘消息键盘消息的分类WM_CHAR 字符消息 鼠标消息鼠标消息附带信息 定时器消息 WM_TIMER创建销毁定时器 菜单资源资源相关菜单资源使用命令消息的…...

springboot项目部署到linux服务器
springboot后端 修改前 修改后 vue前端 修改前 将地址中的 localhost改为 ip 重新生成war包 war上传到linux的tomcat的webapps下 其他环境配置和macOS大差不差 Tomcat安装使用与部署Web项目的三种方法_tomcat部署web项目-CSDN博客...

MagicLens:新一代图像搜索技术和产品形态
MagicLens:Self-Supervised Image Retrieval with Open-Ended Instructions MagicLens: 自监督图像检索与开放式指令 作者:Kai Zhang, Yi Luan, Hexiang Hu, Kenton Lee, Siyuan Qiao, Wenhu …...

[9] CUDA性能测量与错误处理
CUDA性能测量与错误处理 讨论如何通过CUDA事件来测量它的性能如何通过CUDA代码进行调试 1.测量CUDA程序的性能 1.1 CUDA事件 CPU端的计时器可能无法给出正确的内核执行时间CUDA事件等于是在你的CUDA应用运行的特定时刻被记录的时间戳,通过使用CUDA事件API&#…...