Подтвердить что ты не робот

Можно ли принять процесс?

Процесс A fork() процесс B.

Процесс A умирает, и поэтому init принимает B.

Наблюдатель создает процесс C.

Возможно ли, чтобы C принял B из init?


Обновление

Или было бы возможно, чтобы C принимал B непосредственно (когда A умирает), если C был создан до мертвого, без init, становясь промежуточным родителем B?


Update-1:

Также я был бы признателен за любые замечания о том, почему возможность принять процесс так, как я описал, будет плохой или трудно реализовать.


Update-2 - пример использования (родительский и дочерний элементы относятся к процессам):

У меня есть приложение, использующее родителя для управления целым рядом детей, которые полагаются на средство управления родителями. Для выполнения своей работы родитель полагается на уведомление о завершении дочернего процесса, которое выполняется посредством приема связанного сигнала SIGCHLD.

Если сам родитель умирает из-за какой-то случайности (включая segfaulting), мне нужно перезапустить всю "семью", так как теперь невозможно что-то инициировать на дочернем завершении (что также может быть связано с segfault).

В таком случае мне нужно сбить всех детей и выполнить полный перезапуск системы.

Возможный подход, чтобы избежать этой ситуации, состоял бы в том, чтобы иметь запасной процесс, который мог бы взять на себя роль мертвого родителя... - если он снова сможет получать сигналы дочерних элементов SIGCHLD!

4b9b3361

Ответ 1

Нет, это определенно невозможно. Это не могло быть реализовано ни без каких-либо неприятных условий гонки. Парни POSIX, которые делают эти API, никогда не создадут что-то с присущим им гоночным условием, поэтому даже если вас не беспокоит, ваше ядро ​​не получит его в ближайшее время.

Одна проблема заключается в том, что pids повторно используются (они скудный ресурс!), и вы не можете получить ручку или заблокировать ее; это просто номер. Итак, скажем, где-то в вашем коде у вас есть переменная, в которой вы помещаете pid процесса, который хотите повторно использовать. Затем вы вызываете make_this_a_child_of_me(thepid). Что будет тогда? Тем временем другой процесс, возможно, вышел и thepid изменился, чтобы ссылаться на какой-то другой процесс! К сожалению. Невозможно предоставить API make_this_a_child_of_me без большой перестройки процесса unix, обрабатывающего процессы.

Обратите внимание, что вся сделка с wait ing для дочерних pids заключается в том, чтобы предотвратить эту проблему: в таблице процессов все еще существует процесс зомби, чтобы предотвратить повторное использование pid. Затем родитель может ссылаться на своего ребенка своим pid, уверенным, что процесс не собирается выходить и повторно использовать дочерний pid. Если ребенок завершает работу, его pid зарезервирован, пока родитель не поймает SIGCHLD или не ждет его. После того, как процесс будет получен, его pid забирает сразу для других программ, чтобы начать использовать, когда они развиваются, но родитель гарантированно уже знает об этом.

Ответ на обновление: рассмотрим более сложную схему, в которой процессы возвращаются к следующему предку. Понятно, что это невозможно сделать в каждом случае, потому что вы часто хотите отказаться от ребенка, чтобы избежать зомби. init выполняет эту роль очень хорошо. Таким образом, есть какой-то способ для процесса указать, что он намерен либо принять, либо нет, его внуки (или ниже). Проблема с этим дизайном точно такая же, как и в первой ситуации: вы по-прежнему получаете условия гонки.

Если это будет сделано pid снова, то бабушка и дедушка представят себя в состоянии гонки: только родитель может получить pid, так что только родитель действительно знает, с каким процессом идет pid. Поскольку бабушка и дедушка не могут пожинать плоды, она не может быть уверена, что процесс внука не изменился с той, которую он намеревался принять (или отказаться, в зависимости от того, как будет работать гипотетический API). Помните, что на сильно загруженной машине ничего не прекращалось, когда процесс отнимался от процессора в течение нескольких минут, и в это время может измениться вся загрузка! Не идеально, но POSIX получил за него ответственность.

Наконец, предположим, что этот API не работает pid, но, как правило, говорит "отправьте всех внуков мне" или "отправьте их в init". Если он вызван после появления дочерних процессов, то вы получите условия гонки так же, как и раньше. Если он звонит раньше, то все это бесполезно: вы должны иметь возможность немного изменить структуру своего приложения, чтобы получить такое же поведение. То есть, если вы знаете, прежде чем начинать порождать дочерние процессы, которые должны быть родителями, почему вы не можете просто пойти вперед и создать их в правильном направлении? Трубы и IPC действительно способны выполнять всю необходимую работу.

Ответ 2

Нет никакого способа, которым вы могли бы принудительно выполнить Reparenting так, как вы описали.