[英]How to correctly use pipe to transfer data from child process to parent process?
I'm trying to create a function that returns true if execvp is successful and false if it is not. 我正在尝试创建一个函数,如果execvp成功,则返回true,否则返回false。 Initially, I didn't use a pipe and the problem was that whenever execvp failed, I get 2 returns, one false and one true (from the parent).
最初,我没有使用管道,问题是,每当execvp失败时,我都会从父级获得2个返回,一个为false,一个为true。 Now that I'm piping, I'm never getting a false returned when execvp fails.
现在,我正在执行管道操作,当execvp失败时,我再也不会收到错误的返回。
I know there are a lot related questions and answers on this topic, but I can't seem to narrow down where my particular error is. 我知道与此主题相关的问题和答案很多,但是我似乎无法缩小我的特定错误的位置。 What I want is for my variables return_type_child, return_type_parent, and this->return_type to all contain the same value.
我想要的是我的变量return_type_child,return_type_parent和this-> return_type都包含相同的值。 I expected that in the child process, execvp would fail so the next lines would execute.
我希望在子进程中execvp会失败,因此下一行将执行。 As a result, I thought that the 3 variables mentioned would all be false, but instead when I print out the value in this->return_type, 1 is displayed.
结果,我认为提到的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;
}
I've also tried putting a cout statement after execvp(argv[0], argv), which never ran. 我还尝试过将cout语句放在execvp(argv [0],argv)之后,该语句永远不会运行。 Any help is greatly appreciated!
任何帮助是极大的赞赏!
From the code, it seems to be an XY problem (edit: moved this section to the front due to a comment that confirms this). 从代码来看,这似乎是一个XY问题 (编辑:由于有确认这一点的注释,因此将本节移至最前面)。 If the goal is to get the exit status of the child, then for that there is the value that
wait
returns , and no pipes are required: 如果目标是获取子项的退出状态,则为此有
wait
返回的值,并且不需要管道:
int stat;
wait(&stat);
Read the manual of wait
to figure out how to read it. 阅读
wait
手册,以了解如何阅读。 The value of stat
can be tested as follows: stat
的值可以按以下方式进行测试:
exit(N)
or the return value from main
. exit(N)
的调用的低8位或main
的返回值。 It might work correctly without checking WIFEXITED, but the standard does not specify that. There are several errors in the code. 代码中有几个错误。 See the added comments:
查看添加的注释:
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.
This wait
is a potential deadlock: if the child writes enough data to the pipe (usually in the kilobytes) , the write blocks and waits for the parent to read the pipe. 这种
wait
可能会导致死锁:如果子进程将足够的数据写入管道(通常以千字节为单位) ,则写入将阻塞并等待父进程读取管道。 The parent wait(NULL) waits for the child to complete, which which waits for the parent to read the pipe. 父级wait(NULL)等待子级完成,子级等待父级读取管道。 This is likely not effecting the code in question, but it is problematic.
这可能不会影响所讨论的代码,但这是有问题的。
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)
This is problematic since: 这是有问题的,因为:
. 。
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)
This is problematic, since there are two duplicate data intakes to the pipe. 这是有问题的,因为管道有两个重复的数据输入。 In this case it is not critical since they are both closed automatically when the process ends, but it is a bad practice.
在这种情况下,这并不重要,因为在过程结束时,它们都会自动关闭,但这是一个坏习惯。 It is a bad practice, since only closing all the pipe intakes signals END-OF-FILE to the exhaust.
这是一种不好的做法,因为仅关闭所有进气管的进气口信号END-OF-FILE。 Closing one intake but not the other, does not signal END-OF-FILE.
关闭一个进气口但不关闭另一个进气口,并不表示文件结束。 Again, in your case it is not causing trouble since the child's exit closes all the intakes.
同样,在您的情况下,这不会造成麻烦,因为孩子的出口关闭了所有入口。
execvp(argv[0], argv);
The code below the above line is never reached, unless execvp
itself failed. 除非
execvp
本身失败,否则永远不会到达上一行下面的代码。 The execvp
fails only when the file does not exist, or the caller has no permission to execute it. 仅当文件不存在或调用者没有执行该文件的权限时,
execvp
才会失败。 If the executable starts to execute and fails later (possibly even if it fails to read a shared library), then still execvp
itself succeeds and never returns. 如果可执行文件开始执行并在以后失败(可能即使它无法读取共享库),那么
execvp
本身仍然成功并且永不返回。 This is because execvp
replaces the executable, and the following code is no longer in memory when execvp
starts to run the other program. 这是因为
execvp
替换了可执行文件,并且当execvp
开始运行其他程序时,以下代码不再在内存中。
this->return_type = false;
return_type_child = false;
write(1,&return_type_child,sizeof(return_type_child));
}
return;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.