Насколько я знаю, когда vfork
вызывается, дочерний процесс использует то же адресное пространство, что и у родительского, и любые изменения, сделанные дочерним процессом в переменных родителя, отражаются на родительский процесс. Мои вопросы:
- Когда порождается дочерний процесс, приостанавливается ли родительский процесс?
- Если да, то почему?
- Они могут работать параллельно (как потоки)? В конце концов, и потоки, и процессы вызывают одну и ту же
clone()
функцию.
После небольшого исследования и поиска в Google, я обнаружил, что родительский процесс на самом деле не приостановлен, но вызывающий поток приостановлен. Даже если это тот случай, когда дочерний процесс выполняет exit()
или exec()
, как родительский процесс узнает, что дочерний процесс завершился? И что будет, если мы вернемся из дочернего процесса?
sleep()
это реализовано.Я не программист Linux, но сталкиваясь с тем же вопросом сегодня, я сделал следующий тест:
Я собрал это с
g++ -pthread -o repro repro.cpp
и бегу с./repro
. Что я вижу в выводе, так это то, что все происходит одновременно в раундах: сначала все pthreads запускают vfork, затем все ждут секунду, затем "просыпаются" в реальности дочернего процесса, затем все дочерние элементы запускают exec (), а затем, наконец, все родители просыпаются вверх.Для меня это доказывает, что если один pthread вызывает vfork, то он не приостанавливает другие pthread - если он это сделал, то они не смогут вызывать vfork () до тех пор, пока не будет вызван exec ().
источник
sleep()
это реализовано. Наконец, это должен быть собственный вопрос, потому что это вопрос, а не ответ.Да.
Потому что родитель и потомок делят адресное пространство. В частности, адресное пространство стека. Если родитель попытается продолжить, он, вероятно, вызовет другую функцию и очистит стек вызовов дочернего процесса. Так что не работает, пока
exec()
или_exit()
На самом деле. Только вызывающая нить приостановлена. Смотри выше.
Это звонки
wait4()
. Но, скорее, вы спрашиваете, как родитель знает, чтобы продолжить. Это не так. Ядро снова запускает его, когда происходит одно из двух определенных событий.vfork()
возвращается в освобожденный фрейм стека, а следующийreturn;
- быстрый путь к неопределенному поведению.источник
«Однако не получается вернуться во время работы в контексте дочернего процесса из процедуры, которая вызвала vfork (), поскольку возможный возврат из vfork () затем вернется к уже не существующему фрейму стека».
Я не понимаю это буквально. Байты в области стека буквально не исчезают после каждой инструкции POP (или RETURN). Однако если вы вернетесь, продолжите работу и выполните инструкцию PUSH (или CALL), она заменит предыдущее значение в стеке.
Это всего лишь один яркий пример странных вещей, которые произойдут в общем, если вы позвоните,
vfork()
а затем сделаете что-нибудь, чтобы изменить какую-либо память вашего процесса.[Технически я предполагаю то же поведение, что и в Linux. Другие поведения vfork () были технически разрешены POSIX. Я не знаю, нашел ли кто-нибудь применение для технической гибкости POSIX, кроме как для обеспечения vfork (), который идентичен fork ()].
источник