【Linux】进程状态相关知识详细梳理

0. 预备知识

        系统调用和库函数概念

        在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。

        系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。

        有了以上概念,下面我们就来了解操作系统如何对进程进行管理,以及如何查看进程状态。

1. 进程概念

        基本概念:

                抽象概念:程序的一个执行实例,正在执行的程序等。
                内核实际:担当分配系统资源(CPU时间,内存)的实体。

        进程描述方法:

        PCB:

        进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
        课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct。

        Linux下PCB:

        在Linux中描述进程的结构体叫做task_struct。
        task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

        task_struct内容以及属性:

        标示符: 描述本进程的唯一标示符,用来区别其他进程。
        状态: 任务状态,退出代码,退出信号等。
        优先级: 相对于其他进程的优先级。
        程序计数器: 程序中即将被执行的下一条指令的地址。
        内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
        上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
        I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
        记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
        其他信息

2. 进程的组织

        可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里,也可以称为进程表。

        系统通过其中的pid进程标识符来标识不同进程。 

3. 进程信息获取 

        在/proc路径下,可以通过进程的系统文件进行查看进程状态属性:

        大多数进程信息同样可以使用top和ps这些用户级工具来获取:

         

        还可以通过系统调用来获取进程标识符(pid):

        

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid()); //系统调用getpid()获取进程pidprintf("ppid: %d\n", getppid());//系统调用getppid()获取父进程pidreturn 0;
}

4. 进程创建(fork) 

        我们可以通过fork系统调用来创建子进程,以便我们更好的感受进程,加深理解。

 fork函数“有两个返回值”,父进程会返回子进程的pid,子进程会返回0,于此同时,子进程会继承父进程的代码以及数据(以写实拷贝的形式),因此父子进程拥有相同的代码和数据,但又是互相独立的。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{int ret = fork();printf("hello proc : %d!, ret: %d\n", getpid(), ret);sleep(1);return 0;
}

fork调用后,父子进程都会从相同的代码向后运行,这样就会出现两条输出。 

除此之外,通常会用if语句通过fork返回值对父子进程进行分流,使他们执行不同的任务。 


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{int ret = fork();if (ret < 0){perror("fork");return 1;}else if (ret == 0){ // childprintf("I am child : %d!, ret: %d\n", getpid(), ret);}else{ // fatherprintf("I am father : %d!, ret: %d\n", getpid(), ret);}sleep(1);return 0;
}

5. 进程状态 

        进程状态在内核中的定义:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
(interruptible sleep))。
D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

查看进程状态的指令:

ps aux | ps axj

下面我们重点讲两个进程状态: 

5.1 Z(zombie)-僵尸进程

僵尸状态(Zombies)是一个比较特殊的状态:

当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。
僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

