2014-10-28 72 views
1

我有简单的C程序,它使用fork()和execl()来执行应用程序。如果execl()无法运行应用程序,那么我必须在父进程中调用一个函数并退出子进程。如果execl()成功运行应用程序,那么我已经显示父进程的成功日志。因此,父进程应该等待子进程的execl()调用(只是调用,直到应用程序执行结束),获取有关它的状态信息,然后做出决定并继续执行。这是我的代码。如何在C程序中调用execl()之后控制父进程的执行?

int main() 
{ 
    int iExecRetVal, pid; 
    pid = fork(); 

    if (pid == -1) 
    { 

    } 
    else if (pid > 0) 
    { 
    } 
    else 
    { 
     iExecRetVal = execl("./flute-static", "./flute-static", "-send", "-a192.168.190.1/6666", "JFlute.1.2.tar.gz", NULL); 
     if (iExecRetVal == -1) 
     { 
      /*execl() failed, need some error handling in the parent process*/ 
     } 
     _exit(0); 
    } 

    /*Parent's normal execution*/ 
} 

int HandleSuccessFromParent() 
{ 
    /*Should be called when exec call was successful*/ 
} 

int HandleFailureFromParent() 
{ 
    /*Should be called when exec call was NOT successful*/ 
} 

我们知道execl()不会成功返回。因此,如何在子节点中的execl()调用后正确调用HandleSuccessFromParent()和HandleFailureFromParent()函数。请帮帮我。

回答

1

一种可能的解决方案涉及ptrace。大纲如下:

让孩子打电话ptrace(PTRACE_TRACEME)。让父母对孩子启用PTRACE_O_TRACEEXEC选项和waitpid。在此设置waitpid将返回成功execl。测试状态以查看它是否设置了SIGTRAP标志。让孩子继续PTRACE_DETACH

+2

确实如此,但对我们大多数人来说,这可能太高科技了。我在实践中更喜欢[Jonathan Leffler的回答](http://stackoverflow.com/a/26617152/841108)。 – 2014-10-28 21:00:34

7

子进程需要以错误状态退出(非零; 1是常见的,EXIT_FAILURE是标准C)。

父进程需要等待孩子完成并使用wait()waitpid()捕获孩子的退出状态。

如果你需要知道孩子是否死亡,但不希望等待它完成,一个小小的停顿之后使用waitpid()WNOHANG让孩子尝试和运行(一分一秒的延迟可能是够长了)。

+0

IIRC,[system(3)](http://man7.org/linux/man-pages/man3/system.3.html)如果其''/ bin/sh'的'execve'会'退出(127)' '在Linux或Posix上失败我认为在这种情况下使用127退出代码是有用的(在其他情况下,我知道没有程序退出127) – 2014-10-28 20:59:25

+0

@BasileStarynkevitch:是的,以及POSIX ['sh'](http ://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01)包含关于shell上不同错误条件的退出状态值126,127和129+的信息。如果你愿意,你可以决定遵循。关键的一点是'不要在失败状态下退出状态0';与126,127等退出是一个二阶的细化。 – 2014-10-28 21:31:22

+0

确实这是一种改进,但却是一个非常有用的方法。 GNU'grep'在失败时使用几个(小的)退出代码,所以使用其他不是1的代码是有用的,而使用127稍微有用(因为在这种情况下它是一种常规习惯)。 – 2014-10-28 21:35:40

相关问题