gpt4 book ai didi

c++ - 在 C++ : Why is a blank line entering getline after piping? 中编码管道 "|"

转载 作者:行者123 更新时间:2023-11-30 03:17:45 25 4
gpt4 key购买 nike

我正在编写模拟 shell,目前正在使用 dup2 编写管道代码。这是我的代码:

bool Pipe::execute() {
int fds[2]; //will hold file descriptors
pipe(fds);
int status;
int errorno;
pid_t child;
child = fork();

if (-1 == child) {
perror("fork failed");
}
if (child == 0) {
dup2(fds[1], STDOUT_FILENO);
close(fds[0]);
close(fds[1]);
this->component->lchild->execute();
_exit(1);
}
else if (child > 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
close(fds[1]);
this->component->rchild->execute();
waitpid(child, &status, 0);
if ( WIFEXITED(status) ) {
//printf("child exited with = %d\n",WEXITSTATUS(status));
if ( WEXITSTATUS(status) == 0) {
cout << "pipe parent finishing" << endl;
return true;
}
}
return false;
}
}

this->component->lchild->execute();this->component->rchild->execute();运行 execvp在相应的命令上。我已经通过在父进程中打印出一条语句来确认每一个都返回了。然而,在我的Pipe::execute() ,似乎子进程没有完成,因为从未打印父进程中的 cout 语句,并且在提示 ( $) 初始化后出现段错误(见图)。这是每次执行后初始化提示的主要功能:

int main()
{
Prompt new_prompt;
while(1) {
new_prompt.initialize();
}
return 0;
}

这里是 initialize()功能:

void Prompt::initialize()
{
cout << "$ ";
std::getline(std::cin, input);

parse(input);
run();
input.clear();
tokens.clear();
fflush(stdout);
fflush(stdin);
return;
}

好像ls | sort运行正常,但是当提示被初始化时,一个空行被 getline 读入输入。我试过使用 cin.clear()、cin.ignore 以及上面的 fflush 和 clear() 行。这个空白字符串被“解析”,然后是 run()函数被调用,它试图解引用一个空指针。关于为什么/在哪里将此空白行输入到 getline 中的任何想法?我该如何解决这个问题?谢谢!

更新:管道中的父进程现在正在完成。我还注意到我的 I/O 重定向类( >< )也遇到段错误。我认为我没有正确刷新流或关闭文件描述符...

这是我的 execute() lchild 和 rchild 的函数:

bool Command::execute() {
int status;
int errorno;
pid_t child;
vector<char *> argv;
for (unsigned i=0; i < this->command.size(); ++i) {
char * cstr = const_cast<char*>(this->command.at(i).c_str());
argv.push_back(cstr);
}
argv.push_back(NULL);
child = fork();
if (-1 == child) {
perror("fork failed");
}
if (child == 0) {
errorno = execvp(*argv.data(), argv.data());
_exit(1);

} else if (child > 0) {
waitpid(child, &status, 0);
if ( WIFEXITED(status) ) {
//printf("child exited with = %d\n",WEXITSTATUS(status));
if ( WEXITSTATUS(status) == 0) {
//cout << "command parent finishing" << endl;
return true;
}
}
return false;
}
}

最佳答案

这是错误:

else if (child > 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
close(fds[1]);
this->component->rchild->execute();

您正在为 parent 关闭 stdin,而不仅仅是正确的 child 。在此之后,父进程的标准输入与右子进程的标准输入相同。

之后

std::getline(std::cin, input);

尝试读取左 child 的输出,而不是原始的标准输入。到那时,左边的 child 已经完成,管道的那一端已经关闭。这使得读取 stdin 失败,并使 input 保持其原始状态不变。

编辑:您的设计有一个小缺陷和一个大缺陷。小缺陷是您不需要 Pipe::execute 中的分支。主要缺陷是 child 应该是重定向流并关闭描述符的人。

只需通过 fork() 传递输入和输出参数,让 child dup2 这些。不要忘记让它也关闭不相关的管端。如果你不这样做,左 child 将完成但它的输出管道将继续存在于其他进程中。只要该描述符的其他拷贝存在,正确的 child 在读取其管道末端时永远不会得到 EOF - 并且永远是周 block 。

关于c++ - 在 C++ : Why is a blank line entering getline after piping? 中编码管道 "|",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55214615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com