在子返回中使用带有execl的waitpid-1和ECHILD?
如果我使用的是execl is子进程可能需要时间才能完成,那么何时需要使用waitpid 当我在父级中使用waitpid时,它会给我运行的子级,因为waitpid的返回值为0。我试图在另一个函数中使用waitpid,在这个函数中,它返回带有ECHILD的me-1。如果我不确定孩子是否完成,我应该在什么时候使用waitpid在子返回中使用带有execl的waitpid-1和ECHILD?,c,linux,fork,waitpid,os.execl,C,Linux,Fork,Waitpid,Os.execl,如果我使用的是execl is子进程可能需要时间才能完成,那么何时需要使用waitpid 当我在父级中使用waitpid时,它会给我运行的子级,因为waitpid的返回值为0。我试图在另一个函数中使用waitpid,在这个函数中,它返回带有ECHILD的me-1。如果我不确定孩子是否完成,我应该在什么时候使用waitpid //pid_t Checksum_pid = fork(); Checksum_pid = fork(); if (Checksum_pid == 0) { exe
//pid_t Checksum_pid = fork();
Checksum_pid = fork();
if (Checksum_pid == 0)
{
execl(path, name, argument as needed, ,NULL);
exit(EXIT_SUCCESS);
}
else if (Checksum_pid > 0)
{
pid_t returnValue = waitpid(Checksum_pid, &childStatus, WNOHANG);
if ( returnValue > 0)
{
if (WIFEXITED(childStatus))
{
printf("Exit Code: _ WEXITSTATUS(childStatus)") ;
}
}
else if ( returnValue == 0)
{
//Send positive response with routine status running (0x03)
printf("Child process still running") ;
}
else
{
if ( errno == ECHILD )
{
printf(" Error ECHILD!!") ;
}
else if ( errno == EINTR )
{
// other real errors handled here.
printf(" Error EINTR!!") ;
}
else
{
printf("Error EINVAL!!") ;
}
}
}
else
{
/* Fork failed. */
printf("Fork Failed") ;
}
如果您使用
WNOHANG
等待,则除非您的孩子已经死亡,否则您将无法获得任何有用的状态,而且它甚至可能还没有开始运行(当家长执行waitpid()
时,它可能仍在等待从磁盘加载可执行文件)
如果您想知道子进程已完成,请不要对第三个参数使用WNOHANG
-使用0
,除非您想知道未跟踪或继续的进程。这将等待Checksum\u pid
标识的进程退出,或者系统通过某种神秘的方式(我从未见过这种情况发生)失去对它的跟踪
此代码生成退出代码0作为输出:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
pid_t Checksum_pid = fork();
if (Checksum_pid < 0)
printf("Fork Failed\n");
else if (Checksum_pid == 0)
{
execl("/bin/sleep", "/bin/sleep", "2", NULL);
exit(EXIT_FAILURE);
}
else
{
int childStatus;
pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0);
if (returnValue > 0)
{
if (WIFEXITED(childStatus))
printf("Exit Code: %d\n", WEXITSTATUS(childStatus));
else
printf("Exit Status: 0x%.4X\n", childStatus);
}
else if (returnValue == 0)
printf("Child process still running\n");
else
{
if (errno == ECHILD)
printf(" Error ECHILD!!\n");
else if (errno == EINTR)
printf(" Error EINTR!!\n");
else
printf("Error EINVAL!!\n");
}
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
pid_t校验和_pid=fork();
if(校验和pid<0)
printf(“Fork失败\n”);
else if(校验和=0)
{
execl(“/bin/sleep”、“/bin/sleep”、“2”、NULL);
退出(退出失败);
}
其他的
{
国际儿童地位;
pid_t returnValue=waitpid(校验和&childStatus,0);
如果(返回值>0)
{
如果(妻子退出(子女身份))
printf(“退出代码:%d\n”,WEXITSTATUS(childStatus));
其他的
printf(“退出状态:0x%.4X\n”,childStatus);
}
else if(returnValue==0)
printf(“子进程仍在运行\n”);
其他的
{
if(errno==ECHILD)
printf(“错误ECHILD!!\n”);
else if(errno==EINTR)
printf(“错误EINTR!!\n”);
其他的
printf(“错误EINVAL!!\n”);
}
}
返回0;
}
它与您的代码非常相似;我只是将fork()
的检查移到了顶部。我仍然希望去掉if
语句中的“茂密树”,但这并不重要。运行此代码时会发生什么情况?要获得ECHILD
错误,您需要更改什么(您可以更改它以获得ECHILD
错误)
当您成功地获得了基于此的代码来重现问题时,我们可以找出为什么会出现这种行为
在Mac OS X 10.9.2 Mavericks和GCC 4.8.2上进行了测试,在Ubuntu 13.10和GCC 4.8.1上也进行了测试(我需要添加-D_XOPEN_SOURCE=700
以使其使用我严格的编译标志进行编译;Mac OS X不使用该标志进行管理),但我不希望在其他地方得到不同的结果。int start(int Area)
int start(int Area)
{
int childStatus;
pid_t Checksum_pid = fork();
if(Checksum_pid < 0)
{
/* Fork failed. */
printf(" Fork Failed") ;
}
else if (Checksum_pid == 0)
{
for (int i = 0; i<5; i++)
{
if ( g_area[i] == Area)
{
execl(ScriptPath, ScriptName, NULL);
}
}
exit(EXIT_FAILURE);
}
else
{
/* This is the parent process. */
pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0);
if ( returnValue > 0)
{
// Check if child ended normally
printf("WAITPID Successful") ;
if (WIFEXITED(childStatus))
{
printf("Exit Code: _ WEXITSTATUS(childStatus)");
}
}
else if ( returnValue == 0)
{
printf("Child process still running") ;
}
else
{
if ( errno == ECHILD )
{
printf("Error ECHILD!!") ;
}
else if ( errno == EINTR )
{
printf("Error EINTR!!") ;
}
else
{
printf(" Error EINVAL!!") ;
}
retCode = FAILED;
}
}
}
{
国际儿童地位;
pid_t校验和_pid=fork();
if(校验和pid<0)
{
/*Fork失败了*/
printf(“Fork失败”);
}
else if(校验和=0)
{
对于(int i=0;i 0)
{
//检查孩子是否正常结束
printf(“WAITPID Successful”);
如果(妻子退出(子女身份))
{
printf(“退出代码:uwexitstatus(childStatus)”;
}
}
else if(returnValue==0)
{
printf(“子进程仍在运行”);
}
其他的
{
if(errno==ECHILD)
{
printf(“错误ECHILD!!”);
}
else if(errno==EINTR)
{
printf(“错误EINTR!!”);
}
其他的
{
printf(“错误EINVAL!!”);
}
retCode=失败;
}
}
}
如果忽略信号SIGCHLD(这是默认值),并且您跳过Jonathan提到的WNOHANG,waitpid将挂起,直到子项退出,然后使用代码ECHILD失败。我自己在一个场景中遇到过这种情况,父进程只需等待子进程完成,为SIGCHLD注册一个处理程序似乎有点过火。自然的后续问题是“在这种情况下,是否可以将ECHILD视为预期事件,还是我应该一直为SIGCHLD编写处理程序?”,
但我没有答案
从:
梯田
(对于waitpid()或waitid())由pid(waitpid())指定的进程
或idtype和id(waitid())不存在或不是的子级
呼叫过程。(这可能发生在自己的孩子身上,如果
for SIGCHLD设置为SIG_IGN。另请参阅Linux说明部分关于
线程。)
再往下
POSIX.1-2001规定,如果SIGCHLD的处置设置为
为SIGCHLD设置SIG_IGN或SAU NOCLDWAIT标志(请参阅
sigaction(2)),则终止的子对象不会变成僵尸,并且
对wait()或waitpid()的调用将被阻止,直到所有子项
终止,然后在errno设置为ECHILD时失败。(原文)
POSIX标准保留了将SIGCHLD设置为SIG_IGN的行为
未指定。请注意,即使SIGCHLD的默认配置
是“忽略”,显式地将处置设置为SIG_IGN会导致
对僵尸进程子进程的不同处理。)Linux 2.6符合
本规范。但是,Linux2.4(及更早版本)没有:如果
在忽略SIGCHLD时进行wait()或waitpid()调用
调用的行为就像SIGCHLD没有被忽略一样,也就是说,
调用将一直阻塞,直到下一个子项终止,然后返回
过程