Я кодирую фиктивную оболочку, и сейчас я работаю над кодированием каналов с 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?и как мне решить это?Спасибо!
ОБНОВЛЕНИЕ: родительский процесс в конвейере завершается.Я также заметил, что я получаю ошибки seg также для моих классов перенаправления ввода / вывода (>
и <
).Я думаю, что я не сбрасываю поток или правильно закрываю файловые дескрипторы ...
Вот моя 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;
}
}