我有这个方法:
int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc) {
std::cout << "Building Pipe...\ncmd1: " << cmd1 << "\n cmd2: " << cmd2 << "\n";
int *pipefd = new int[2];
if (pipe(pipefd) < 0) {
std::cerr << "There was an error setting up the pipe.\n";
return -1;
}
pid_t cpid1 = fork();
std::cout << "First process forked, cpid: " << cpid1 << " - Process " << getpid() << "\n";
switch (cpid1) {
case -1:
std::cerr << "There was an error forking the process.\n";
return -1;
break;
case 0: // this is the part that isn't executing
std::cout << "Dup2 return: " << dup2(pipefd[1], 1) << "\n";
std::cout << "Process " << getpid() << " duped and about to exec.\n";
execvp(cmd1.c_str(), argv1);
std::cout << "Process " << getpid() << " about to exit.\n";
_exit(0);
break;
default:
pid_t cpid2 = fork();
switch (cpid2) {
case -1:
std::cerr << "There was an error forking the process.\n";
return -1;
break;
case 0:
dup2(pipefd[0], 0);
std::cout << "Process " << getpid() << " duped and about to exec.\n";
execvp(cmd2.c_str(), argv2);
_exit(0);
break;
default:
if (conc) {
} else {
int status1, status2;
std::cout << "Process " << getpid() << " about to wait.\n";
waitpid(cpid1, &status1, 0);
waitpid(cpid2, &status2, 0);
}
break;
}
}
delete[] pipefd;
return 0;
}
我已经添加了打印语句,仅用于调试。但是,当此方法运行时,这就是打印的内容。
Building Pipe...
cmd1: cat
cmd2: wc
First process forked, cpid: 1454 - Process 1453
First process forked, cpid: 0 - Process 1454
Process 1453 about to wait.
Process 1455 duped and about to exec.
进程1454,即分叉的第一个进程,在创建消息后立即打印该消息。但是,它从不打印来自switch语句的任何消息,并且从不执行指定的程序(在本例中为cat)。这个过程并不像僵尸那样流连,它只会消失。结果,第二个子进程挂起,实际上从未做过任何事情。
(另外,只是添加,我知道我还没有添加所有适当的错误处理功能,但功能还没有完成)。
答案 0 :(得分:2)
您没有看到switch语句中的消息,因为它们已写入管道。尝试将std::cout
替换为std::cerr
。
答案 1 :(得分:1)
管道在检测到EOF时结束,为此你必须在重复它后关闭不需要的描述符(在子项和父项中):
close(pipefd[0]);
close(pipefd[1]);
此外,请始终检查execvp
的返回值,您可能在argv中出错:
if (execvp(cmd1.c_str(), argv1) == -1) {
// check errno here
}
此外,请务必以 nullptr 作为最后一个元素结束argv, argv [0] 必须是命令本身。原型:
int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc)
...让我觉得你没有提供第一个元素( argv [0] = cmd1 )。如果你在 argv 中拥有它,你就不需要为函数build_pipe_and_call
提供额外的值( cmdX )。
请注意,如果execvp
运行良好,您将永远无法访问程序中的后续代码,因此您无法按照预期看到某些消息:
execvp(cmd1.c_str(), argv1);
std::cout << "Process " << getpid() << " about to exit.\n"; // if execvp didn't fail, it's never reached
一旦你复制了它,也要小心使用 std :: cout ,如@larpico answered