что - таблица процессов linux




Темы и процессы в Linux (9)

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

Поэтому мой вопрос заключается в том, что, столкнувшись с ситуацией, когда потоки и процессы могут обрабатываться довольно хорошо, следует ли использовать процессы или потоки? Например, если я писал веб-сервер, должен ли я использовать процессы или потоки (или комбинацию)?


Linux (и действительно Unix) дает вам третий вариант.

Вариант 1 - процессы

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

Вариант 2 - потоки

Создайте автономный исполняемый файл, который запускается с одним потоком и создает дополнительные потоки для выполнения некоторых задач

Вариант 3 - вилка

Это доступно только под Linux / Unix, это немного другое. Разветвленный процесс - это собственный процесс со своим собственным адресным пространством - нет ничего, что ребенок может (обычно) воздействовать на адресное пространство своего родителя или родного брата (в отличие от потока) - так что вы получите дополнительную надежность.

Однако страницы памяти не копируются, они копируются на запись, поэтому обычно используется меньше памяти, чем вы могли себе представить.

Рассмотрим программу веб-сервера, которая состоит из двух шагов:

  1. Чтение данных конфигурации и времени выполнения
  2. Подавать запросы на страницу

Если вы использовали потоки, шаг 1 будет выполнен один раз, а шаг 2 будет выполнен в нескольких потоках. Если вы использовали «традиционные» процессы, шаги 1 и 2 нужно будет повторять для каждого процесса, а память для хранения дубликатов данных конфигурации и времени выполнения. Если вы использовали fork (), вы можете сделать шаг 1 один раз, а затем fork (), оставив данные и конфигурацию в памяти, нетронутыми, не скопированными.

Таким образом, есть действительно три варианта.


Linux использует 1-1 поточную модель, с (для ядра) никакого различия между процессами и потоками - все это просто выполняемая задача. *

В Linux clone системного вызова клонирует задачу с настраиваемым уровнем совместного доступа, среди которых:

  • CLONE_FILES : совместно использовать одну и ту же таблицу дескриптора файла (вместо создания копии)
  • CLONE_PARENT : не устанавливайте отношения между родителями и getpid() между новой задачей и старым (в противном случае дочерний getppid() = родительский getpid() )
  • CLONE_VM : использовать одно и то же пространство памяти (вместо создания копии COW )

fork() вызывает clone( наименьший доступ ) и pthread_create() вызывает clone( большинство разделов ) . **

fork ing стоит чуть меньше pthread_create из-за копирования таблиц и создания сопоставлений COW для памяти, но разработчики ядра Linux попытались (и преуспели) в минимизации этих затрат.

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

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

* Упрощенный. CLONE_THREAD приводит к совместному CLONE_THREAD сигналов (для этого требуется CLONE_SIGHAND , который разделяет таблицу обработчика сигналов).

** Упрощенный. Существуют как SYS_fork и SYS_clone syscalls, но в ядре sys_fork и sys_clone - очень тонкие обертки вокруг одной и той же функции do_fork , которая сама по себе является тонкой оболочкой вокруг copy_process . Да, термины process , thread и task используются относительно взаимозаменяемо в ядре Linux ...


В моей недавней работе с LINUX стоит только знать библиотеки. Если вы используете потоки, убедитесь, что любые библиотеки, которые вы можете использовать в потоках, являются потокобезопасными. Это сожгло меня пару раз. В частности, libxml2 не является потокобезопасным. Его можно скомпилировать с помощью потоковой безопасности, но это не то, что вы получаете с установкой aptitude.


Другие обсудили эти соображения.

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


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

В современной Linux (2.6.x) разница в производительности между контекстным переключателем процесса по сравнению с потоком невелика (только материал MMU является дополнительным для потока). Существует проблема с общим адресным пространством, что означает, что ошибочный указатель в потоке может испортить память родительского процесса или другого потока в одном и том же адресном пространстве.

Процесс защищен MMU, поэтому ошибочный указатель просто вызовет сигнал 11 и не повредит.

Я бы вообще использовал процессы (не слишком много перераспределения контекста в Linux, но защита памяти из-за MMU), но pthreads, если мне понадобится класс планировщика в реальном времени, который представляет собой чашку чая.

Почему вы думаете, что потоки имеют такую ​​большую производительность в Linux? У вас есть данные для этого, или это просто миф?


Насколько тесно связаны ваши задачи?

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


Темы -> Темы разделяют пространство памяти, это абстракция процессора, он легкий. Процессы -> Процессы имеют собственное пространство памяти, это абстракция компьютера. Для параллелизации задачи вам необходимо абстрагироваться от процессора. Однако преимущества использования процесса над потоком - это безопасность, стабильность, в то время как поток использует меньшую память, чем процесс, и предлагает меньшую задержку. Примером с точки зрения Интернета будет хром и firefox. В случае Chrome каждая вкладка - это новый процесс, поэтому использование памяти хром выше, чем firefox, в то время как безопасность и стабильность предоставляются лучше, чем firefox. Безопасность здесь обеспечивается хром лучше, так как каждая вкладка представляет собой новый процесс, вкладка не может перескакивать в пространство памяти данного процесса.


Чтобы еще больше усложнить ситуацию, существует такая проблема, как локальное хранилище потоков и общая память Unix.

Потоковое локальное хранилище позволяет каждому потоку иметь отдельный экземпляр глобальных объектов. Единственный раз, когда я использовал его, - это создание среды эмуляции на linux / windows, для кода приложения, работающего в RTOS. В RTOS каждая задача была процессом с собственным адресным пространством, в среде эмуляции каждая задача была потоком (с общим адресным пространством). Используя TLS для таких вещей, как singleletons, мы могли иметь отдельный экземпляр для каждого потока, как в реальной среде RTOS.

Совместно используемая память может (очевидно) дать вам преимущество в производительности при одновременном доступе нескольких процессов к одной и той же памяти, но по стоимости / риску необходимости правильно синхронизировать процессы. Один из способов сделать это - один процесс создать структуру данных в общей памяти, а затем отправить дескриптор этой структуры через традиционную межпроцессную связь (например, именованный канал).


Я должен согласиться с тем, что вы слышали. Когда мы сравниваем наш кластер ( xhpl и т. Д.), Мы всегда получаем значительно лучшую производительность с процессами по потокам. </anecdote>





process