简体   繁体   English

僵尸进程和分叉

[英]Zombie process and fork

i have a code like this... 我有这样的代码......

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] and fd[WRITE] are pipe file descriptors. fd [READ]和fd [WRITE]是管道文件描述符。

when i run it continuously, there are a lot of zombie processes when i use ps ax. 当我连续运行时,当我使用ps ax时,会有很多僵尸进程。 How to rectify this? 如何纠正这个? Is this because i am not using the parent to wait for the exit status of the child process... 这是因为我没有使用父进程来等待子进程的退出状态...

如果您无意wait子进程,请将SIGCHLD处理程序设置为SIG_IGN以使内核自动SIG_IGN您的子进程,例如。

signal(SIGCHLD, SIG_IGN);

Yes, the parent must wait for the child return status. 是的,父母必须等待孩子返回状态。 You can do it asynchronously by catching SIGCHILD in the parent process and then call waitpid in the capture method. 您可以通过在父进程中捕获SIGCHILD来异步执行,然后在捕获方法中调用waitpid

Yes, waitpid() should be called from parent. 是的,应该从父级调用waitpid()。 waitpid() will clean-up any child process of the parent process, which is currently in terminated state. waitpid()将清除父进程的任何子进程,该进程当前处于已终止状态。

You can add below code to your program : 您可以在程序中添加以下代码:

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; 
    }
  }
}

FYI : more on waitpid. 仅供参考:更多关于waitpid。

First parameter is set to -1 such that waitpid() will clean-up any child process of this parent process, which is currently in terminated state.The first parameter can also be +ve - in this case, waitpid() will cleanup only the specific child process.Most common use is to set first parameter to -1 also refer to manual page of waitpid(). 第一个参数设置为-1,这样waitpid()将清除此父进程的任何子进程,该进程当前处于已终止状态。第一个参数也可以是+ ve - 在这种情况下,waitpid()将仅清除具体的子进程。最常见的用法是将第一个参数设置为-1,也可以参考waitpid()的手册页。 Second parameter is used to extract the termination/exit status code of the child process - waitpid() system call API fills the status field when the system call API is invoked. 第二个参数用于提取子进程的终止/退出状态代码 - waitpid()系统调用API在调用系统调用API时填充状态字段。 Last field is the flags field - currently unused - in most cases, flags field will be set to 0 - meaning, default behaviour of the system call API !!! 最后一个字段是标志字段 - 当前未使用 - 在大多数情况下,标志字段将设置为0 - 意味着,系统调用API的默认行为! if you really need to use flags, refer to manual page of waitpid(). 如果你真的需要使用标志,请参考waitpid()的手册页。

Note: In the code you submitted, _exit(1) will be called iff execlp() fails. 注意:在您提交的代码中,iff execlp()失败时将调用_exit(1)。 so you can put a condition for execlp() fail and that condition _exit() can be called. 所以你可以为execlp()失败一个条件,并且可以调用条件_exit()。 The Reason is, execlp() functions only return if an error has occurred. 原因是,execlp()函数仅在发生错误时才返回。

Modified code can be like below : 修改后的代码如下:

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]);

I appreciate the above 2 answers. 我很欣赏以上2个答案。 Wish this answer may give more clarity. 希望这个答案可以更清晰。 Thank you. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM