Intereting Posts
почему printf ведет себя по-разному, когда мы пытаемся напечатать символ как float и как шестнадцатеричный? Ошибка синтаксиса в инструкции INSERT INTO c openmp параллельно внутри параллельной области Конец вывода скрипта перед заголовками Apache 2.4 Error Do-s и Don’t-s для арифметики с плавающей запятой? Как возможно, что BITWISE AND операция требует больше процессорных часов, чем операция ARITHMETIC ADDITION в программе на C? Как процесс, выполняющийся в Linux, может определить, как долго он был приостановлен? Добавить таймаут для getchar () Остановка getline в C Уродливая Макро Интерпретация (всего 1 строка) Динамическое изменение размера массива строк select () не отвечает на запись на / dev / input / mice C Символьные указатели Почему Eclipse CDT говорит: «Синтаксическая ошибка», но компиляция не проблема безопасный метод для ожидания завершения всех обратных вызовов таймера таймера

Управление трубопроводами и процессами

Я работаю над крошечной оболочкой (tsh), реализованной в C (это назначение). Одна часть задания принадлежит PIPING. Мне нужно передать вывод команды другой команде. например: ls -l | sort ls -l | sort

Когда я запускаю оболочку, каждая команда, которую я выполняю на ней, обрабатывается дочерним процессом, который он порождает. После того, как ребенок закончит, возвращается результат. Для трубопроводов я сначала хотел реализовать пример с кодировкой, чтобы проверить, как он работает. Я написал метод, который частично работает. Проблемы возникают, когда я запускаю команду pipe, после завершения дочернего процесса вся программа завершает работу с ней! Очевидно, что я неправильно обрабатываю сигнал дочернего процесса (ниже приведен код метода).

Мой вопрос:

EDIT: Во время запуска этого кода я получаю результат дважды. не знаю, почему он работает дважды, там нет петли.

Вот мой код:

 pid_t pipeIt(void){ pid_t pid; int pipefd[2]; if(pipe(pipefd)){ unix_error("pipe"); return -1; } if((pid = fork()) <0){ unix_error("fork"); return -1; } if(pid == 0){ close(pipefd[0]); dup2(pipefd[1],1); close(pipefd[1]); if(execl("/bin/ls", "ls", (char *)NULL) < 0){ unix_error("/bin/ls"); return -1; }// End of if command wasn't successful }// End of pid == 0 else{ close(pipefd[1]); dup2(pipefd[0],0); close(pipefd[0]); if(execl("/usr/bin/tr", "tr", "e", "f", (char *)NULL) < 0){ unix_error("/usr/bin/tr"); return -1; } } return pid; }// End of pipeIt 

Да, shell должна использовать fork для выполнения каждого subprocessа. Помните, что когда вы вызываете одно из семейств функций execve() , он заменяет текущий образ процесса на exec’ed. Ваша shell не может продолжать обрабатывать дальнейшие команды, если она непосредственно выполняет subprocess, потому что после этого она больше не существует (кроме как subprocess).

Чтобы исправить это, просто fork() снова в ветви pid == 0 и выполните команду ls в этом дочернем элементе. Не забудьте wait() для обоих (всех) дочерних процессов, если вы не хотите, чтобы конвейер выполнялся асинхронно.

Да, вам нужно вызывать fork по крайней мере дважды, один раз для каждой программы в конвейере. Помните, что exec заменяет образ программы текущего процесса, поэтому ваша shell перестает существовать с момента запуска сортировки или (tr).