【Linux系统】进程状态:一个进程的轮回史

Linux系列


文章目录


前言

在前面几篇文章中,我们将进程的基本概念以及一些关于进程的简单系统调用接口给大家详细介绍了,在本篇文章中我们会涉及到,进程的状态以及优先级的概念,帮助大家进一步的理解操作系统和进程之间的羁绊。

一、进程状态概念

作为一个多任务的操作系统,Linux必须在多个进程之间,进行合理的调度和管理,为了方便操作系统对进程的管理,每个进程都有属于自己的进程标识符,对应的状态信息也在其中,这个状态信息标识着当前进程是处于运行、休眠、僵尸等状态。不同的状态信息能够帮助操作系统了解每个进程当前的执行状态,以便做出合理的资源调度和管理决策。

二、进程状态

1、R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
2、S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
3、D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的
进程通常会等待IO的结束。
4、T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
5、X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
6、Z(zombie)-僵尸进程:这是一个比较特殊的状态,下面我们会详细介绍。

2.1、R运行状态

当一个进程除了,CPU以外的资源都准备就绪时,我们就称为该进程处于运行状态(这个状态是指CPU正在执行的和处于就绪状态的),在我们的操作系统中,会同时存在多个,资源准备就绪的进程,但是CPU的资源是有限的,所以处于运行状态的进程,并不能立刻被CPU所执行,对于这些处于运行状态的进程,操作系统将他们,链接在CPU运行队列中(一个CPU绑定一个运行队列),等待操作系统分配CPU资源。

那么当一个进程,获取到CPU资源开始执行时,是不是要等这个程序执行完毕才可以执行下一个?当然不是,如果一个死循环的程序一直结束不了,难道其他的程序就不运行了吗,所以为了更好分配CPU,每一个进程都会有一个时间片 的概念,比如这个时间片为;10ms,当一个进程被执行了10ms时,这个进程就会被换下来,重新排队等待执行,这样保证了在一段时间内所有程序都会被执行,我们称之为**并发执行!!**而大量的把进程从CPU上,放上去,拿下来的动作我们称之为进程切换!!

下面给大家看个具体处在运行状态的进程:

c 复制代码
  1 #include<stdio.h>
  2 
  3 int main()
  4 {
  5   while(1)
  6   { }                                                                                                                             
  7 
  8   return 0;
  9 }


这里的+表示前台运行,指令的意思我以经在前几篇文章讲过很多次了,这里就不介绍了

2.2、S睡眠状态

睡眠状态是进程暂停执行,等待特定事件发生的状态,一般是等待外部设备资源,或调用系统接口而发生的。

比如一个正在运行的程序,需要我们输入一些信息(相当于scanf、cin等从外部设备获取信息资源),但我们也一直不输入,而CPU一定不会持续等待,它会将这个处于运行队列的进程,排入外部设备的结构体对象的等待队列中,继续等待我们的输入,此时的进程不占用CPU资源。我们称这种进程处于睡眠状态:

c 复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   while(1)
  6   {
  7     printf("我是一个进程\n");                             
  8   }
  9 
 10   return 0;
 11 }                              

我们执行程序后,一直在运行为什么会,呈现出的S状态?这是因为此时我们运行环境是远程登陆的服务器,而它需要将结果从运服务器打印到我们的显示器上,所以需要等待网络资源或显示器资源,对外表现为睡眠状态,对于这睡眠状态我们称之为浅度睡眠(可中断睡眠)。

这里再介绍一个挂起状态,大家了解即可:

当操作系统内部的内存资源严重不足时,操作系统就开始对那些一直处在等待队列的进程开始下手了,将他们的代码和数据(PCB结构体对象依然处于对应设备的等待队列)从内存拿出去保存在外存的特定区域-------交换空间,接着将该进程的状态标记为挂起状态,空出来的空间继续用于新的进程执行,当对应的等待设备就绪时,就会恢复该进程的运行,即:将他从等待队列,调度至运行队列。

2.2、D磁盘休眠状态

