写一个后台运行程序,出现僵尸进程

yanjinbin01 2008-07-17 11:08:52

void deamon_process()
{
int pid,i;
if(pid=fork())
{
exit(0);
}else if(pid < 0)
{
_exit(1);
}
setsid();
if(pid=fork())
{
exit(0);
}else if(pid < 0)
{
_exit(1);
}
for( i=0;i< NOFILE;++i)
{
close(i);
}

chdir("/tmp");
umask(0);
signal(SIGCHLD,SIG_IGN);
}
这是一个把一个当前用户进程,变成后台运行进程的函数.
但是使用该函数后,会产生一个僵尸进程.
比如我用该函数编译出程序 test
运行 test
ps查看进程发现:
706 z [test]
707 s test
发现PID=706 test 的进程编程僵尸进程了,而PID=707则是在运行的.

为什么706会变成一个僵尸进程,我显示调用exit(0)来退出父进程的啊,他因该回收掉啊.
...全文
425 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
wlabing 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wangzongqing 的回复:]
setsid(); 有没有失败?
第一个fork出来的子进程执行setsid(); ,这时候有可能父进程还没有执行exit,那么setsid(); 执行就会失败,如果失败了那后面的操作就达不到daemon的效果,可以试着在前面加sleep看看

z的那个进程的父进程是不是init,如果是init,则表示不是上述的情况,那么就是init进程的问题,init进程需要定期的对子进程进行回收,那么肯定就是init的回收有问题了
[/Quote]
同意楼上的说法.
看看僵尸进程的父进程是不是1号进程,如果不是,你把僵尸进程的父进程kill掉,然后再看看它的父进程是不是1号进程,由此判断是不是init进程的问题.
wangzongqing 2008-07-18
  • 打赏
  • 举报
回复
setsid(); 有没有失败?
第一个fork出来的子进程执行setsid(); ,这时候有可能父进程还没有执行exit,那么setsid(); 执行就会失败,如果失败了那后面的操作就达不到daemon的效果,可以试着在前面加sleep看看

z的那个进程的父进程是不是init,如果是init,则表示不是上述的情况,那么就是init进程的问题,init进程需要定期的对子进程进行回收,那么肯定就是init的回收有问题了
yanjinbin01 2008-07-18
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 wlabing 的回复:]
我运行了上面的代码,没有出现你说的这种现象啊(只有一个进程,它的父进程ID为1,没有出现僵尸进程),不会是你的操作系统有问题吧.
出现僵尸进程的情况是:子进程比父进程先退出,而父进程却没做善后处理才导致的.
而现在是父进程比子进程先退出,子进程成了孤儿进程,被init进程领养,是不会出现僵尸进程的.
when a child terminates,maybe in his parent called wait func who wana
to get the exit status. so kerne…
[/Quote]
听你这么说我也试着在不同的操作平台运行了该段代码,
发现只是在arm-linux我的实际使用环境才会出现这种情况,而且还发现在arm-linux 进程里面还有别的僵尸进程也没有回收.
但是这个问题是因为我内核裁减出问题吗,我的内核是2.6.9.5 .
大家帮忙一起想想 是那出问题了。
谢谢.
wlabing 2008-07-18
  • 打赏
  • 举报
回复
我运行了上面的代码,没有出现你说的这种现象啊(只有一个进程,它的父进程ID为1,没有出现僵尸进程),不会是你的操作系统有问题吧.
出现僵尸进程的情况是:子进程比父进程先退出,而父进程却没做善后处理才导致的.
而现在是父进程比子进程先退出,子进程成了孤儿进程,被init进程领养,是不会出现僵尸进程的.
when a child terminates,maybe in his parent called wait func who wana
to get the exit status. so kernel will keep the child process stauts
for a moment,thus the child process becomes zombies. If u let the parent
process to terminate first, Kernel knows that it's no need to keep the
child's process status so when child call exit it disappear immedaitely.
during the period from the child process has no parent(parent exit first)
to child exit then child process is a orphan process and will be adopted by
init process (id=1). IT IS NOT A ZOMBIE OF CAUSE.
yanjinbin01 2008-07-18
  • 打赏
  • 举报
