尝试使用 execp、dup2 和管道实现 shell,挂起或"bad file descriptor"



我正在尝试用c++实现一个带有管道的shell。我有命令在工作,但一旦管道介入,事情就会停止工作。我会告诉你我的意思。这是代码:

int inPipe[2];
int outPipe[2];
pipe(inPipe);
pipe(outPipe);
int std_in = dup(0);
int std_out = dup(1);
std::for_each(cmds.begin(), cmds.end(), [&](Command command){
//printf("Executing [%s] n", command.args[0].c_str());
auto pid = fork();
if(pid==-1) {
std::cerr << "Could not forkn";
return;
}
if (pid==0) {
//std::cout << "Childn";
if(command.inFile == "none") {
printf("In, none.n");
dup2(std_in, 0);
close(std_in);
}
else if(command.inFile == "pipe") {
printf("In, pipe.n");
dup2(inPipe[0], 0);
close(inPipe[0]);
}
if(command.outFile == "none") {
printf("Out, none.n");
dup2(std_out, 1);
close(std_out);
}
else if(command.outFile == "pipe") {
printf("out, pipe.n");
dup2(outPipe[1], 1);
close(outPipe[1]);
}
const char* name = command.args[0].c_str();
char** args = new char*[command.args.size()];
for(int i=0; i<command.args.size(); i++) {
args[i] = new char[command.args[i].size()];
strcpy(args[i], command.args[i].c_str());
}
execvp(name, args);
exit(errno);
}
else {
//std::cout << "Parentn";
int status;
auto before = std::chrono::system_clock::now();
dup2(outPipe[0], inPipe[0]);
dup2(outPipe[1], inPipe[1]);
close(outPipe[0]);
close(outPipe[1]);
pipe(outPipe);
waitpid(pid, &status, 0);

auto after = std::chrono::system_clock::now();
std::chrono::duration<double> ptime = after-before;
elapsed_time = elapsed_time + ptime.count();
}
});

当我运行单管命令时,就像一个简单的"ls",它工作得很好。然而,如果我使用ls|sort,它会给出以下错误消息:

ls: cannot access : No such file or directory

然后一直挂到我离开那里。我认为挂起的原因是我不知何故对管道处理不当(没有关闭管道),但我不知道该把它放在哪里或放多少次。我认为"无法访问"是因为我在能够以某种方式调用ls之前丢失了std_in。我对几乎所有这些函数(dup2、fork、execp、pipe等)都是新手,所以我觉得我的猜测和检查更像是6轮俄罗斯轮盘赌。

不管怎样,我们非常感谢您的帮助。谢谢

检查变量名称和Args,其中一个值可能是NULL

最新更新