Как Bash (и другие оболочки) обрабатывают отключение STDIN, когда `bg` останавливает процесс? - PullRequest
0 голосов
/ 03 декабря 2018

Я пишу свою собственную оболочку и у меня есть поддержка управления заданиями [1] (сродни jobs).Я могу остановить процессы, возобновить их на переднем плане, а также в фоновом режиме [2].Все это в основном работает, как и ожидалось - по крайней мере, с точки зрения пользователя.

Однако проблема, с которой я сталкиваюсь, заключается в том, что при возобновлении работы в фоновом режиме любые приложения, которые читают из STDIN, будут конкурировать с readline (на самом деле я написал свойсобственный readline API, по причинам, выходящим за рамки этого вопроса), и это нарушает удобство использования оболочки.

Я допускаю, что такие случаи довольно редки, но я понимаю, что обычно должны происходить любые фоновые процессы, которыетребует чтения из STDIN [3] и посылает сигнал SIGTTIN [4].

Моя проблема в том, как мне следить за тем, чтобы приложения считывали из STDIN - чтобы я мог отправлять SIGTTIN при необходимости?

Вот где мои исследования зашли в тупик.Поэтому меня интересует, как другие оболочки справляются с такой проблемой.

Ниже приведены некоторые ссылки, которые помогут объяснить, что я пытаюсь сделать в случае, если мое описание выше не очень понятно:

[1] https://en.wikipedia.org/wiki/Job_control_(Unix)#Overview

[2] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bg.html

[3] https://en.wikipedia.org/wiki/Job_control_(Unix)#Implementation

[4] https://en.wikipedia.org/wiki/Signal_(IPC)#SIGTTIN

1 Ответ

0 голосов
/ 03 декабря 2018

Мое понимание:

  • Обычно оболочкой является лидер сеанса, который выделяет управляющий терминал.
  • Каждое задание (может иметь несколько процессов, например ls | wc -l) - это процессgroup.
  • Только управляющий pgrp может читать с управляющего терминала.(У fg pgrp может быть несколько процессов, и эти процессы МОГУТ одновременно читать управляющий termianl.)
  • Оболочка вызывает tcsetpgrp() для установки pgrp на переднем плане (например, когда мы начинаем новое задание, илипоместите задание bg обратно в fg с помощью fg).
  • Ядро (драйвер tty) отправляет SIGTTIN в фоновый процесс, который пытается прочитать с управляющего терминала.
  • Оболочка не знает, когда процесс будет читать с управляющего терминала.Вместо этого оболочка отслеживает изменение статуса задания.Когда процесс останавливается SIGTTIN, оболочка получает SIGCHLD, а затем может вызвать waitpid() для получения дополнительной информации.
...