Чи потоки копіюються під час виклику вилки?


31

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

Відповіді:


29

Ні.

Нитки не скопійовані fork(). Специфікація POSIX говорить (наголос - це моє):

fork - створити новий процес

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

Щоб обійти цю проблему, існує pthread_atfork()функція, яка допомагає.


7

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

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


Але це здається дивним: чому б стек для потоків у процесі виклику вилки копіювався, якщо фактичні потоки (які я не знаю, містять сховище десь крім віртуальної пам'яті)?

Ну чому це зовсім інше питання. Я не знаю оригінальних дизайнерських рішень, які призвели до цієї реалізації. Якщо ви зацікавлені, вам слід задати це як окреме запитання.
кайлум

@dip, але стек інших потоків не копіюється, хто це сказав?
Жан-Батист Юньєс

1
@ Jean-BaptisteYunès У системах Unix існує структура, що представляє віртуальну пам'ять для процесу. Це одне скопійоване. Не лише купа та bss

6
ви отримуєте весь простір пам'яті - а отже, і стеки всіх потоків. вам це потрібно, тому що немає обмежень на те, куди вказують покажчики, що живуть у стеці (або статичній пам'яті), доступній для решти потоку - вони могли б дуже добре вказувати на дані, що живуть у стеці якогось потоку в початковому процесі
davidbak

4

Із специфікацій бази відкритої групи випуск 7, 2018 року вилки :

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

Коли програма викликає fork () від обробника сигналу та будь-якого з оброблювачів виделки, зареєстрованих pthread_atfork (), викликає функцію, яка не є безпечною для сигналу асинхронізації, поведінка не визначена.


-2

Спочатку "вилка" була досягнута записом завдання на диск, а потім, а не читанням в іншій потоці (що було б зроблено, якщо поміняти завдання на інший), змінивши ідентифікатор завдання зображення, що зберігається в пам'яті, і продовжуючи з його виконанням (як нове завдання). Це була дуже проста модифікація основного механізму комутації завдань, де лише одне завдання займало б оперативну пам'ять за один раз.

Звичайно, по мірі того, як управління пам'яттю стало більш детальним, ця схема була модифікована відповідно до нового середовища.


Цікаво, чому це було знято. Ось так це зробив Unix.
Гарячі виливки

Це цікаве розуміння, але де в ньому згадуються теми? Це не схоже на мене відповідь.
wastl
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.