Как я могу узнать, просит ли ребенок вводить stdin?Как мне сказать это, чтобы остановить это? - PullRequest
6 голосов
/ 16 февраля 2012

В bash, когда я запускаю команду типа wc & или cat &, которая сразу требует стандартного значения, она немедленно возвращается с

[1] + Stopped cat

Как этодостигнуто?Как мне остановить программу, которую я запустил с exec, и как мне узнать, как остановить эти программы?Есть ли какой-нибудь способ сказать, что эти программы хотят стандартного ввода?

Спасибо!

PS Кроме того, что такое + о?Я всегда задавался вопросом, но это действительно трудно гуглить ...

Ответы [ 4 ]

2 голосов
/ 16 февраля 2012

[Отредактировано - см. Другие ответы для ответа на главный вопрос]

Знак + просто относится к текущему заданию . Каждый конвейер команд (например, foo | bar | baz) является заданием, на которое можно ссылаться, используя jobspec , начинающийся с символа %. %1 - это задание № 1, %+ - текущее задание, а %- - предыдущее задание.

Подробнее о заданиях см. В разделе Управление заданиями руководства Bash.

2 голосов
/ 16 февраля 2012

Если вы хотите, чтобы порожденные программы работали аналогично тому, как работает оболочка, позвоните setpgrp() после разветвления вашего ребенка. Это заставит фоновую программу работать в своей собственной группе процессов и, следовательно, иметь отдельный tty. Когда он пытается выполнить ввод / вывод на консоль, он будет получать сигналы SIGTTIN или SIGTTOU. Поведение SIGTTIN или SIGTTOU по умолчанию останавливает процесс точно так же, как SIGSTOP.

Как родитель, вы можете узнать, остановили ли вы дочерние процессы, используя waitpid() и WUNTRACED.

1 голос
/ 16 февраля 2012

Страница справочника setpgid() объясняет, как это работает:

Сеанс может иметь управляющий терминал.В любое время одна (и только одна) из групп процессов в сеансе может быть приоритетной группой процессов для терминала;остальные группы процессов находятся в фоновом режиме.Если из терминала генерируется сигнал (например, ввод ключа прерывания для генерации SIGINT), этот сигнал отправляется в группу процессов переднего плана.(См. termios(3) для описания символов, которые генерируют сигналы.) Только терминальная группа процессов может read(2) из терминала;если группа фоновых процессов пытается read(2) от терминала, то группе отправляется сигнал SIGTSTP, который приостанавливает его.Функции tcgetpgrp(3) и tcsetpgrp(3) используются для получения / установки группы процессов переднего плана управляющего терминала.

Итак, вы хотите сделать следующее:

  1. Когда вы создаете новый конвейер, вызовите setpgid(), чтобы поместить все элементы конвейера в новую группу процессов (с PID первого процесса в конвейере в качестве PGID).

  2. Используйте tcsetpgrp() для управления тем, какая группа процессов находится на переднем плане - если вы помещаете конвейер в фоновом режиме с помощью &, вы должны сделать собственную группу процессов оболочки приоритетной группой процессов.

  3. Вызовите waitpid() с флагами WNOHANG и WUNTRACED, чтобы проверить состояние дочерних процессов - это сообщит вам, когда они остановятся на SIGTSTP, что позволит вамнапечатать сообщение, как это делает bash.

0 голосов
/ 16 февраля 2012

Вы можете использовать system("command &") в разветвленном дочернем процессе, а затем вручную завершить его, если нет ограничений по времени и приоритетам.

...