Нитки проти (роздвоєні) процеси


9

Програми Linux зазвичай розщеплюються, а потім виконують exec (з execve ()), але додатки Java та певні MPM-версії Apache використовують нитку. Якщо forking використовує fork + exec для нерестування процесу, то яка версія високого рівня для нитки? Як формуються нитки JVM або Worker MPM?


2
Перевірте Stackoverflow. Є кілька питань і запитань, які пояснили частину цього.
Хенк Лангевельд

Відповіді:


13

Ідея, що стоїть за потоками та процесами, приблизно однакова: ви розщеплюєте шлях виконання. Інакше нитки та процеси відрізняються в таких речах, як пам'ять. Тобто процеси мають різний простір VM, в той час як потоки діляться всіма тим, що існувало до розколу.

В основі роботи як нарізання різьби, так і викрутки за допомогою виклику clone () (man 2 clone):

На відміну від fork (2), clone () дозволяє дочірньому процесу обмінюватися частинами свого контексту виконання з процесом виклику, таким як простір пам'яті, таблиця дескрипторів файлів і таблиця обробників сигналів. (Зверніть увагу, що на цій сторінці керівництва "процес виклику" зазвичай відповідає "батьківському процесу". Але див. Опис CLONE_PARENT нижче.)

Основне використання clone () - це реалізація потоків: декількох потоків управління в програмі, які працюють одночасно в спільному просторі пам'яті.

Відмінності походять від прапорів, які передаються до clone (). Як видно зі сторінки man, вилка та нитка - це лише набір заздалегідь заданих параметрів для клонування (). Однак можна також робити спеціальні речі з ним.


1
Ум? Що? Будь ласка, перечитайте майже кожну книгу з цієї теми, оскільки окремий простір пам'яті для процесів - це щось велике. Також допомагає "зловити" код, який виходить з ладу, тоді як ядро ​​просто знищить процес, коли окремий потік переходить "haywire / trespasses".
0xC0000022L

3
@ 0xC0000022L ваш аргумент не суперечить відповіді, як мені здається.
Руслан

1
@Ruslan: Я прошу відрізнятись: "Ідея [...] приблизно однакова"? Ідея, що стоїть за нитками, справді є одночасною, але для процесів це зовсім інша історія.
0xC0000022L

4
@ 0xC0000022L Ви пропустили важливу частину відповіді V13: "Ви розщедрили шлях виконання" - питання про те, як породжуються потоки, а не в чому різниця між потоками та процесами
Izkata

@Izkata: зовсім не так. Я просто вважаю, що це неправильне твердження.
0xC0000022L

8

Більшість багатопроцесорних операційних систем (ОС), які не працюють Unix, використовують дзвінок "spawn ()" або щось подібне для створення нового процесу ОС або потоку управління. Spawn (), як правило, дуже складний дзвінок, з великою кількістю варіантів і безліччю накладних витрат. Однією з нововведень Unix було створення набагато нижчого режиму створення процесів - fork (). Unix подбав про безліч необхідних варіантів spawn (), дозволяючи довільну кількість обробки перед другою половиною spawn (), за допомогою exec ().

Оскільки Unix та його варіанти використовувались все більше і більше, було виявлено корисним створення і використання низьких накладних процесів. Насправді його використовували так багато, що люди хотіли ще нижчих накладних способів створення процесів, і так народилася ідея «ниток». Спочатку нитками повністю оброблявся процес створення (і такі програми, як JVM, можуть це робити за допомогою "зелених ниток"); але обробка багатопотокового планування складна і часто робиться неправильно. Таким чином, існує більш простий проміжний спосіб робити потоки, де ОС обробляє планування, але деяка накладні витрати зберігаються (зазвичай) спільним адресним простором між потоками.

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


1
"обробка багатопотокового планування складна і часто робиться неправильно". Реалізація потоків користувальницького простору не є проблемою. Проблема з потоками користувальницького простору полягає в тому, що якщо потік блокує sscall, всі потоки блокуються. Єдиний спосіб уникнути цього - це використання ниток системного рівня.
Бакуріу

