2

我对如何处理来自execvp(). 到目前为止,我的代码如下所示:

int pid = fork();
if (pid < 0) {
    // handle error.
}
else if (pid == 0) {
    int status = execvp(myCommand,myArgumentVector); // status should be -1 because execvp
                                                     // only returns when an error occurs
    // We only reach this point as a result of failure from execvp
    exit(/* What goes here? */);
}
else {
    int status;
    int waitedForPid = waitpid(pid,&status,0);
    //...
}

我试图解决三种情况:

  1. myCommand,myArgumentVector有效并且命令正确执行。
  2. myCommand,myArgumentVector是有效参数,但在执行myCommand.
  3. myCommand,myArgumentVector是无效参数(例如myCommand无法找到)并且execvp()调用失败。

我主要担心的是父进程将拥有正确处理子错误所需的所有信息,我不完全确定如何做到这一点。

在第一种情况下,程序可能以退出状态 0 结束。这意味着如果我要WIFEXITED(status)在宏中调用,我应该得到true. 我认为这应该可以正常工作。

在第二种情况下,程序可能以非 0 的退出状态结束。这意味着如果我要调用,WEXITSTATUS(status)我应该得到子调用的特定退出状态myCommand(如果这不正确,请告知)。

第三种情况让我很困惑。因此,如果execvp()失败,则错误将存储在全局变量errno中。但是这个全局变量只能从子进程访问;父母作为一个完全独立的过程,我认为看不到它。这是否意味着我应该打电话exit(errno)?还是我应该在这里做点别的事情?另外,如果我打电话,我exit(errno)怎么能从父母那里得到errno回来的价值?status

我的掌握仍然有点脆弱,所以我正在寻找的是确认或纠正我对如何处理这三种情况的理解。

4

4 回答 4

3

这是我尝试过的简单代码。

if(fork() == 0){
   //do child stuff here
   execvp(cmd,arguments); /*since you want to return errno to parent
                            do a simple exit call with the errno*/
   exit(errno);
}
else{                
    //parent stuff
    int status;
    wait(&status);       /*you made a exit call in child you 
                           need to wait on exit status of child*/
    if(WIFEXITED(status))
         printf("child exited with = %d\n",WEXITSTATUS(status));
                              //you should see the errno here
}
于 2013-11-19T05:53:34.870 回答
2

在情况 1 中,execvp()不返回。返回给父进程的状态将是子进程的退出状态——它提供给exit()什么或从什么返回main(),或者可能是子进程死于信号,在这种情况下退出状态不同但可检测到 ( WIFSIGNALED, ETC)。请注意,这意味着状态不必为零。

(对我来说)您对案例 2 的想法并不完全清楚。如果命令启动但拒绝调用它的选项,实际上是案例 1,但退出状态为零的机会应该很小(尽管众所周知,程序在出错时会以状态 0 退出)。或者,找不到该命令,或者找到该命令但不可执行,在这种情况下execvp()返回并且您有情况 3。

在情况 3 中,execvp()调用失败。你知道,因为它会返回;一个成功的execvp()永远不会回来。测试 ; 的返回值是没有意义的execvp()。它返回的事实意味着它失败了。您可以从errno. POSIX 使用 126 和 127 的退出状态 — 参见xargssystem()示例。您可以查看错误代码,execvp()以确定何时应该返回这些值或其他一些非零值。

于 2013-11-19T06:22:14.933 回答
1

在第三种情况下,也可以从父级访问 errno,因此您可以退出(errno)。但是,这不是最好的做法,因为 errno 的值可能会在您退出时发生变化。

如果在 exec() 和 exit() 调用之间有代码,为了更确定不会丢失 errno,请将 errno 分配给 int:

execvp(<args>);

int errcode=errno;

/* other code */

exit(errcode);

至于您的另一个问题,退出状态与 errno 不能直接比较,并且您不应该尝试从除 errno 之外的任何东西(如上)中检索 errno。

本文档可能会有所帮助: http ://www.gnu.org/software/libc/manual/html_node/Exit-Status.html

于 2013-11-19T05:52:58.237 回答
0

这是我的代码:它工作正常。子状态在 waitpid 中返回,因此它告诉子进程是否成功执行。//声明一个进程id变量pid_t pid, ret_pid;

//fork a child process is assigned 
//to the process id
pid=fork();

DFG_STATUS("Forking and executing process in dfgrunufesimulator %d \n", pid);

//code to show that the fork failed
//if the process id is less than 0
if(pid<0)
{
    return DFG_FAILURE;
}
else if(pid==0)
{
    //this statement creates a specified child process
    exec_ret = execvp(res[0],res);  //child process

DFG_STATUS("Process failed ALERT exec_ret = %d\n", exec_ret);
exit(errno);

}
//code that exits only once a child 
//process has been completed
else
{
  ret_pid = waitpid(pid, &status, 0);
  if ( ret_pid == -1) 
  { 
    perror("waitpid"); 
    return DFG_FAILURE; 
  }

   DFG_STATUS("ret_pid = %d, pid = %d, child status = %d\n",ret_pid,pid,status);


  if (WIFEXITED(status)) {
        DFG_STATUS("child exited, status=%d\n", WEXITSTATUS(status));


    } else if (WIFSIGNALED(status)) {
        DFG_STATUS("child killed (signal %d)\n", WTERMSIG(status));


    } else if (WIFSTOPPED(status)) {
        DFG_STATUS("child stopped (signal %d)\n", WSTOPSIG(status));


#ifdef WIFCONTINUED     /* Not all implementations support this */
    } else if (WIFCONTINUED(status)) {
        DFG_STATUS("child continued\n");
#endif
    } else {    /* Non-standard case -- may never happen */
        DFG_STATUS("Unexpected status (0x%x)\n", status);
    }

  if(status != 0) /* Child process failed to execute */
    return DFG_FAILURE;

  result = DFG_SUCCESS;
}
于 2017-05-11T06:47:43.087 回答