Хорошие вопросы. Идентификатор задания - это в основном просто оболочка. В ядре есть поддержка в виде сигналов, которые участвуют в управлении заданиями, и способ, которым ядро точно знает, в какие процессы отправлять сигналы управления заданиями.
Строго говоря, ответ на ваш первый вопрос заключается в том, что идентификатор задания - это просто создание оболочки. Он существует потому, что конвейер (или, редко, другая конструкция, сгруппированная в оболочку) может состоять из нескольких процессов, которые должны управляться как единое целое.
Чтобы ответить на ваш последний вопрос, оболочка запускает все процессы, выполнив сначала fork(2)
, а затем execve(2)
. Единственная разница с &
заключается в том, что оболочка не выполняет wait(2)
(или связанный вариант), и поэтому программа может продолжать работу «в фоновом режиме». На самом деле в Unix мало различий между передним и задним планами.
Группа процессов - это ассоциация, определяемая оболочками, так что ядро знает об одном «переднем» процессе, который обрабатывает набор различных «фоновых» процессов. Это главным образом важно для того, чтобы фоновые процессы генерировали сигнал, если они решат внезапно прочитать данные с терминала. (Возможно, такой терминал подключен к стандартному входу.) Это приведет к тому, что «задание» сгенерирует сигнал, а оболочка предложит пользователю что-то сделать.
Попробуйте (sleep 5; read x)&
и через 6 секунд введите return или что-то еще, чтобы оболочка проснулась. Вот когда ты видишь что-то вроде ...
[1] + Остановлен (сон 5; чтение х)
... и затем вы набираете fg
, чтобы вытащить его на передний план.
Изначально в Unix имелись конвейеры, и в нем было &
, но не было никакого способа переместить команду или конвейер между передним планом и фоном, и не было никакого способа помочь фоновому процессу, который внезапно решил прочитать стандартный ввод.
Управление заданиями и поддержка ядра были добавлены Биллом Джоем и другими в ранних версиях BSD и csh (1). Они были подобраны построчно коммерческим Unix и клонированы для аналогичного ядра Linux.
По вопросам о группах процессов и ps(1)
...
Для поддержки управления заданиями в оболочках состояние процесса ядра включает в себя идентификатор группы процессов и идентификатор сеанса. группа процессов и job - это одно и то же, но job number - это просто дескриптор, который составляет оболочка. Процесс является лидером сеанса, если идентификатор сеанса совпадает с pid, а процесс является лидером группы процессов, если pgid совпадает с pid. Я считаю, что с отпечатками +
, которые ps(1)
происходит нечто более тонкое. Каждый терминал знает, какова его группа процессов переднего плана, поэтому я считаю, что процесс получает +, если pid == pgid && (pgid - это передний план pg для своего управляющего терминала).
Таким образом, ядро сохраняет несколько элементов состояния: pid, pgid, sid, и процесс может иметь управляющий терминал, а терминал может иметь pgid переднего плана. Эти учетные данные в основном предназначены для поддержки управления заданиями, но также используются для отзыва доступа к терминалу при выходе пользователя из системы.