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

总结

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

相关推荐
道路与代码之旅24 分钟前
Delphi - IndyHttpServer接收上传文件
运维·服务器
lybugproducer1 小时前
深入 Linux 文件系统:从数据存储到万物皆文件
linux
烦躁的大鼻嘎1 小时前
【Linux】深入Linux多线程架构与高性能编程
linux·运维·服务器·开发语言·c++·ubuntu
羚羊角uou1 小时前
【Linux】system V共享内存
linux·运维·服务器
林克爱塞尔达1 小时前
Linux入门(二)
linux·运维·chrome
破烂儿1 小时前
Ubuntu Server 安装图形界面和通过Window远程桌面连接服务器(Xrdp)
linux·服务器·ubuntu
Hello.Reader1 小时前
Kafka 运维实战基本操作含命令与最佳实践
运维·kafka·linq
存储服务专家StorageExpert2 小时前
手搓一个 DELL EMC Unity存储系统健康检查清单
linux·运维·服务器·存储维护·emc存储
笑口常开xpr2 小时前
Linux 库开发入门:静态库与动态库的 2 种构建方式 + 5 个编译差异 + 3 个加载技巧,新手速看
linux·c语言·动态库·静态库
小虾米vivian2 小时前
达梦:将sql通过shell脚本的方式放在后台执行
服务器·数据库·sql