回复
谢谢各位.
终于发现是怎么回事了.
原来我有个前台运行进程放在rcS脚本中,阻塞了init进程.
所以init不会去回收僵尸进程.
linuxguy 2008-07-17
  • 打赏
  • 举报
回复
在这个函数前要做好SIGCHLD信号量的妥善安置工作!要不然ZOMBIE进程肯定有!
wlabing 2008-07-17
  • 打赏
  • 举报
回复
signal(SIGCHLD,SIG_IGN);
你用了这句,子进程退出后,你没做善后处理,所以就出现僵尸进程.
你可以写这样一个函数用来处理SIGCHLD信号.
void sig(int signo)
{
waitpid(-1,NULL,WNOHANG);
return;
}

void deamon_process()
{
int pid,i;
signal(SIGCHLD,sig);
if(pid=fork())
{
exit(0);
}else if(pid < 0)
{
_exit(1);
}
setsid();
if(pid=fork())
{
exit(0);
}else if(pid < 0)
{
_exit(1);
}
for( i=0;i < NOFILE;++i)
{
close(i);
}

chdir("/tmp");
umask(0);
//signal(SIGCHLD,SIG_IGN);
}
yanjinbin01 2008-07-17
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wlabing 的回复:]
引用楼主 yanjinbin01 的帖子:

这是一个把一个当前用户进程,变成后台运行进程的函数.
但是使用该函数后,会产生一个僵尸进程.
比如我用该函数编译出程序 test
运行 test
ps查看进程发现:
706 z [test]
707 s test
发现PID=706 test 的进程编程僵尸进程了,而PID=707则是在运行的.

为什么706会变成一个僵尸进程,我显示调用exit(0)来退出父进程的啊,他因该回收掉啊.


不对啊,父进程已经终止了,怎么还会…
[/Quote]

这正是我的疑问啊.
为什么啊,老天啊.
wlabing 2008-07-17
  • 打赏
  • 举报
回复
父进程比子进程先退出,这时子进程成了孤儿进程,init进程收养了它,init进程就成了该子进程的父进程了,它是不会成为僵尸进程的.
wlabing 2008-07-17
  • 打赏
  • 举报
回复
[Quote=引用楼主 yanjinbin01 的帖子:]

这是一个把一个当前用户进程,变成后台运行进程的函数.
但是使用该函数后,会产生一个僵尸进程.
比如我用该函数编译出程序 test
运行 test
ps查看进程发现:
706 z [test]
707 s test
发现PID=706 test 的进程编程僵尸进程了,而PID=707则是在运行的.

为什么706会变成一个僵尸进程,我显示调用exit(0)来退出父进程的啊,他因该回收掉啊.
[/Quote]

不对啊,父进程已经终止了,怎么还会有两个进程.
PID=707的正在运行,而PID=706的却成为了僵尸进程,父进程怎么成了僵尸进程,子进程却安然无恙.
yanjinbin01 2008-07-17
  • 打赏
  • 举报
回复
signal(SIGHUP,SIG_IGN); 报告用户已经被终端从系统中断开.
加这个也没用.


一 铭 2008-07-17
  • 打赏
  • 举报
回复


对了:
这句应该不需要把
signal(SIGCHLD,SIG_IGN);

这里面的儿子都被init收养了,呵呵

可以加signal(SIGHUP,SIG_IGN);
在setsid();
后面;

一 铭 2008-07-17
  • 打赏
  • 举报
回复

把test 贴出来看看把!
wangzongqing 2008-07-17
  • 打赏
  • 举报
回复
deamon是这么写的,是不是主程序或者什么其他地方有问题了?
yanjinbin01 2008-07-17
  • 打赏
  • 举报
回复
这里我想是因为该段代码杀死父进程后,过继给init进程,而init进程没有负责的清理它,导致僵尸进程的产生.
yanjinbin01 2008-07-17
  • 打赏
  • 举报
回复
SIGCHLD 信号是等待子进程结束的信号,
我这里是是特意处理掉父进程而留下子进程的,然后把子进程过继给init进程.
这样的.
如果signal(SIGCHLD,sig); 那么sig永远不会执行.

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