1

我通过 fork() 创建了多个子进程,并让它们通过 execl() 运行可执行文件。

我想检查是否有任何 execl() 失败(例如:尝试执行不存在的文件)。通过,尝试 execl() 所有程序,如果其中一个程序失败,则在 start 与任何程序通信之前返回 1。

这是参考代码,(假设所有设置都正确)

#DEFINE NUMBEROFCHILD 4
char** exeFile = {"./p1", "./p2", "./p3", "nonexist"); //"nonexist" is a non-exist program
int main(int argc, char** argv){
     pid_t childPID [numberOfChild];

     for (int i = 0; i<numberOfChild; i++) {
          //setting up pipes
          pid_t childPID[i] = fork();

          if(childPID[i] < 0) {
               //close all pipes and quit
          }else if (childPID[i] == 0) {
               //redirect pipe
               execl(exeFile[i],"args",(char*)0;
               return 1; 
               //I'm expecting this to return when it try to execute "nonexist"
               //but it didn't and keep running successed execl()
          }else {
               //close un-use pipes
          }
     }

     while(true) {
          for (int i = 0; i<numberOfChild; i++) {
               //communicate with childs through pipe
          }
     }

     for (int i = 0; i<numberOfChild; i++) {
          //close reminded pipes
          if (waitpid(childPID[i], NULL, 0) == -1){
               return 1;
          }
     }
     return 0;
}

该程序仍然向“不存在”发送消息(但没有按预期收到任何回复)。

有没有办法实现我的目标?谢谢!

4

2 回答 2

2

您可以安排给孩子一个的一端pipe(),设置为 close-on-exec。

失败后execl()(即如果调用返回),子进程将write()进入管道。如果父级在其管道末端收到任何内容(检查poll()或类似),则它知道子级失败。

如果来自孩子的消息包含孩子的标识符,那么管道可以在所有孩子之间共享。不过,尽量保持write()足够小以成为原子!

于 2016-09-29T20:50:06.980 回答
0

实现目标的唯一强大(但非常奇特,可能不是很便携)的方法是使用ptrace. 父级设置PTRACE_TRACEEXEC选项,派生所有子级,并wait()在循环中。孩子做

    } else if () {
        ptrace(PTRACE_TRACEME, ...);
        execl(...);
    }

父级应继续循环wait,直到所有子级报告其中一个PTRACE_EVENT_EXEC或退出。在第一种情况下,exec成功了,孩子被阻止了。当您知道每个孩子都报告了,并且您对他们的状态感到满意时,ptrace(PTRACE_DETACH, ...)请按照所有孩子的要求进行操作。

于 2016-09-29T22:25:12.833 回答