Ответ 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 действительно способны выполнять всю необходимую работу.