僵尸与孤儿(Linux下各进程状态的查看)

僵尸与孤儿(Linux进程的状态)

Linux下的状态

R状态 要么在运行,要么在运行队列里等待运行
S状态 浅度睡眠 – 可中断睡眠(类似于阻塞状态)
D状态 深度睡眠 – 不可中断睡眠(无论如何都kill不掉)
T状态(暂停) 程序暂停,从前台转向后台
t状态(追踪) 用gdb调试的时候,停在断点处
Z状态(僵尸) 看正文
X状态(孤儿) 看正文

僵尸进程

僵尸进程是什么

僵尸与孤儿(Linux下各进程状态的查看)_第1张图片

左图将死未死的僵尸,并不是僵尸状态
右图的死亡后,浏览器记录还没有删掉(生前的记录还有保存),是僵尸状态

僵尸进程:

  1. 子进程与父进程运行时,子进程先退出了(此时子进程的声明周期已经终止,子进程的状态需要维持,他们被保存在了task_struct结构体中)
  2. 如果此时父进程不接收子进程的返回状态,那么子进程就会维持僵尸状态,等待父进程的接收(帮助自己删除浏览器记录)
  3. 等到父进程接收后,子进程就会解除僵尸状态,然后就真真正正死亡了

Linux下的Z状态

在这里插入图片描述

完整代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<stdlib.h>
  5 
  6 int main()
  7 {
  8    size_t pid=fork();
  9    if(pid==0)
 10    {
 11        int n=5;
 12        while(n--)//5秒后子进程退出,父进程还在跑
 13        {
 14            printf("i am child poccess,pid:%d,ppid:%d\n",getpid(),getppid());
 15            sleep(1);
 16        }
 17    }
 18   else
 19   {
 20       
 21       while(1)//父进程死循环,不退出,也不接收子进程的返回信息                                                 
 22       {
 23           printf("i am father poccess,pid:%d,ppid:%d\n",getpid(),getppid());
 24           sleep(1);
 25           //wait();
 26           //printf("wait complet\n");
 27       }
 28   }
 29     return 0;
 30 }

上述代码结果:

父子进程开始时一起运行,5秒之后,子进程退出,父进程还在运行,此时父进程没有接收子进程的返回信息。子进程进入僵尸状态

僵尸进程的危害

一个程序的进程结束后,状态信息还没有被接收,此时进入僵尸状态。而这个僵尸状态会一直维持到该进程的状态信息被接收

这就会导致

  1. 占用空间,内存泄露
  2. 由于操作系统提供给用户的进程数量是有限的,大量的僵尸进程可能会导致新的进程无法运行

如何避免产生大量的僵尸进程

先给出一个概念:任何进程的结束状态都是僵尸状态

参照C语言:任何函数结束的时候都有一个返回值(或者运行中途出错了,要保留出错信息告诉调用自己的函数),此时就可以理解为他们进入了僵尸状态(程序已经运行完了,等待有人来接收我的返回值)。所以有时候你在Linux上看不到一些程序运行完后的僵尸状态,是因为操作系统读取的太快了。

  • 建议方法 – 进程等待

调用 **wait() , waitpid()**函数

pid_t wait(int *status);
//等待任意一个子进程,成功返回子进程pid,失败返回<0
pid_t waitpid(pid_t pid, int *status, int options);
//返回值同上,参数pid==-1时可以回收任意子进程,>0时指定回收指定pid的子进程;
//status用来接收退出信息(退出码和信号);
//options为0是阻塞等待

调用这个函数来回收子进程的资源和获取子进程的退出信息,然后子进程就会退出僵尸状态

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<sys/wait.h>
  5 
  6 int main()
  7 {
  8    size_t pid=fork();
  9    if(pid==0)
 10    {
 11        int n=5;
 12        while(n--)
 13        {
 14            printf("i am child poccess,pid:%d,ppid:%d\n",getpid(),getppid());
 15            sleep(1);
 16        }
 17    }
 18   else
 19   {
 20       
 21       while(1)
 22       {
 23           printf("i am father poccess,pid:%d,ppid:%d\n",getpid(),getppid());
 24           sleep(1);
 25           pid_t rpid=wait(NULL);//调用wait,来等待子进程,此时父进程不会再往后运行,直到子进程返回
 26           if(rpid>0) printf("wait complet\n");
 27       }
 28   }
 29     return 0;
 30 }

运行结果:

僵尸与孤儿(Linux下各进程状态的查看)_第2张图片

子进程退出的一瞬间就被父进程接收了,所以本来的两个进程变成了一个进程


孤儿进程

孤儿进程是什么

孤儿进程:

  1. 当其失去了父进程,而子进程还在跑,那么此时子进程就变成了孤儿进程
  2. Linux下的孤儿进程会被init进程(pid=0)回收
  3. 变成孤儿的进程会由前台进程变成后台进程

Linux下的X状态

僵尸与孤儿(Linux下各进程状态的查看)_第3张图片

完整代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 
  6 int main()
  7 {
  8    size_t pid=fork();
  9    if(pid==0)
 10    {
 11        while(1)//子进程一直运行,不退出
 12        {
 13            printf("i am child process,pid:%d,ppid:%d\n",getpid(),getppid());
 14            sleep(1);
 15        }
 16    }
 17   else
 18   {
 19       int n=10;
 20       while(n--)//父进程运行10秒后退出
 21       {
 22           printf("i am father process,pid:%d,ppid:%d\n",getpid(),getppid());
 23           sleep(1);
 24       }                                                                             
 25       printf("father process out\n\n");
 26   }
 27     return 0;
 28 }

上图中为何显示不出X?详见如下

Linux中对孤儿进程的处理

由上述代码可以看出,子进程的ppid在其父进程被干掉后立马转变成为1。

这是因为子进程变成孤儿的瞬间,就被init进程接收了,并且变成后台进程,所以S+变成S(此时ctrl+c杀不死,只能用kill来杀掉)

孤儿进程的危害

由于init进程帮我们接手了孤儿进程,所以孤儿进程就等于换了个父进程,所以并没有什么危害


其余的几种状态的查看

T状态(暂停)

可以用 kill -19 pid 命令来暂停进程

僵尸与孤儿(Linux下各进程状态的查看)_第4张图片


t状态(追踪)

这种状态常见于gdb调试,可以用gdb调试一个代码,运行到断点处就会显示t状态

在这里插入图片描述


S状态

这种是最常见的状态,分为 S+(前台运行)和 S(后台运行)

但是为什么我的程序分明正在运行,他却显示的是S状态,如图:

僵尸与孤儿(Linux下各进程状态的查看)_第5张图片

这是因为我的函数要访问硬件设备(要向屏幕打印输出),而访问硬件设备的速度是很慢的,这个时候程序在等待向硬件设备写入,所以是S+状态。


R状态

注意:R状态并和不意味着程序正在运行,他也可能正处于运行队列里,等待被运行

如何查看R状态呢?只需要对上图进行一点修改

僵尸与孤儿(Linux下各进程状态的查看)_第6张图片

这样就不会访问硬件设备,无需等待,就会显示R+状态


D状态

这种状态十分罕见,如果你碰到了,那么恭喜你,你的电脑也差不多挂掉了

个时候程序在等待硬件设备写入,所以是S+状态。

你可能感兴趣的:(Linux,linux,运维,服务器)