求解。。。
#include ......
pid_t cpid;
void sigHandle(int sig)
{
printf("\nin sigHandle\n");
pid_t pid;
pid= waitpid(-1,NULL,0);
if (pid>0)
printf("pid=[%d] terminated\n",pid);
else
printf("waitpid error [%s]\n",strerror(errno));
return ;
}
int main()
{
char path[]="/home/test";
char pro_name[]="test";
pid_t pid;
signal(SIGCHLD,sigHandle);
pid=fork();
if(pid==0)
{cpid=getpid();
printf("cpid=[%d]\n",cpid);
if( 0 > execl(path,pro_name,par,"start",NULL))
// if( 0 > system(path))
{
printf("call program: [%s] failed!\n",pro_name);
}// sleep(1); //此处加上后SIGCHLD信号处理函数怎么不执行了呢??
printf("\nnever run here \n");
}
return 0;
}
12 个解决方案
#1
man execl函数, 有以下说明:
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see <signal.h>).
是不是因为这个原因呢?
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see <signal.h>).
是不是因为这个原因呢?
#2
#3
自己进行了以下实验:
test.c中:
exec.c中:
程序运行结果:
但是如果将exec.c中的父进程中的sleep(5)去掉,则执行结果为:
Fork分叉后,先执行父进程,父进程执行完毕后直接返回了。而在执行子进程时,由于父进程已经退出所以此时father pid已经变为(init )1号进程了。
总归是由于父子进程的竞争执行顺序关系影响了SIGCHLD信号处理函数的执行。
test.c中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("\ntest:\n test pid=[%d],ppid=[%d]\n",getpid(), getppid());
sleep(1);
return 0;
}
exec.c中:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
pid_t cpid;
void sigHandle(int sig)
{
printf("\n************in sigHandle*************\n");
pid_t pid;
pid= waitpid(-1,NULL,0);
if (pid>0)
printf("pid=[%d] terminated\n",pid);
else
printf("waitpid error [%s]\n",strerror(errno));
return ;
}
int main()
{
char path[]="/Desktop/MyTest/test";
char pro_name[]="test";
pid_t pid;
// signal(SIGCHLD,sigHandle);
struct sigaction chld;
memset(&chld,0x00,sizeof(chld));
chld.sa_handler=sigHandle;
sigaction(SIGCHLD,&chld,NULL);
pid=fork();
if(pid==0)
{
cpid=getpid();
printf("\nexec:This is in child process. \nchild pid=[%d] ,father pid =[%d]\n",cpid,getppid());
if( 0 > execl(path,pro_name,NULL))
// if( 0 > system(path))
{/*调起任务失败*/
printf("call program: [%s] failed!\n",pro_name);
}
printf("\nnever run here\n");
}
else
if (pid>0)
{
printf("exec:in father process.\n pid=[%d]\n",getpid());
sleep(5);//此处加入了等待子进程结束
;
}
return 0;
}
程序运行结果:
但是如果将exec.c中的父进程中的sleep(5)去掉,则执行结果为:
Fork分叉后,先执行父进程,父进程执行完毕后直接返回了。而在执行子进程时,由于父进程已经退出所以此时father pid已经变为(init )1号进程了。
总归是由于父子进程的竞争执行顺序关系影响了SIGCHLD信号处理函数的执行。
#4
事实是父进程fork()没有阻塞等待SIGCHLD,就直接return 0了,然后子进程变成了zombie
#5
你在return 0前加个 pause();
#6
厉害!
#7
为啥我ps命令查看,没有看到僵尸进程呢??
#8
pause方案不够专业。
了解一下sigprocmask+sigsuspend
了解一下sigprocmask+sigsuspend
#9
嗯,过继到init了,没有zombie。不好意思。
#10
pause方案不够专业。
了解一下sigprocmask+sigsuspend
恩,如果我程序里面fork了多个子进程,每个子进程通过execl函数拉起不同的可执行程序,这样每个子进程(其实也就是每个execl函数拉起的每个可执行程序)结束的时间并不一定相同,这样的话如果在父进程return之前pause() 一下,就只能接收到在调用pause()函数这一时刻时结束的子进程发出的SIGCHLD信号,处理僵尸进程。万一有个子进程执行的时间比较长,在pause()这一时刻还没有结束,而这时父进程已经返回了,那岂不是这个子进程就成为僵尸进程了吗??
这种情况下应该怎么办呢?怎么将所有子进程产生的僵尸进程全部清理了呢??
#11
你想做的其实就是wait所有的子进程。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
#12
你想做的其实就是wait所有的子进程。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
恩,这个方法我倒是想到了,在fork的时候记录下所有的子进程数,然后看wait了多少个,进行判断。
但是想知道还有没有其他的方法。
#1
man execl函数, 有以下说明:
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see <signal.h>).
是不是因为这个原因呢?
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see <signal.h>).
是不是因为这个原因呢?
#2
#3
自己进行了以下实验:
test.c中:
exec.c中:
程序运行结果:
但是如果将exec.c中的父进程中的sleep(5)去掉,则执行结果为:
Fork分叉后,先执行父进程,父进程执行完毕后直接返回了。而在执行子进程时,由于父进程已经退出所以此时father pid已经变为(init )1号进程了。
总归是由于父子进程的竞争执行顺序关系影响了SIGCHLD信号处理函数的执行。
test.c中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("\ntest:\n test pid=[%d],ppid=[%d]\n",getpid(), getppid());
sleep(1);
return 0;
}
exec.c中:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
pid_t cpid;
void sigHandle(int sig)
{
printf("\n************in sigHandle*************\n");
pid_t pid;
pid= waitpid(-1,NULL,0);
if (pid>0)
printf("pid=[%d] terminated\n",pid);
else
printf("waitpid error [%s]\n",strerror(errno));
return ;
}
int main()
{
char path[]="/Desktop/MyTest/test";
char pro_name[]="test";
pid_t pid;
// signal(SIGCHLD,sigHandle);
struct sigaction chld;
memset(&chld,0x00,sizeof(chld));
chld.sa_handler=sigHandle;
sigaction(SIGCHLD,&chld,NULL);
pid=fork();
if(pid==0)
{
cpid=getpid();
printf("\nexec:This is in child process. \nchild pid=[%d] ,father pid =[%d]\n",cpid,getppid());
if( 0 > execl(path,pro_name,NULL))
// if( 0 > system(path))
{/*调起任务失败*/
printf("call program: [%s] failed!\n",pro_name);
}
printf("\nnever run here\n");
}
else
if (pid>0)
{
printf("exec:in father process.\n pid=[%d]\n",getpid());
sleep(5);//此处加入了等待子进程结束
;
}
return 0;
}
程序运行结果:
但是如果将exec.c中的父进程中的sleep(5)去掉,则执行结果为:
Fork分叉后,先执行父进程,父进程执行完毕后直接返回了。而在执行子进程时,由于父进程已经退出所以此时father pid已经变为(init )1号进程了。
总归是由于父子进程的竞争执行顺序关系影响了SIGCHLD信号处理函数的执行。
#4
事实是父进程fork()没有阻塞等待SIGCHLD,就直接return 0了,然后子进程变成了zombie
#5
你在return 0前加个 pause();
#6
你在return 0前加个 pause();
厉害!
#7
你在return 0前加个 pause();
为啥我ps命令查看,没有看到僵尸进程呢??
#8
pause方案不够专业。
了解一下sigprocmask+sigsuspend
了解一下sigprocmask+sigsuspend
#9
你在return 0前加个 pause();
为啥我ps命令查看,没有看到僵尸进程呢??
嗯,过继到init了,没有zombie。不好意思。
#10
pause方案不够专业。
了解一下sigprocmask+sigsuspend
恩,如果我程序里面fork了多个子进程,每个子进程通过execl函数拉起不同的可执行程序,这样每个子进程(其实也就是每个execl函数拉起的每个可执行程序)结束的时间并不一定相同,这样的话如果在父进程return之前pause() 一下,就只能接收到在调用pause()函数这一时刻时结束的子进程发出的SIGCHLD信号,处理僵尸进程。万一有个子进程执行的时间比较长,在pause()这一时刻还没有结束,而这时父进程已经返回了,那岂不是这个子进程就成为僵尸进程了吗??
这种情况下应该怎么办呢?怎么将所有子进程产生的僵尸进程全部清理了呢??
#11
你想做的其实就是wait所有的子进程。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
#12
你想做的其实就是wait所有的子进程。
可以对waited子进程和total子进程数都做记录,如果不相等就通过某种方式阻塞,然后再wait,直到回收了所有子进程为止。
恩,这个方法我倒是想到了,在fork的时候记录下所有的子进程数,然后看wait了多少个,进行判断。
但是想知道还有没有其他的方法。