以下面的代码为例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{int fd = fork();if (fd < 0){perror("fork");}while (1){if (fd == 0){// 子进程printf("子进程: %d,父为:%d\n", getpid(),getppid());sleep(2);printf("子进程退出!");exit(1);}else{// 父进程printf("父进程: %d,父为:%d\n", getpid(),getppid());sleep(2);}}return 0;
}

用ps命令进行监控: 

可以看到,子进程退出后,父进程没有进行资源回收(调用wait()),子进程的状态就会变成“Z+”,其中Z表示僵尸状态 ,+表示进程属于前台进程的一部分。

僵尸进程的危害:

        僵尸进程如果一直不被父进程回收,其PCB资源也会一直被维护,会导致内存资源的浪费。

        进程表的占用:

        每个僵尸进程在进程表中保留一个条目,系统的进程表是有限的。如果僵尸进程数量过多,可能会导致进程表满,新的进程无法创建。

        资源浪费:

        虽然僵尸进程本身不占用CPU和内存资源,但它们占用的进程表条目意味着系统资源未被完全释放,可能导致系统性能下降。

如何避免僵尸进程:

5. 2 孤儿进程

        现在我们已经了解了子进程先退出,父进程不回收相关资源的情况。那么如果父进程先退出呢?

        父进程先退出,子进程会变为“孤儿进程”
        孤儿进程将被1号init进程领养,之后由init进程回收。

        以下面的代码为例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{int fd = fork();if (fd < 0){perror("fork");}while (1){if (fd == 0){// 子进程printf("子进程: %d,父为:%d\n", getpid(),getppid());sleep(2);}else{// 父进程printf("父进程: %d,父为:%d\n", getpid(),getppid());sleep(6);printf("父进程退出!");exit(1);}}return 0;
}

此时子进程的状态也变成了“S”, 表明此时正不被CPU调度,并且是后台进程的一部分。(前后台进程最明显的差异就是,后台进程执行时命令行解释器可以正常运作,因为命令行解释器是前台进程,两者互不干扰

6.进程属性

        在linux系统中输入ps -l命令,可以看到类似的内容:

        

其中:

        UID : 代表执行者的身份
        PID : 代表这个进程的代号
        PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
        PRI :代表这个进程可被执行的优先级,其值越小越早被执行
        NI :代表这个进程的nice值

PRI和NI:

        PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
        那NI呢?其表示进程可被执行的优先级的修正数值,PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice,这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值nice其取值范围是-20至19,一共40个级别。
        需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
        可以理解nice值是进程优先级的修正修正数据。

可以使用top命令更改已存在进程的nice值:

        输入top
        进入top后按“r”–>输入进程PID–>输入nice值

相关重要概念:

        竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
        独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
        并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
        并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1258.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

unity搭建场景学习

unity搭建场景学习 创建场景创建gameobject创建材质&#xff0c;用于给gameobject上色拖拽材质球上色上色原理设置多个材质方式设置贴图的方式 效果设置光滑度一些预览设置菜单渲染模型与碰撞模型网格渲染参数1. materials(材质)2. lighting(光照)3. reflection probes(反射探针…

【Linux】文件系统

目录 1、认识硬件--磁盘 2、文件系统 3、软链接&&硬链接 1、认识硬件--磁盘 唯一的一个机械设备&#xff0c;也是一个外设。 我们可以把磁盘看作是由无数个扇区构成的存储介质。 要把数据存到磁盘&#xff0c;第一个要解决的问题是定位一个扇区&#xff1a;哪一面&…

Linux进阶

认识root用户(超级管理员) root账号:超级管理员账户,在任何地方都有最高权限 其它账户: 是由root权限创建来的.只能在自己的家目录用更大的权限. su和exit(切换/退出) su - 用户名 : 切换到其它用. -加载环境变量 exit 登出当前用户. 可以使用ctrl d 快捷键在前面&#xff…

单臂路由实现不同VLAN之间设备通信

转载请注明出处 本实验为单臂路由配置&#xff0c;目的为让不同VLAN之间的设备能够互相通信。 1.首先&#xff0c;按照要求配置两个pc的ip地址&#xff0c;以pc0为例子&#xff1a; 2在交换机创建vlan10和vlan20 3.划分vlan&#xff0c;pc0为vlan10的设备&#xff0c;pc1为vla…

AR基础知识:SLAM同时定位和构图

在第一部分中&#xff0c;我们了解了算法如何识别相机帧中的关键点。这些是跟踪和识别环境的基础。 对于增强现实&#xff0c;设备必须知道更多信息&#xff1a;它在世界上的 3D 位置。它通过自身与多个关键点之间的空间关系来计算这一点。这个过程称为“同时定位和地图构建”…

【数据结构-邻项消除】力扣2211. 统计道路上的碰撞次数

在一条无限长的公路上有 n 辆汽车正在行驶。汽车按从左到右的顺序按从 0 到 n - 1 编号&#xff0c;每辆车都在一个 独特的 位置。 给你一个下标从 0 开始的字符串 directions &#xff0c;长度为 n 。directions[i] 可以是 ‘L’、‘R’ 或 ‘S’ 分别表示第 i 辆车是向 左 、…

[实战-11] FlinkSql 设置时区对TIMESTAMP和TIMESTAMP_LTZ的影响

table.local-time-zone table.local-time-zoneDataStream-to-Table Conversion&#xff08;拓展知识&#xff09;代码测试flinksql代码执行结果截图1. Asia/Shanghai 结果如下2. UTC结果如下 table.local-time-zone table.local-time-zone可用于设置flinksql的时区。 flink的内…

通过哪些性能指标来评估微调后的大模型实际业务效果?【大模型行业应用落地系列】

ct) 大模型应用场景探讨 ● 通过哪些性能指标来评估微调后的大模型实际业务效果&#xff1f; **【议题说明】**本议题主要探讨评估微调后大模型在实际业务场景中效果的性能指标&#xff0c;确保模型优化与业务目标一致。探讨该议题对用户企业具有多方面的价值&#xff0c;精确…

12-Docker发布微服务

12-Docker发布微服务 Docker发布微服务 搭建SpringBoot项目 新建一个SpringBoot项目 选择依赖项Spring Web和Spring Boot Actuator 在com.qi.docker_boot下创建controller目录&#xff0c;并在该目录下创建OrderController的java类 OrderControllerjava类的内容如下&#xf…

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用 目录 文章目录 【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用目录摘要研究背景问题与挑战如何解决创新点算法模型1. 知识总结模块&#xff08;Knowledge Summarization Module&…

HTML CSS

目录 1. 什么是HTML 2. 什么是CSS ? 3. 基础标签 & 样式 3.1 新浪新闻-标题实现 3.1.1 标题排版 3.1.1.1 分析 3.1.1.2 标签 3.1.1.3 实现 3.1.2 标题样式 3.1.2.1 CSS引入方式 3.1.2.2 颜色表示 3.1.2.3 标题字体颜色 3.1.2.4 CSS选择器 3.1.2.5 发布时间字…

应用在汽车控制系统安全气囊的爱普生可编程晶振SG-8018CG

在汽车安全领域&#xff0c;安全气囊是保护驾乘人员生命安全的关键防线。而作为安全气囊控制系统的关键元件 —— 爱普生可编程晶振 SG - 8018CG&#xff0c;以其卓越的性能成为汽车安全的坚实守护者。 一、高精度频率输出&#xff1a;安全气囊触发的精准之选 在汽车安全气囊控…

第112届全国糖酒会(3月成都)正式官宣!

作为食品饮料行业内备受瞩目的年度盛事&#xff0c;全国糖酒商品交易会&#xff08;简称“糖酒会”&#xff09;一直是各大厂商与经销商展现企业风采、寻觅合作伙伴及签署订单的关键舞台。2024年10月31日&#xff0c;第111届全国糖酒商品交易会&#xff08;秋糖&#xff09;在深…

【Javaee】网络原理-http协议(二)

前言 上一篇博客初步介绍了抓包工具的安装及使用&#xff0c;介绍了http请求报文与响应报文的格式。​​​​​​【Javaee】网络原理—http协议&#xff08;一&#xff09;-CSDN博客 本篇将详细介绍http的方法和http报文中请求头内部键值对的含义与作用&#xff0c;以及常见状…

Python实现摇号系统:详细指南与案例解析

目录 一、摇号系统的基本概念与原理 二、摇号系统的准备工作 三、摇号系统的详细实现步骤 1. 数据读取 2. 随机摇号 3. 结果存储 4. 结果查询 5. 主函数 四、案例解析 五、常见问题与解答 如何确保摇号过程的公平性&#xff1f; 如何处理大量用户数据&#xff1f; …

python将数据集中所有文件名升序制作txt文件(医学影像)

import os import re # 设定图像文件所在的路径 img_path ./2d/images/ #需修改路径 # 获取该路径下的所有文件名 img_list os.listdir(img_path) # 过滤出以.nii结尾的文件名 nii_list [f for f in img_list if f.endswith(.nii)] # 使用正则表达式从文件名中提…

Stable diffusion 3.5本地运行环境配置记录

1.环境配置 创建虚环境 conda create -n sd3.5 python3.10Pytorch(>2.0) conda install pytorch2.2.2 torchvision0.17.2 torchaudio2.2.2 pytorch-cuda12.1 -c pytorch -c nvidiaJupyter能使用Anaconda虚环境 conda install ipykernel python -m ipykernel install --user …

2001-2023年A股上市公司数字化转型数据(MDA报告词频统计)(三种方法)

2001-2023年A股上市公司数字化转型数据&#xff08;MD&A报告词频统计&#xff09;&#xff08;三种方法&#xff09; 1、时间&#xff1a;2001-2023年 2、来源&#xff1a;上市公司MD&A报告 3、指标&#xff1a;年份、股票代码、股票简称、行业名称、行业代码、MD&a…

【力扣专题栏】字母异词分组,如何利用强大的容器(unordered_map)解决该问题?

题解目录 1、题目描述解释2、算法原理解析3、代码编写 1、题目描述解释 2、算法原理解析 3、代码编写 class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {//创建哈希表unordered_map<string,vector<string&g…

基于python的语音识别与蓝牙通信的温控系统毕设项目

基于python的语音识别与蓝牙通信的温控系统毕设项目 大家好&#xff0c;我是俊星学长&#xff0c;一名在 Java 圈辛勤劳作的码农。今日&#xff0c;要和大家分享的是一款基于python的语音识别与蓝牙通信的温控系统毕设项目。项目源码以及部署相关事宜&#xff0c;请联系小村学…