- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写模拟 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/
我是一名优秀的程序员,十分优秀!