Копируются ли потоки при вызове fork?

31

Если у меня есть программа, работающая с потоками и вызывающая в системе fork()на основе Unix, скопированы ли потоки? Я знаю, что виртуальная память для текущего процесса копируется 1: 1, чтобы новый процесс порождался. Я знаю, что потоки имеют свой собственный стек в виртуальной памяти процесса. Таким образом, хотя бы стек потоков тоже должен быть скопирован. Тем не менее, я не знаю, есть ли что-то еще для потоков, которые не находятся в виртуальной памяти и, следовательно, НЕ копируются. Если нет, два процесса совместно используют потоки или они являются независимыми копиями?

Жан-Батист Юнес
источник

Ответы:

29

Нет.

Темы не копируются fork(). Спецификация POSIX гласит (подчеркнуть, это мое):

fork - создайте новый процесс

Процесс должен быть создан с одним потоком . Если многопоточный процесс вызывает fork (), новый процесс должен содержать реплику вызывающего потока и всего его адресного пространства, возможно, включая состояния мьютексов и других ресурсов. Следовательно, чтобы избежать ошибок, дочерний процесс может выполнять только асинхронно-безопасные операции до тех пор, пока не будет вызвана одна из функций exec.

Чтобы обойти эту проблему, существует pthread_atfork()функция, чтобы помочь.

Жан-Батист Юнес
источник
7

человек вилка :

Дочерний процесс создается с помощью одного потока, который называется fork (). Все виртуальное адресное пространство родительского объекта реплицируется в дочернем объекте, включая состояния мьютексов, переменных условий и других объектов pthreads; использование pthread_atfork (3) может быть полезно для решения проблем, которые это может вызвать.

kaylum
источник
Но это кажется странным: зачем копировать потоки в потоке процесса, вызывающего fork, если фактические потоки (которые я не знаю, содержат хранилище где-то еще, кроме виртуальной памяти)?
Ну, почему это совсем другой вопрос. Я не знаю оригинальных дизайнерских решений, которые привели к этой реализации. Если вы заинтересованы, вы должны задать это как отдельный вопрос.
Кайлум
@ Dip, но стек других потоков не копируются, кто так сказал?
Жан-Батист Юнес
1
@ Jean-BaptisteYunès В системах Unix существует структура, представляющая виртуальную память для процесса. Это тот, который скопирован. Не только куча, но и bss
6
Вы получаете все пространство памяти - и, следовательно, стеки всех потоков. вам это нужно, потому что нет ограничений на то, куда указывают указатели, находящиеся в стеке (или статической памяти), доступные остальному потоку, - они вполне могут указывать на данные, которые жили в стеке какого-то потока в исходном процессе
davidbak
4

От Open Group Base спецификации Выпуск 7, 2018 Edition, вилка :

Процесс должен быть создан с одним потоком. Если многопоточный процесс вызывает fork () , новый процесс должен содержать реплику вызывающего потока и всего его адресного пространства, возможно, включая состояния мьютексов и других ресурсов. Следовательно, чтобы избежать ошибок, дочерний процесс может выполнять только асинхронно-безопасные операции до тех пор, пока не будет вызвана одна из функций exec .

Когда приложение вызывает fork () из обработчика сигнала, а любой из обработчиков fork, зарегистрированных pthread_atfork (), вызывает функцию, которая не безопасна для async-signal, поведение не определено.

Йен Эбботт
источник
-2

Первоначально «ответвление» было достигнуто путем записи задачи на диск, а затем вместо чтения в другом потоке (что было бы сделано, если поменять задачу на другой), путем изменения идентификатора задачи изображения, все еще находящегося в памяти, и продолжения с его выполнением (как новая задача). Это была очень простая модификация базового механизма переключения задач, когда только одна задача занимала бы оперативную память одновременно.

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

Горячие лижет
источник
Любопытно, почему за это проголосовали. Это способ, которым Unix сделал это.
Hot Licks
Это интересная идея, но где упоминаются темы? Не похоже на ответ для меня.
Wastl