我通过fork()创建了多个子进程,并让它们通过execl()运行可执行文件。
我想检查是否有任何execl()失败(例如:尝试执行不存在的文件)。通过,尝试execl()所有程序,如果其中一个失败,则在开始与任何程序通信之前返回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;
}
此程序仍然向&#34; nonexist&#34;发送消息。 (但没有像预期的那样从中收到任何东西)。
反正有没有实现我的目标?谢谢!
答案 0 :(得分:2)
你可以安排给孩子一个pipe()
的一端,设置为关闭执行。
execl()
失败后(即如果通话返回),孩子将write()
到管道。如果父母在管道的末端收到任何东西(用poll()
或类似物检查),那么它就知道孩子失败了。
如果来自子项的消息包含子项的标识符,则可以在所有子项之间共享管道。尽量保持write()
小到足以成为原子的!
答案 1 :(得分:0)
实现目标的唯一强大(但非常奇特,可能不是非常便携)的方法是使用ptrace
。父设置PTRACE_TRACEEXEC
选项,分叉所有子项,并在循环中设置wait()
。孩子没有
} else if () {
ptrace(PTRACE_TRACEME, ...);
execl(...);
}
父母应保持循环wait
,直到所有孩子报告PTRACE_EVENT_EXEC
或退出。在第一种情况下,exec
成功,孩子停止了。当您知道每个孩子都报告了,并且您对他们的状态感到满意时,请对所有孩子进行ptrace(PTRACE_DETACH, ...)
并按照需要继续进行。