Linux 僵尸进程产生原因及解决方法
作者:sparkdev 发布时间:2023-07-28 05:29:33
Linux 允许进程查询内核以获得其父进程的 PID,或者其任何子进程的执行状态。例如,进程可以创建一个子进程来执行特定的任务,然后调用诸如 wait() 这样的一些库函数检查子进程是否终止。如果子进程已经终止,那么,它的终止代号将告诉父进程这个任务是否已成功地完成。
为了遵循这些设计原则,不允许 Linux 内核在进程一终止后就丢弃包含在进程描述符字段中的数据。只有父进程发出了与被终止的进程相关的 wait() 类系统调用之后,才允许这样做。这就是引入僵死状态的原因:尽管从技术上来说进程已死,但必须保存它的描述符,直到父进程得到通知。
如果一个进程已经终止,但是它的父进程尚未调用 wait() 或 waitpid() 对它进行清理,这时的进程状态称为僵死状态,处于僵死状态的进程称为僵尸进程(zombie process)。任何进程在刚终止时都是僵尸进程,正常情况下,僵尸进程都立刻被父进程清理了。
僵尸进程是如何产生的
在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程。通过ps命令查看其带有defunct的标志。僵尸进程是一个早已死亡的进程,但在进程表 (processs table)中仍占了一个位置(slot)。
但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程。因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程,看看有没有哪个 进程是刚刚结束的这个进程的子进程,如果是的话,就由Init进程来接管他,成为他的父进程,从而保证每个进程都会有一个父进程。而Init进程会自动 wait其子进程,因此被Init接管的所有进程都不会变成僵尸进程。
为了观察到僵尸进程,我们自己写一个不正常的程序,父进程 fork 出子进程,子进程终止,而父进程既不终止也不调用 wait 清理子进程:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i = 100;
pid_t pid=fork();
if(pid < 0)
{
perror("fork failed.");
exit(1);
}
if(pid > 0)
{
printf("This is the parent process. My PID is %d.\n", getpid());
for(; i > 0; i--)
{
sleep(1);
}
}
else if(pid == 0)
{
printf("This is the child process. My PID is: %d. My PPID is: %d.\n", getpid(), getppid());
}
return 0;
}
把上面的代码保存到文件 zomprocdemo.c 文件中,并执行下面的命令编译:
$ gcc zomprocdemo.c -o zomprocdemo
然后运行编译出来的 zomprocdemo 程序:
$ ./zomprocdemo
此时子进程已经退出,但是父进程没有退出也没有通过 wait() 调用处理子进程。我们使用 ps 命令查看进程的状态:
上图红框中的大写字母 "Z" 说明 PID 为 112712 的进程此时处于僵死的状态。
让我们接着往下看!在结束 sleep 后父进程退出。当父进程退出后,子进程会变成孤儿进程,此时它会被一个管理进程收养。在不同的系统中,这个管理进程不太一样,早期一般是 init 进程,Ubuntu 上是 upstart,还有近来的 Systemd。但是它们都完成相同的任务,就是 wiat() 这些孤儿进程,并最终释放它们占用的系统进程表中的资源。这样,这些已经僵死的孤儿进程就彻底的被清除了。
僵尸进程的危害
在进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号 PID,退出状态 the termination status of the process,运行时间 the amount of CPU time taken by the process 等)。直到父进程通过 wait / waitpid 来取时才释放。
如果进程不调用 wait / waitpid 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。
如何处理僵尸进程
僵尸进程的产生是因为父进程没有 wait() 子进程。所以如果我们自己写程序的话一定要在父进程中通过 wait() 来避免僵尸进程的产生。
当系统中出现了僵尸进程时,我们是无法通过 kill 命令把它清除掉的。但是我们可以杀死它的父进程,让它变成孤儿进程,并进一步被系统中管理孤儿进程的进程收养并清理。
下面的 demo 中,父进程通过 wait() 等待子进程结束:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(1);
}
if (pid == 0) {
int i;
for (i = 3; i > 0; i--)
{
printf("This is the child\n");
sleep(1);
}
// exit with code 3 for test.
exit(3);
}
else
{
int stat_val;
wait(&stat_val);
if (WIFEXITED(stat_val))
{
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
}
}
return 0;
}
demo 中父进程不仅等待子进程结束,还通过 WEXITSTATUS 宏取到了子进程的 exit code。
来源:http://www.cnblogs.com/sparkdev/p/8275221.html
猜你喜欢
- PHP5安装图解本文讨论的是Windows2003下安装PHP5,请注意 下载PHP5,下载地址:http://www.php.n
- 5天前美图秀秀[点击本站下载]软件才刚刚发布过2.0周年纪念版,今天又以迅猛速度推出2.0.1小幅度升级版。虽然只是小幅度的升级,但是这次开
- “每个人都可以变强大,只要他懂得什么是坚持”这句话也不知道谁说的,在百度搜索了下,没有找到答案,也许这个就是传说中的真理!今天在站长中国看了
- 服务器群集功能最早是为 Microsoft Windows NT® Server 4.0 操作系统设计的,这一功能在 Mic
- 确切的说,第一次知道网络是在1999年的某一天。由于我生活在一个很偏僻的地方,那里很落后,所以知道1999年的某一天,一次偶然的机会得到一张
- Linux下路由配置命令1. 添加主机路由route add -host 192.168.1.11 dev eth0route add -h
- 长尾关键词这个概念现在大家都已经有所了解。在做英文网站优化时,因为受到各种因素的限制(如资源,时间等),我们不应该去追求那些高搜索但是同样高
- 北京时间10月28日消息,据国外媒体报道,Facebook昨日召开了年度Facebook 开发者大会,表示Facebook用户十分热衷于游戏
- sendStaticResource 方法是非常简单的。它首先传递父路径和子路径给File类的构造器,从而对java.io.File类进行了
- 建站程序是站长运营网站的根本,如何结合整合各个不同系统的程序、数据表、架构,提供统一的网站会员系统,一直是困扰很多站长的问题,而使用UCen
- 如何在WordPress程序中集成支付宝是实现WordPress电子商务化必须要突破的一个瓶颈。WordPress有很多的电子商务类插件,像
- 既然是我们的防范是从入侵者角度来进行考虑,那么我们就首先需要知道入侵者的入侵方式。目前较为流行web入侵方式都是通过寻找程序的漏洞先得到网站
- 1. 输出重定向:默认条件下,标准输出和错误输出都是终端,可以把标准输出和错误内容进行重定向:[~]# echo "hello\!
- DedeCMS Error Warning,这个问题我也出现过,有办法解决,但能不能行得通还是个问题,如果你是独立服务器可以使用以下两个方法
- 本文记录了VMware Workstation 12 Pro 安装linux教程,供大家参考,具体内容如下事先准备:安装VMware Wor
- 1. 环境说明节点IPredis-node-110.10.239.31redis-node-210.10.239.32redis-node-
- 看到这个标题,想必大家会不屑一顾,“需要分析IIS日志吗?我有流量统计、51yes、cnzz、51la等等一大堆,功能全面,用起来也方便”,
- 还记得《暗黑破坏神》吗?还记得那些曾经的游戏吗?随着2008年网页游戏在全国的异军突起,这些经典游戏也就逐渐成为了游戏开发厂商模仿和借鉴的对
- 今天上午闲来没事,写了一下自己几年来建站回忆录,发现鱼给加了16分!还差4分就落伍了,干脆在写一下论坛运营和管理上的一些经验! 希望今天就能
- Linux(Ubuntu) adb 无法识别的问题一般开发公司都开发员都有同时处理不同开发板,因为项目迭代需要。但是不同的开发板的USB并不