我必须通过fork(),dup2和pipe并行运行一堆程序;
(程序:rgen,A1,A2和驱动程序本身A3)
- A3使用cml参数启动并执行rgen(通过fork);
- rgen将stdout传递给A1(通过管道'到'A1');
- A1需要从rgen(通过管道'到A1')获取stdin,处理然后将stdout发送到A2(通过管道'toA2');
- A2需要从A1(从管道'到A2')取stdin;
- A2然后接收该输入并将从A1获得的内容发送到stdout(屏幕),然后等待用户输入A3(通过管道'到A2')或从A1通过管道输入到'A2';
- 然后驱动程序需要从键盘获取stdin并将stdout发送到A2(通过管道'toA2');
问题是管道'toA2'似乎不起作用。我知道A1将正确的输出发送到stdout。我知道A2接收来自stdin的输入。目前A2从键盘接收stdin,如“std :: cin>> use_input”所示,以及当我运行程序时除非我在命令行输入内容,否则它不会做任何其他事情。
终端应该如下所示:
$./A3 -s 5 -n 4 -l 5
V 8
E {<0,2>,<0,3>,<0,4>,<1,3>,<4,7>,<5,2>,<5,6>}
s 2 4
2-0-4
其中“./A3 -s 5 -n 4 -l 5”和“s 2 4”是用户输入到命令行的“V 8”和“E {...}”和“2-0” A2“全部输出到屏幕。
* fyi所有单个程序都运行得很好(可能不是A3,因为它是唯一有潜在问题的程序),我更担心从其他进程获取信息。
我删除了程序中与stdin或stdout无关的所有代码,并将其替换为“...”。如果有必要展示,让我知道,我只是觉得用这种方式阅读会更容易,因为我知道它在我输入之后就有效了。
计划A3(c ++):
int main(int argc, char **argv) {
std::string user_input;
std::vector<pid_t> kids;
pid_t child_pid;
char* empty_arg1[2];
empty_arg1[0] = "A1.py";
empty_arg1[1] = nullptr;
char* empty_arg2[2];
empty_arg2[0] = "A2";
empty_arg2[1] = nullptr;
int toA1[2];
int toA2[1];
pipe(toA1);
pipe(toA2);
child_pid = fork();
//runs rgen; Sends output to 'toA1'
if (child_pid == 0) {
dup2(toA1[1], STDOUT_FILENO); //Sends stdout to pipe 'toA1'
close(toA1[0]);
close(toA1[1]);
return execv("./rgen", argv);
}
kids.push_back(child_pid);
child_pid = fork();
//runs A1; Sends output to 'toA2'; Gets input from pipe 'toA1'
if (child_pid == 0) {
dup2(toA1[0], STDIN_FILENO); //A1 gets stdin from pipe 'toA1'
close(toA1[0]);
close(toA1[1]);
dup2(toA2[1], STDOUT_FILENO); //sends stdout to pipe 'toA2'
close(toA2[0]);
close(toA2[1]);
return execvp("./A1.py", empty_arg1);
}
kids.push_back(child_pid);
child_pid = fork();
//runs A2; Gets input from 'toA2'
if (child_pid == 0) {
std::string use_input = "blank";
dup2(toA2[0], STDIN_FILENO); //A2 gets stdin from pipe 'toA2'
close(toA2[0]);
close(toA2[1]);
std::cout << "use_input[1] = " << use_input << std::endl;
return execv("./A2", empty_arg2);
}
kids.push_back(child_pid);
dup2(toA2[1], STDOUT_FILENO); //Sends output to 'toA2'
close(toA2[0]);
close(toA2[1]);
while (!std::cin.eof()) {
getline(std::cin, user_input); //Assumes there will be a space after the command
std::cout << user_input << std::endl;
}
// sends kill signal to all children processes
for (int i = 0; i < kids.size(); i++) {
int status;
kill(kids[i], SIGTERM);
waitpid(kids[i], &status, 0);
}
return 0;
}
程序rgen(c ++):
...
int main(int argc, char** argv) {
........
// removes pre-existing streets
std::cout << output << std::endl;
street_names.pop_back();
}
}
........
//Outputs the 'a' command to add the streets for assignment 1
std::cout << output << std::endl;
std::cout << "g" << std::endl;
sleep(wait_sec);
}
return 0;
}
计划A1(python):
...
def main():
sys.stdout.write("From A1 forked process\n")
.....
sys.stdout.write("V " + str(len(vertex_list)) + "\n")
sys.stdout.write(str_edges + "\n")
if __name__ == '__main__':
main()
计划A2(c ++):
int main() {
std::string use_input = "NOPE";
std::cerr << "A2 is running" << std::endl;
std::cin >> use_input;
std::cout << "use_input[2] = " << use_input << std::endl;
while (!std::cin.eof()) {
getline(std::cin, user_input); //Assumes there will be a space after the command
std::istringstream iss(user_input);
iss >> command;
if (command == 'V') {
....
}
else if (command == 'E') {
...
iss >> edges;
std::cout << "V " << num_vert << std::endl;
std::cout << "E " << edges << std::endl;
...
}
else if (command == 's') {
...
iss >> str_vert >> end_vert;
....
std::cout << path;
std::cout << std::endl;
}
else {
std::cerr << "Error: Invalid command[a2]" << std::endl;
}
}
return 0;
}