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

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

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

目录

1、操作系统进程

1.1、进程背景

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

1.2、进程状态

2、Linux的进程状态

2.1、如何描述进程状态?

[2.2、R 和S 运行状态](#2.2、R 和S 运行状态)

[2.3、T/t 运行状态](#2.3、T/t 运行状态)

[2.4、D 运行状态](#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资源,也有可能随时要外设资源

  1. 阻塞状态:

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

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

  1. 挂起状态:

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

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

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 3

struct 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.c
	gcc -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不存在也就搜索不到这个进程,所以也无法演示。

总结

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

相关推荐
Betty’s Sweet12 分钟前
[Linux]:信号(下)
linux·信号·可重入函数·volatile·信号集
Sunsets_Red26 分钟前
Linux 系统
linux·运维·服务器·c++·学习·系统架构·系统安全
北飞的山羊30 分钟前
【计算机网络】详解UDP套接字&网络字节序&IP地址&端口号
linux·服务器·网络·后端·计算机网络·udp·信息与通信
西京刀客33 分钟前
linux的redir命令实现端口转发
linux·运维·tcp·流量转发
wit_yuan40 分钟前
BMC 虚拟i2c访问PCA9545(switch芯片)后面的设备,为什么找不到PCA9545?
linux·服务器·嵌入式硬件
繁依Fanyi1 小时前
828 华为云征文|华为 Flexus 云服务器打造 Laverna 在线笔记应用
运维·服务器·笔记·python·算法·华为·华为云
m0_375599731 小时前
Linux离线安装rmp包
linux
即兴小索奇1 小时前
linux如何查看当前的目录所在位置
linux·运维·服务器
x66ccff1 小时前
【linux】快速列出 systemctl 特定名的服务
linux·服务器·数据库
维生素C++1 小时前
【可变模板参数】
linux·服务器·c语言·前端·数据结构·c++·算法