1
Цікаво, що Windows не включила цю інновацію Unix: вона не має CreateProcess()нічого подібного fork().
Руслан

2
@Bakuriu - шукайте будь-яку з багатьох статей про створення багатопроцесорних планувальників, збереження справедливості, уникнення голоду, керування пріоритетами тощо. Реалізація потоків користувальницького простору, як ви кажете, не є проблемою. Планування нетривіальних прикладів складно.
mpez0

@Ruslan: можна роздрібнитись на Windows, це просто не частина API Win32. Прочитайте "Нативний API Windows NT / 2000" від Неббетта. У нього є реалізація, яка імітує fork().
0xC0000022L

3

Нитки та розгортання - це фактично дві різні концепції, обидва з яких існують в системах Unix / Linux (і обидва вони можуть бути використані в C / C ++).

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

Нитки використовуються для паралелізму (нагадайте, що батько чекає на дитину, як правило, у роздвоєній програмі). Потік, такий як pthread в C / C ++ (пошук у Google), буде працювати паралельно основного процесу та може ділитися глобальними змінними та глобальними функціями з оригінальною програмою. Оскільки потоки Java поводяться аналогічно, я б уявив, що вони діють більше, як ці нитки, ніж як процес розщеплення.

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

РЕДАКТИКА №1

Ознайомтеся з цими прикладами того, як вилки та нитки можна викликати та використовувати. Зверніть увагу на поведінку функцій exec та їх вплив на основну програму.

http://www.jdembrun.com:2352/computerScience/forkVSthread.zip


2
Вилка (з exec або без) може використовуватися і для паралелізму. Я не впевнений, що ви маєте на увазі під "exec-функціями, що закривають процес, який викликав їх, коли вони закінчуються", а exec давно закінчений, коли процес закінчується. Також pthreadє API, а не реалізація потоку.
Мат

Щодо вилки, я цитую свого вчителя ОС. Відповідно до того, що він сказав нам, так, форкінг можна використовувати для запуску паралельно, але, якби він використовував функцію exec, це була б остання. Що стосується pthread, то він мав на увазі приклад.
jaredad7

Exec був би останнім викликом у коді абонента, а не останньою інструкцією роздвоєного процесу. Процес роздвоєння діятиме при виконанні коду exec'd.
Мат

Ваші коментарі спонукали мене перевірити ці речі. Я написав кілька програм c ++, які демонструють поведінку функцій exec та їх вплив на програми при використанні у fork vs. потоках. Перегляньте редагування вище.
jaredad7

Я боюся, що більшість людей не будуть намагатися завантажити це. Також ваші приклади не ілюструють цікавих відмінностей між моделями, які в основному стосуються спільного використання (або не) адресного простору.
Мат

1

І JVM, і Apache MPM покладаються на ядро ​​для власних потоків. Тобто вони використовують ОС для їх планування. Звичайно, обом потрібен власний API для відстеження речей.

У Stackoverflow вже є кілька питань, що стосуються цього:

  1. Рідні теми JVM , ознайомтеся з цією відповіддю для більш детальної інформації.

  2. Apache має два типи MPM: Prefork, з одним процесом на потік, і Worker, який обробляє декілька потоків: Apache MPM . Ознайомтесь із посиланням наcodebucket


1

Якщо forking використовує fork + exec для нерестування процесу, то яка версія високого рівня для нитки? Як формуються нитки JVM або Worker MPM?

Це специфічно для платформи, але в Linux і я б припустив, що багато інших сумісних з POSIX системами вони використовують локальну реалізацію pthreads , інтерфейсу API для користування. Наприклад:

#include <pthread.h>

pthread_t tid;
pthread_create(&tid, NULL, somefunc, NULL);

Починає новий потік виклику somefuncяк його перший пункт виконання.

Ви також можете створити нитки - відмінні від forks тим, що вони поділяють той самий глобальний простір пам’яті купи батьківського процесу, замість того, щоб отримувати його копію (але відзначте, що потоки виконуються з незалежною пам'яттю стека ) - із clone()системним викликом, на якому будується pthreads.

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