Threads vs (Forked) Процессы

9

Приложения Linux, как правило, разветвляются затем на exec (с execve ()), но приложения Java и некоторые MPM Apache используют многопоточность. Если разветвляется, использует fork + exec для запуска процесса, какова высокоуровневая версия для многопоточности? Как JVM или Worker MPM порождают потоки?

Грегг Левенталь
источник
2
Проверьте Stackoverflow. Есть несколько вопросов и ответов, которые объяснили часть этого.
Хенк Лангевельд,

Ответы:

13

Идея потоков и процессов примерно одинакова: вы разветвляете путь выполнения. В противном случае потоки и процессы различаются в таких вещах, как память. Т.е. процессы имеют разное виртуальное пространство, а потоки разделяют все, что существовало до разделения.

В основе работы потоков и разветвления лежит вызов clone () (клон man 2):

В отличие от fork (2), clone () позволяет дочернему процессу обмениваться частями своего контекста выполнения с вызывающим процессом, такими как пространство памяти, таблица дескрипторов файлов и таблица обработчиков сигналов. (Обратите внимание, что на этой странице руководства «вызывающий процесс» обычно соответствует «родительскому процессу». Но см. Описание CLONE_PARENT ниже.)

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

Различия происходят от флагов, которые передаются в clone (). Как вы можете видеть из справочной страницы, fork и threading - это просто набор предопределенных параметров для clone (). Тем не менее, можно также сделать пользовательские вещи с ним.

V13
источник
1
Ммм? Какая? Пожалуйста, перечитайте почти каждую книгу по этой теме, потому что отдельное пространство памяти для процессов является чем-то большим. Также помогает «поймать» код, который дает сбой, тогда как ядро ​​просто уничтожит процесс, когда отдельный поток сходит с ума.
0xC0000022L
3
@ 0xC0000022L Ваш аргумент не противоречит ответу, как мне кажется.
Руслан
1
@Ruslan: Я позволю себе не согласиться: «Идея [...] примерно такая же»? Идея, лежащая в основе потоков, действительно параллельна, но для процессов это совсем другая история.
0xC0000022L
4
@ 0xC0000022L Вы пропустили важную часть ответа V13: «Вы разветвляете путь выполнения» - вопрос в том, как
порождаются
@Izkata: совсем нет. Я просто считаю, что это не правильное утверждение.
0xC0000022L
8

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

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

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

mpez0
источник
1
«Обработка многопотокового планирования сложна и часто выполнялась неправильно». Реализация потоков в пользовательском пространстве не является проблемой. Проблема с потоками пользовательского пространства заключается в том, что, если поток выполняет системный вызов, все потоки блокируются. Единственный способ избежать этого - использовать потоки системного уровня.
Бакуриу
1
Интересно, что в Windows не было этого нововведения Unix: в нем нет CreateProcess()ничего похожего fork().
Руслан
2
@Bakuriu - посмотрите любую из многих статей о построении многопроцессорных планировщиков, поддержании справедливости, избежании голодания, обработке приоритетов и т. Д. Реализация потоков в пользовательском пространстве не является, как вы говорите, проблемой. Планирование нетривиальных примеров сложно.
mpez0
@Ruslan: можно подключиться к Windows, он просто не является частью Win32 API. Прочтите «Windows NT / 2000 Native API» от Nebbett. У него есть реализация, которая имитирует fork().
0xC0000022L
3

Потоки и разветвления - это на самом деле две разные концепции, обе из которых существуют в системах Unix / Linux (и обе могут использоваться в C / C ++).

Идея fork () - это (очень по сути) создание отдельного процесса, который имеет тот же код выполнения, что и родительский процесс, и который начинает выполнение на линии ветвления. Цель использования вилок с функциями exec состоит в том, что функции exec закрывают процесс, который вызвал их, когда они заканчиваются. Таким образом, вы обычно выполняете форк, получая PID каждого процесса (child всегда равен 0), и заставляете родителя ждать, пока дочерний процесс завершит выполнение функции exec.

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

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

РЕДАКТИРОВАТЬ # 1

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

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

jaredad7
источник
2
Вилка (с или без exec) также может быть использована для параллелизма. Я не уверен, что вы подразумеваете под "функциями exec, закрывающими процесс, который вызвал их, когда они заканчиваются", exec давно закончил работу, когда процесс завершился. Также pthreadявляется API, а не реализация потока.
Мат
На развилке я цитирую своего учителя ОС. Согласно тому, что он сказал нам, да, разветвление можно использовать для параллельной работы, но, если оно использует функцию exec, это будет последним. Что касается pthread, то это был пример.
jaredad7
Exec будет последним вызовом в коде вызывающего, а не последней инструкцией разветвленного процесса. Разветвленный процесс будет жить при выполнении кода exec'd.
Мат
Ваши комментарии побудили меня проверить эти вещи. Я написал несколько программ на c ++, которые демонстрируют поведение exec-функций и их влияние на программы при использовании в forks против потоков. Пожалуйста, смотрите редактирование выше.
jaredad7
Боюсь, что большинство людей не будут загружать это. Также ваши примеры не иллюстрируют интересные различия между моделями, которые в основном связаны с разделением (или нет) адресного пространства.
Мат
1

И JVM, и Apache MPM полагаются на ядро ​​для собственных потоков. То есть они используют ОС для планирования их. Конечно, обоим нужен собственный API для отслеживания вещей.

Stackoverflow уже имеет несколько вопросов, касающихся этого:

  1. Собственные темы JVM , проверьте этот ответ для более подробной информации.

  2. Apache имеет два типа MPM: Prefork, с одним процессом на поток, и Worker, который обрабатывает несколько потоков: Apache MPM . Проверьте ссылку наcodebucket

Хенк Лангевельд
источник
1

Если разветвляется, использует fork + exec для запуска процесса, какова высокоуровневая версия для многопоточности? Как JVM или Worker MPM порождают потоки?

Это зависит от платформы, но в linux, и я бы предположил, что многие другие POSIX-совместимые системы используют локальную реализацию pthreads , API потоков пользователя. Например:

#include <pthread.h>

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

Запускает новый поток, вызывающий somefuncего в качестве первой точки выполнения.

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

лютик золотистый
источник