在Linux操作系统中,D状态(不可中断睡眠状态),于S状态不同,进程处于D状态时,不能响应信号(这个到后面会介绍)。比较常见的是进程等待硬件资源,如:一个进程向磁盘写入1GB数据,因为磁盘写入速度过慢,可能会导致进程长时间等待,此时进程需要等待获取执行反馈(是否写入成功),就会进入深度睡眠状态,直至事件结束,才会被唤醒。

状态的特点:

  • 不可中断:与S状态(可中断睡眠状态)不同,D状态下的进程不能被信号中断,无法通过外部操作(如发送SIGKILL)来强制终止。
  • 通常是硬件等待:进程通常会在等待底层硬件设备(如磁盘、网络、文件系统等)响应时进入D状态。例如,进程可能正在等待磁盘设备返回数据,或者在等待硬件设备准备好进行某个操作。
  • 阻塞I/O操作:进程在执行一些可能导致长时间等待的I/O操作时,可能会进入D状态,直到I/O操作完成。例如,读取磁盘上的大文件,或等待网络硬件返回数据。

2.3、Z状态

我们通常称为僵尸进程:

  • 子进程执行完(已死亡),但是父进程尚未读取父进程的退出状态。
  • 进程占用的大部分系统资源已经被回收,但是进程描述符等一些信息还保留着。

产生原因:

  • 父进程没有正确处理子进程的终止状态
  • 父进程未忽略SIGCHLD信号

特点:

  • 僵尸进程不消耗cpu或内存,但会占用进程表项(PID)
  • 若父进程长期未回收子进程,可能会导致进程表耗尽无法创建新进程。
c 复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   pid_t id=fork();
  6   if(id==0)
  7   {
  8     int i=0;                                                                                                                      
  9     for(;i<3;i++)                                                
 10     {                                                            
 11       printf("子进程PID是->%d\n",getpid());                      
 12     }                                                            
 13   }                                                              
 14   else{                                                          
 15     while(1)                                                     
 16     {                                                            
 17       printf("父进程PID是->%d\n",getpid());                      
 18     }                                                            
 19   }                                                              
 20   return 0;                                                      
 21 }

上代码,我们使用fork()函数分流后,子进程答应三次后结束,并且父进程并没有获取子进程的结束信息,父进程一直执行,此时子进程等待父进程获取信息,变为僵尸进程,处于Z状态。
孤儿进程:

孤儿进程是父进程,在子进程终止之前终止,此时子进程会被init进程(PID=1)领养,成为其新的父进程。
产生原因:

  • 父进程主动终止(如:被杀手、异常退出)
  • 父进程未等子进程结束便提前退出

特点:

  • 孤儿进程由init进程接管,并回收,不会再成僵尸进程。
  • 孤儿进程可能会在后台继续运行,但不再依赖于原父进程。

总结

学习这块可以帮助我们更深入的理解,进程的概念,但是需要注意的是,对于理解进程状态,这些是远远不够的,需要结合信号相关的知识,深入理解。

相关推荐
奔波霸的伶俐虫1 小时前
liunx磁盘挂载和jar启动命令
linux·运维·服务器
wwwlyj1233211 小时前
slab分配器(3):slab内存申请和释放
linux
JiMoKuangXiangQu1 小时前
Linux 网络:skb 数据管理
linux·网络·skb
做程序员的第一天1 小时前
ubuntu下在pycharm中配置已有的虚拟环境
linux·ubuntu·pycharm
yqcoder2 小时前
vscode 好用插件
ide·vscode·编辑器
唐青枫2 小时前
Linux fgrep 命令使用详解
linux
亭墨2 小时前
linux0.11内核源码修仙传第六章——中断初始化
linux·c语言·驱动开发·学习·面试
Ljw...2 小时前
序列化和反序列化(Linux)
linux·开发语言·网络·c++·tcp/ip·序列化反序列化
aiprtem3 小时前
LVGL组件设计之模拟桌面
linux·c语言·网络·物联网
一直在学习的小白~4 小时前
Nginx 服务器,Apache 服务器,IIS 服务器的区别
服务器·nginx·apache