我正在尝试创建一个函数,如果execvp成功,则返回true,否则返回false。最初,我没有使用管道,问题是,每当execvp失败时,我都会从父级得到2个返回,一个为false,一个为true。现在,我正在执行管道操作,当execvp失败时,我再也不会收到错误的返回。
我知道与此主题相关的问题和答案很多,但是我似乎无法缩小我的特定错误的位置。我想要的是我的变量return_type_child,return_type_parent和this-> return_type都包含相同的值。我希望在子进程中execvp会失败,因此下一行将执行。结果,我认为提到的3个变量都为假,但是当我打印出this-> return_type中的值时,将显示1。
bool Command::execute() {
this->fork_helper();
return return_type;
}
void Command::fork_helper() {
bool return_type_child = true;
int fd[2];
pipe(fd);
pid_t child;
char *const argv[] = {"zf","-la", nullptr};
child = fork();
if (child > 0) {
wait(NULL);
close(0);
close(fd[1]);
dup(fd[0]);
bool return_type_parent = read(fd[0], &return_type_child, sizeof(return_
this->return_type = return_type_parent;
}
else if (child == 0) {
close(fd[0]);
close(1);
dup(fd[1]);
execvp(argv[0], argv);
this->return_type = false;
return_type_child = false;
write(1,&return_type_child,sizeof(return_type_child));
}
return;
}
我还尝试将cout语句放在从未运行过的execvp(argv [0],argv)之后。任何帮助将不胜感激!
答案 0 :(得分:0)
从代码中看,它似乎是XY problem(编辑:由于有确认这一点的注释,因此将本节移至最前面)。如果目标是获取孩子的退出状态,则为此的值为wait
returns,并且不需要管道:
int stat;
wait(&stat);
阅读wait
的手册以了解如何阅读。可以如下测试stat
的值:
exit(N)
的调用的低8位或main
的返回值。无需检查WIFEXITED,它可能可以正常工作,但是标准未对此进行指定。代码中有几个错误。查看添加的评论:
void Command::fork_helper() {
// File descriptors here: 0=stdin, 1=stdout, 2=stderr
//(and 3..N opened in the program, could also be none).
bool return_type_child = true;
int fd[2];
pipe(fd);
// File descriptors here: 0=stdin, 1=stdout, 2=stderr
//(and 3..N opened in the program, could also be none).
// N+1=fd[0] data exhaust of the pipe
// N+2=fd[1] data intake of the pipe
pid_t child;
char *const argv[] = {"zf","-la", nullptr};
child = fork();
if (child > 0) {
// This code is executed in the parent.
wait(NULL); // wait for the child to complete.
此wait
是潜在的死锁:如果子项writes enough data to the pipe (usually in the kilobytes),写操作将阻塞并等待父项读取管道。父级wait(NULL)等待子级完成,子级等待父级读取管道。这可能不会影响所讨论的代码,但这是有问题的。
close(0);
close(fd[1]);
dup(fd[0]);
// File descriptors here: 0=new stdin=data exhaust of the pipe
// 1=stdout, 2=stderr
// (and 3..N opened in the program, could also be none).
// N+1=fd[0] data exhaust of the pipe (stdin is now a duplicate)
这是有问题的,因为:
。
bool return_type_parent = read(fd[0], &return_type_child, sizeof(return_
this->return_type = return_type_parent;
}
else if (child == 0) {
// this code runs in the child.
close(fd[0]);
close(1);
dup(fd[1]);
// File descriptors here: 0=stdin, 1=new stdout=pipe intake, 2=stderr
//(and 3..N opened in the program, could also be none).
// N+2=fd[1] pipe intake (new stdout is a duplicate)
这是有问题的,因为管道有两个重复的数据输入。在这种情况下,这并不重要,因为在过程结束时,它们都会自动关闭,但这是一个坏习惯。这是一种不好的做法,因为仅关闭所有进气管的进气口信号END-OF-FILE。关闭一个进气口但不关闭另一个进气口,并不表示文件结束。同样,在您的情况下,这不会造成麻烦,因为孩子的出口关闭了所有入口。
execvp(argv[0], argv);
除非execvp
本身失败,否则永远不会到达上一行下面的代码。 execvp
仅在文件不存在或调用者没有执行权限时失败。如果可执行文件开始执行并在以后失败(可能即使无法读取共享库也是如此),则execvp
本身仍然成功并且永不返回。这是因为execvp
替换了可执行文件,并且execvp
开始运行另一个程序时,以下代码不再在内存中。
this->return_type = false;
return_type_child = false;
write(1,&return_type_child,sizeof(return_type_child));
}
return;
}