我有这样的代码......
c = fork();
if(c==0) {
close(fd[READ]);
if (dup2(fd[WRITE],STDOUT_FILENO) != -1)
execlp("ssh", "ssh", host, "ls" , NULL);
_exit(1);
}
close(fd[WRITE]);
fd [READ]和fd [WRITE]是管道文件描述符。
当我连续运行时,当我使用ps ax时,会有很多僵尸进程。如何纠正这个?这是因为我没有使用父级等待子进程的退出状态...
答案 0 :(得分:7)
如果您无意wait
处理子进程,请将SIGCHLD
处理程序设置为SIG_IGN
以使内核自动收获您的子进程,例如。
signal(SIGCHLD, SIG_IGN);
答案 1 :(得分:2)
是的,家长必须等待孩子返回状态。您可以通过在父进程中捕获SIGCHILD
来异步执行,然后在捕获方法中调用waitpid
。
答案 2 :(得分:0)
是的,应该从父母调用waitpid()。 waitpid()将清除父进程的任何子进程,该进程当前处于已终止状态。
您可以在程序中添加以下代码:
if(c>0)
{
while(1){
ret = waitpid(-1,&status,0);
if(ret>0){
if(WIFEXITED(status)){
if(WEXITSTATUS(status) == 0){
printf("child process terminated normally and successfully\n");
}
else{
printf("child process terminated normally and unsuccessfully\n");
}
}
else{
printf("child process terminated abnormally and unsuccessfully\n");
}
}
if(ret<0) {
break;
}
}
}
仅供参考:更多关于waitpid。
第一个参数设置为-1,这样waitpid()将清除此父进程的任何子进程,该进程当前处于已终止状态。第一个参数也可以是+ ve - 在这种情况下,waitpid()将仅清理特定的子进程。最常见的用法是将第一个参数设置为-1,也可以参考waitpid()的手册页。 第二个参数用于提取子进程的终止/退出状态代码 - waitpid()系统调用API在调用系统调用API时填充状态字段。 最后一个字段是标志字段 - 当前未使用 - 在大多数情况下,标志字段将设置为0 - 意味着,系统调用API的默认行为!如果你真的需要使用标志,请参考waitpid()的手册页。
注意: 在您提交的代码中,如果iff execlp()失败,将调用_exit(1)。所以你可以为execlp()失败一个条件,并且可以调用条件_exit()。原因是,execlp()函数仅在发生错误时才返回。
修改后的代码如下所示:
c = fork();
if(c==0) {
close(fd[READ]);
if (dup2(fd[WRITE],STDOUT_FILENO) != -1)
ret_execlp = execlp("ssh", "ssh", host, "ls" , NULL);
if(ret_execlp == -1 ) {
printf("execlp is failed");
_exit(1);
}
}
close(fd[WRITE]);
我很欣赏以上2个答案。希望这个答案可以更清晰。谢谢。