Легковесный процесс (англ. light-weight process, LWP) является средством достижения многозадачности в компьютерной операционной системе в традиционном понимании этого термина. В Unix System V и Solaris легковесный процесс работает в пространстве пользователя поверх одного потока выполнения ядра, разделяет виртуальное адресное пространство и системные ресурсы потока выполнения с другими легковесными процессами в рамках того же процесса. Несколько потоков пользовательского уровня, управляемых с помощью библиотеки потоков, могут быть размещены в одном или нескольких легковесных процессах, что даёт многозадачность на уровне пользователя, которая может иметь некоторые преимущества в производительности[1].

В некоторых операционных системах нет отдельного слоя легковесных процессов между потоками ядра и пользовательскими потоками. Это означает, что пользовательские потоки реализуются непосредственно потоками ядра. В таких случаях термин «легковесный процесс», как правило, означает поток ядра, а термин «поток» может означать пользовательский поток. В ядре Linux пользовательские потоки реализованы так, что позволяют определенным процессам совместно использовать ресурсы, что иногда позволяет применять к этим потокам термин «легковесные процессы»[2]. Аналогично в SunOS версии 4 (предшественнице Solaris) легковесными процессами назывались пользовательские потоки[1].

Потоки ядра править

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

Производительность править

[прояснить]

Создание легковесного процесса обходится дороже и выполняется дольше, чем пользовательский поток. При создании легковесного процесса сначала делается системный вызов, создающий соответствующий поток ядра[прояснить], то есть производится переключение в режим ядра. Такие переключения режимов, как правило, связаны с копированием параметров между ядром и пользовательским пространством, также ядро обычно выполняет дополнительные действия по проверке корректности параметров. Переключение контекста между легковесными процессами требует упреждающего сохранения регистров, затем производится переход в режим ядра, где затем производится сохранение регистров потока ядра, и после того, как производится всё необходимое по планированию легковесного процесса, производится восстановление соответствующих значений регистров в режиме ядре и в пользовательском режиме.[1]

В связи с этим некоторые библиотеки пользовательского уровня реализованы так, что создают несколько пользовательских потоков поверх легковесного процесса. Пользовательские потоки могут быть созданы, уничтожены, синхронизированы и переключаться между друг другом полностью в пространстве пользователя без необходимости осуществления системных вызовов и переходов в режим ядра. Это обеспечивает значительное улучшение производительности в момент создания потока и переключений контекста.[1] Тем не менее, существуют трудности в реализации планировщика потоков пользовательского уровня, который бы хорошо работал вместе с ядром.

Активация планировщика править

Пока пользовательская библиотека занимается планированием пользовательских потоков, ядро занимается планированием подлежащих легковесных процессов. Без координации между ядром и потоковой библиотекой ядро может принять субоптимальные решения планирования. Кроме того, это может привести взаимной блокировке, когда пользовательские потоки распределённые по несколько легковесным процессам, пытаются получить те же ресурсы, использующиеся другим пользовательским потоком, который не выполняется в данный момент.[1]

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

Библиотека пользовательского уровня не имеет никакого контроля над механизмом более высокого уровня, она только получает уведомления от ядра и осуществляет планирование потоков пользовательских потоков на имеющихся легковесных процессах, а не процессорах. Планировщик ядра решает как планировать легковесные процессы на процессорах. Это означает что легковесные процессы представляются в библиотеке потоков как «виртуальные процессоры»[3].

Поддержка в операционных системах править

В Solaris реализован отдельный слой легковесных процессов, начиная с версии 2.2. До версии 9, Solaris предоставляла многие-ко-многим соотношения легковесных процессов к пользовательским потокам. Однако, это было упразднено, из-за сложностей, к которым это приводило, что также улучшило производительность планировщика ядра[1].

UNIX System V и его современные производные, такие как IRIX, SCO OpenServer, HP-UX и IBM AIX предоставляют сопоставления «многие ко многим» между пользовательскими потоками и легковесными процессами[3][4].

В Linux определена собственная версия легковесных процессов, которая отличается от используемых в некоторых других системах, таких как SVR4 и Solaris. Linux рассматривает легковесные процессы как основной контекст выполнения и управляет ими с помощью нестандартного системного вызова clone()[2].

Примечания править

  1. 1 2 3 4 5 6 Юреш Вахалия. Нити и легковесные процессы // UNIX изнутри = UNIX Internals - The New Frontiers / пер. с англ. Е. Васильев, Л. Серебрякова. — Петербург: Питер, 2003. — С. 97. — 844 с. — ISBN 5-94723-013-5, 0-13-101908-2.
  2. 1 2 Д. Бовет, М. Чезати. Процессы, облегчённые процессы и потоки // Ядро Linux = Understanding the Linux Kernel / пер. с англ. Сергей Иноземцев. — Петербург: БХВ-Петербург, 2007. — С. 123. — 1104 с. — ISBN 0-596-00565-2, 978-5-94157-957-0.
  3. 1 2 Silberschatz, Galvin, Gagne. Chapter 5 - Threads // Operating System Concepts with Java. — 6. — John Wiley & Sons, Inc., 2004. — ISBN 978-0-470-50949-4.
  4. AIX 6.1 - Thread tuning. IBM (2009). Дата обращения: 5 декабря 2015. Архивировано 8 декабря 2015 года.