Я работаю над крошечной оболочкой (tsh), реализованной в C (это назначение). Одна часть задания принадлежит PIPING. Мне нужно передать вывод команды другой команде. например: ls -l | sort
ls -l | sort
Когда я запускаю оболочку, каждая команда, которую я выполняю на ней, обрабатывается дочерним процессом, который он порождает. После того, как ребенок закончит, возвращается результат. Для трубопроводов я сначала хотел реализовать пример с кодировкой, чтобы проверить, как он работает. Я написал метод, который частично работает. Проблемы возникают, когда я запускаю команду pipe, после завершения дочернего процесса вся программа завершает работу с ней! Очевидно, что я неправильно обрабатываю сигнал дочернего процесса (ниже приведен код метода).
Как работает управление процессом с помощью pipe ()? если я запустил команду ls -l | sort
ls -l | sort
создает ли дочерний процесс для ls -l
и другой процесс sort
? Из примеров трубопроводов, которые я видел до сих пор, создается только один процесс (fork ()).
Когда обрабатывается вторая команда ( sort
из нашего примера), как я могу получить ее идентификатор процесса?
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).