使用带有 stdin 和 stdout 重定向的 2 进程管道时如何避免在 stdin 上重复输入
How to avoid duplicate input on stdin when using 2-process pipeline with stdin and stdout redirect
我打算在两个进程之间建立一个管道:parent 和 child。 parent 派生 child 并使用 execve 将其映像替换为指定进程的映像。
parent 通过 std::getline(std::cin, input_line) 从标准输入读取。
child 通过 std::cout << output_line 写入标准输出。
我正在寻找设置管道并将 child 的输出重定向到 parent 的输入。
问题是 parent 接收每个输入(其中每个输入是 child 在 stdout 上输出的数字)两次。我想解决这个问题,但我不明白为什么会这样。
代码使用g++ 7.4.0和C++11标准版编译。
Child 被编译成一个名为 'p1'.
的二进制文件
Parent代码:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
char *
const p1argv[] = {
(char * )
"./p1",
nullptr
};
char *
const p1envp[] = {
(char * ) nullptr
};
int main(int argc, char ** argv) {
pid_t p1id;
int p1fd[2];
pipe(p1fd);
if (p1id = fork() == 0) {
close(p1fd[0]);
dup2(p1fd[1], STDOUT_FILENO);
execve(argv[0], p1argv, p1envp);
perror("Error: failed to execve ./p1.");
} else {
dup2(p1fd[0], STDIN_FILENO);
close(p1fd[1]);
std::string line;
while (std::getline(std::cin, line)) {
std::cout << "d(" << line << ")" << std::endl;
}
int status;
waitpid(p1id, & status, 0);
close(p1fd[0]);
}
}
Child代码:
#include <iostream>
#include <thread>
int main(int argc, char** argv) {
long it = 0;
while(true) {
it += 1;
std::cout << std::to_string(it) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
示例代码的实际输出是:
d(d(1))
d(d(2))
...
预期输出为:
d(1)
d(2)
...
问题是这一行:
execve(argv[0], p1argv, p1envp);
正在重新执行主父程序,因为此时argv[0]
的内容就是这样。我想你想找到一些方法来指定 "./p1"
那里。
我打算在两个进程之间建立一个管道:parent 和 child。 parent 派生 child 并使用 execve 将其映像替换为指定进程的映像。
parent 通过 std::getline(std::cin, input_line) 从标准输入读取。 child 通过 std::cout << output_line 写入标准输出。
我正在寻找设置管道并将 child 的输出重定向到 parent 的输入。
问题是 parent 接收每个输入(其中每个输入是 child 在 stdout 上输出的数字)两次。我想解决这个问题,但我不明白为什么会这样。
代码使用g++ 7.4.0和C++11标准版编译。
Child 被编译成一个名为 'p1'.
的二进制文件Parent代码:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
char *
const p1argv[] = {
(char * )
"./p1",
nullptr
};
char *
const p1envp[] = {
(char * ) nullptr
};
int main(int argc, char ** argv) {
pid_t p1id;
int p1fd[2];
pipe(p1fd);
if (p1id = fork() == 0) {
close(p1fd[0]);
dup2(p1fd[1], STDOUT_FILENO);
execve(argv[0], p1argv, p1envp);
perror("Error: failed to execve ./p1.");
} else {
dup2(p1fd[0], STDIN_FILENO);
close(p1fd[1]);
std::string line;
while (std::getline(std::cin, line)) {
std::cout << "d(" << line << ")" << std::endl;
}
int status;
waitpid(p1id, & status, 0);
close(p1fd[0]);
}
}
Child代码:
#include <iostream>
#include <thread>
int main(int argc, char** argv) {
long it = 0;
while(true) {
it += 1;
std::cout << std::to_string(it) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
示例代码的实际输出是:
d(d(1)) d(d(2)) ...
预期输出为:
d(1) d(2) ...
问题是这一行:
execve(argv[0], p1argv, p1envp);
正在重新执行主父程序,因为此时argv[0]
的内容就是这样。我想你想找到一些方法来指定 "./p1"
那里。