当前位置:首页 » 《休闲阅读》 » 正文

探索Linux下进程状态 | 僵尸进程 | 孤儿进程

12 人参与  2024年04月04日 14:40  分类 : 《休闲阅读》  评论

点击全文阅读


文章目录

Linux下进程状态R、S状态T/t状态D状态 僵尸进程孤儿进程
在这里插入图片描述

Linux下进程状态

任何进程在运行时都会有自己的状态

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

/** 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):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

R、S状态


下来看下面这串代码的运行状态:

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

重复查看代码运行状态:while :; do ps ajx | head -1 && ps ajx | grep testStatus | grep -v grep; sleep 1; done

在这里插入图片描述
在这里插入图片描述
当程序运行时,显示的是S状态,S状态是休眠状态

将代码中while循环里面打印的内容去掉,再来查看状态:

#include<stdio.h>    #include<sys/types.h>    #include<unistd.h>        int main()    {      while(1)      {                            }      return 0;    } 

在这里插入图片描述

在这里插入图片描述
此时代码中只有while死循环,此时是R状态,表示进程正在运行,这个很好理解。

这两个程序刚刚都是运行,为什么第一个代码是S状态(休眠状态)呢?

休眠状态本质上是程序什么都没有做,这叫做休眠状态,但是刚刚一直在打印内容,说是什么都没做,好像有点不对。原因在于:CPU的执行速度很快,比显示器设备显示快的很多,该进程大部分时间都是在显示器的等待队列里等待显示设备就绪,因此最终查看的状态是休眠状态(S状态)。当我们去掉printf后,进程始终都在运行状态里,所以最终查出来的状态是运行状态(R状态)。

休眠状态本质就是进程在等待“资源”就绪

当程序正在运行时,如果ctrl+c,进程被终止,称为可中断睡眠。

S+:意思是进程在前台运行,S是进程在后台运行

在这里插入图片描述
当进程处于后台运行时,无法通过ctrl+c终止程序,需要使用指令:kill -9


T/t状态

T状态和t状态我们可以认为这两个状态是一样的,对于一个进程,可以使用指令kill -19 进程的pid来让进程处于停止状态

T/t状态:让进程处于暂停状态。

在这里插入图片描述
让进程结束暂停状态,继续运行:kill -18 进程pid

当我们使用gdb调试打断点时,遇到断点处就暂停,此时是t状态,这种场景是被追踪暂停。

D状态

D状态:Linux系统比较特有的一种进程状态。在Linux系统层面称作浅度睡眠,S称为深度睡眠。

disk是磁盘的意思,好像是说针对于磁盘的一种状态

有这样一个场景,操作系统中有一个进程,需要将1GB的数据写入磁盘中。首先根据冯诺依曼体系,这个进程要把数据存入磁盘中,实际上是将数据存入外设。进程把数据交给磁盘,磁盘在存储时需要时间,当前进程需要等待,也就是S状态。Linux操作系统负责的是进程管理,文件系统等,整个操作系统管理系统软硬件资源,当系统中整个资源内存不足时,Linux操作系统有权杀掉进程来释放空间。进程在等待磁盘反馈,操作系统忙前忙后,忙的不可开交,看到这个进程:“你干嘛呢?我快忙死了,我快要崩溃了,一旦我崩溃你可知后果??”,操作系统生气了,一气之下把这个进程干掉了,释放了这个进程的内存资源。操作系统继续干自己的事情了,磁盘就说:“不好意思,写入失败,你(进程)跟用户说一下。哎?进程呢?你咋不见了”磁盘在想咋办呢?此时又有新的进程来了,磁盘心想:“不管了,反正之前的进程给的数据写入失败了,先写入新进程的数据吧”。这就造成一批数据丢失问题,如果这个数据很重要,那麻烦大了。用户要对操作系统、磁盘、进程批评审查了。这么一看,操作系统、进程、磁盘好像都没有错,是制度的问题,当进程在向磁盘中写入数据时谁都不能将该进程干掉。于是D状态就诞生了。

当一个进程处于D状态时,它不会响应任何请求,任何人和操作系统都无法干掉这个进程。

结束D状态方式:

等待某个条件,比如数据读入完毕直接断电

僵尸进程

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

代码:

#include<stdio.h>    #include<sys/types.h>    #include<unistd.h>        int main()    {      pid_t id=fork();      if(id==0)      {        int cnt=5;        while(cnt)        {          printf("I am child process,pid:%d,ppid:%d\n",getpid(),getppid());          sleep(1);          cnt--;        }        _exit(0);      }      else      {        while(1)        {          printf("I am father process,pid:%d,ppid:%d\n",getpid(),getppid());          sleep(1);        }                                                                            }      return 0;    }  

在这里插入图片描述

已经运行完毕,但是需要维持自己的退出信息,在自己的进程task_struct会记录自己的退出信息,未来让父进程来进行读取。如果没有父进程读取,僵尸进程会一直存在。

上述代码中,子进程执行完五次后,就处于Z状态并且后面跟了一个<defunct>,该单词有不存在的意思,只不过还等待父进程来回收它的资源。处于Z状态的进程的相关资源不能被释放。只有当父进程把子进程的相关资源回收后,子进程才能变成死亡状态(X状态)。一般的,我们讲这种处于Z状态的进程叫做僵尸进程,如果父进程一直不回收,将长时间占用内存资源,造成内存泄漏。

僵尸进程危害:

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说, Z状态一直不退出, PCB一直都要维护?是的!那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!内存泄漏?是的!

孤儿进程

僵尸进程代码中是子进程先退出,父进程一直运行

在孤儿进程中,让父进程先退出,子进程一直运行

代码:

#include<stdio.h>    #include<sys/types.h>    #include<unistd.h>  int main()                                                                          {                                                                                     pid_t id=fork();                                                                    if(id==0)                                                                           {                                                                                     int cnt=500;                                                                        while(cnt)                                                                          {                                                                                     printf("I am child process,pid:%d,ppid:%d\n",getpid(),getppid());                   sleep(1);                                                                           cnt--;                                                                            }                                                                                   _exit(0);                                                                         }                                                                                   else                                                                                {                                                                                     int cnt=5;                                                                          while(cnt--)        {                                                                                                       printf("I am father process,pid:%d,ppid:%d\n",getpid(),getppid());      sleep(1);            }                    }              return 0;}

在这里插入图片描述
父进程结束后,只剩下子进程,为什么父进程不会处于僵尸进程?父进程也是bash的子进程,父进程结束后,它的父进程bash会将它回收掉,并且过程很快,所以父进程不会处于僵尸状态。

当父进程结束后,它的子进程的父进程变成1号进程,即操作系统

在这里插入图片描述
将父进程是1号进程的进程叫做孤儿进程。 孤儿进程被1号i进程领养,当然要有进程回收喽。

在这里插入图片描述


点击全文阅读


本文链接:http://zhangshiyu.com/post/90511.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1