【Linux系统编程】第十八弹---进程状态(上)

2024-05-14 14:12

本文主要是介绍【Linux系统编程】第十八弹---进程状态(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  ✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、操作系统进程

1.1、进程背景

1.2、进程如何在CPU上运行的?

1.2、进程状态

2、Linux的进程状态

2.1、如何描述进程状态?

2.2、R 和S 运行状态

2.3、T/t 运行状态

2.4、D 运行状态

2.5、僵尸状态(Z)

2.6、死亡状态(X)

总结


1、操作系统进程

1.1、进程背景

         由于Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态。

        进程状态:一个程序被加载到内存变成进程之后,操作系统要对该进程进行管理,即为其创建对应的PCB对象,而进程状态,本质上就是PCB内部的一个整形变量,不同的整形值就对应不同的进程状态。

        常见的进程状态:运行、挂起、阻塞、新建、就绪、等待、挂机、死亡。进程的不同状态本质都是用来满足不同的运行场景的。

1.2、进程如何在CPU上运行的?

CPU在内核上维护了一个运行队列,进行对进程的管理。让进程入队列,本质就是将该进程的task_struct 结构体对象放入运行队列之中。一个CPU就一个运行队列。

1.2、进程状态

1. 运行状态:
进程PCB在运行队列里就是运行状态,不是说这个进程正在运行,才是运行状态。

状态是进程内部的属性,所有的属性在PCB里。

进程不只是占用CPU资源,也有可能随时要外设资源

2. 阻塞状态:
进程不在运行队列之中,进程不能直接被调度,而是在等待外设资源的状态,进程的PCB就被放在硬件的等待队列中。本质是对tack_struct对象放到不同的队列中!

综上,所谓的进程不同的状态,本质是进程在不同的队列之中,等待某种资源

3. 挂起状态:
如果系统中存在许多进程,进程短期内不会被调度,代码和数据在短期内不会被执行,此时如果内存空间不足,操作系统就可以把代码和数据暂时保存到磁盘上,节省一部分空间,该进程暂时被挂起了,这就是挂起状态。

对于阻塞状态和挂起状态,阻塞不一定挂起,挂起一定是阻塞。

2、Linux的进程状态

下面的状态在kernel源代码里定义:

 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 */
};

2.1、如何描述进程状态?

进程状态实质是结构体task_struct内部的一个属性。通过宏定义的方式进行描述以及更改进程状态。

例如:

#define RUN 1
#define SLEEP 2  // 用数字表示进程意思
#define STOP 3struct task_struct
{// 内部的一个属性int status;
}struct task_struct process1; //创建进程
process1.status=RUN;//设置进程状态

补充:vim替换

:%s/name1/name2/   #  name2替换掉name1   在命令模式中

2.2、R 和S 运行状态

R (running): 进程运行的状态 。

S (sleeping): 休眠状态,进程在等待 “资源” 就绪,可中断睡眠。

通过编写C语言代码就行验证,此处依旧使用makefile工具。

makefile 代码:

testStatus:testStatus.cgcc -o $@ $^ 
.PHONY:clean
clean:rm -f testStatus

testStatus.c 代码,测试代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{while (1){printf("I am a process,pid: %d\n", getpid());}return 0;
}

输入命令./testStatus 运行可执行程序,并使用ps 查看进程信息

查看进程信息

 while :; do ps axj | head -1 && ps axj | grep testStatus | grep -v grep; sleep 1;done    

通过运行结果我们可以看到,我们的进程一直在运行,但是进程状态是S+状态,按照我们正常的理解在运行的程序不就是R(运行)状态?那为什么这里确实S+状态呢???

因为:printf的本质是往显示器上打印;而程序的运行是在千里之外的云服务器上跑,最终打印出来的信息显示到我们本地的显示器上;根据冯诺依曼体系结构,显示器是一个外设,所以CPU在跑当前的程序时,把数据写入到我们当前的内存当中,打印数据的顺序:先写入到内存里,再刷新到外设里。可是我们无法保证每次打印的时候,显示器的状态都是就绪的,因为程序是CPU跑的,CPU的运算速度要比显示器本身的速度要快的多,所以进程在被调度的时候,要访问显示器的资源,因为资源要一直在显示器上打,所以大部分时间,相比较CPU来讲,大部分时间,我们对应的进程都在等待我们的设备资源是否就绪。就比如:代码执行到 printf 的时候,CPU是几纳秒,而数据刷新到显示器的时间是几毫秒,其余大部分时间都在等待中,而这等待的时间,就是(S)休眠状态。

补充:

./testStatus &  # 在执行可执行程序后面加&符号,为在后台运行,跑起来后面不带+号。+号表示在前台还是后台运行,以什么为参考系后面说。后台运行后面有数字(pid),且ctrl +c 不能中断进程,需用kill -9 pid杀掉进程。

2.3、T/t 运行状态

补充命令 kill :

语法:

kill  [-s <信号名称或者编号>][程序]   或   kill  [-l <信息编号>]

功能:

给指定命令发信号。

常见选项:

-l <信息编号> : 若不加<信息编号>选项,则 -l 参数会列出全部的信息名称。

总共有64个信息编号。前面我们使用了-9杀死进程,下面我们会用到-18(SIGCOUT)进程继续以及-19(SIGSTOP)暂停进程

T(stopped)   :让进程暂停,等待被进一步唤醒。暂停后自动会变成后台。

 下图可以看到细节:从S+状态(前台运行)变成T,再由T状态变成了S状态(后台运行)

 

t (tracing stop) : 当前的进程因为被追踪而暂停了。

我们有没有让进程暂停过???

答案是当然有,在我们调试代码的时候,断点就是让进程暂停。

2.4、D 运行状态

讲解D状态之前我们先讲解一个故事。

★ 一个进程A要将1个G的数据存储到硬盘,根据冯诺依曼体系结构可以知道,本质是把数据从内存交给外设,由于速度差,进程需要等待硬盘资源把数据写入完毕,此时进程处于S状态,又因为操作系统管理进程,当系统整个的内存资源严重不足时,Linux操作系统有权利杀掉进程来释放空间,然后操作系统把A进程杀掉,但是此时B进程要给硬盘写入数据,硬盘需要去照顾B进程,导致A进程写入数据失败了,1GB的数据丢失了,如果这个数据是银行的转账记录,那么可能造成很大的影响。

 ★ 为了避免这种情况,如果进程在等待硬盘资源时,进程需要将自己的状态设为D状态:不可被杀深度睡眠,不可中断睡眠。

 ★ 我们一般不会遇到这种情况,从事系统管理、运维、存储等工作可能会遇到。

D (disk sleep): Linux系统比较特有的一种进程状态,不可被杀,深度睡眠,不可中断睡眠。

杀死D状态的方法:

1、进程自己醒来。

2、重启,重启不行则断电。

2.5、僵尸状态(Z)

僵尸状态也叫僵死状态,它是在进程在死亡状态之前的状态。当一个进程运行完毕、出现问题或者被杀掉以后,它所占用的内存资源和退出状态没有被它的父进程回收,此时这个进程的状态就称为僵尸状态

2.6、死亡状态(X)

当一个进程执行结束或者是被操作系统杀掉,它的PCB被操作系统删除,并且对应加载到磁盘上的二进制代码也被删除,此时这个进程就处于死亡状态了。

当一个进程占有内存的所有资源被回收以后,这个进程就处于死亡状态。进程的死亡状态是看不到的,因为只有在回收完成的那一刻才会出现,PCB不存在也就搜索不到这个进程,所以也无法演示。

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

这篇关于【Linux系统编程】第十八弹---进程状态(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/988959

相关文章

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l