【发布时间】:2019-03-18 03:59:57
【问题描述】:
我正在编写一个模拟 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 重定向类(> 和<)也出现了段错误。我想我没有正确刷新流或关闭文件描述符......
这是我用于 lchild 和 rchild 的 execute() 函数:
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;
}
}
【问题讨论】:
-
它应该像shell终端提示符 - 它等待用户输入
-
不管实际上是什么导致了空白行,我建议在运行时使用程序 not segfault - 尽快执行检查并给出错误,而不是 segfaulting .
-
更新后是一个不同的问题,需要其他部分的代码。我怀疑那里有类似的问题,但没有看到代码就无法判断
-
@MichaelVeksler 我添加了执行功能。这个函数也应该适用于其他命令类型,所以我害怕关闭其中的一个流(例如,如果我运行 echo hello && pwd,我不想关闭任何东西 - 只有当我使用重定向)
标签: c++ pipe fork getline dup2