Процессы и нити Linux

Сущность процесса неразрывно связана с мультипрограммированием и многозадачностью операционной системы. Например, в однозадачных операционных системах программы существуют, а процессы — нет.

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

В любой программе можно выделить перемежающиеся блоки инструкций, использующих или центральный процессор (ЦП), или устройства ввода-вывода (УВВ).

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

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

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

Количество времени, потраченного на вычислительные операции упаковки, будет много больше количества времени, потраченного на чтение исходных данных и запись результатов, поэтому нагрузка на ЦП будет высокой, а на УВВ — нет. Такой же анализ можно привести и для дубликатора dd, копировщика rsync или архиватора tar, которые, наоборот, почти не выполняют никаких вычислений, а сосредоточены на вводе-выводе больших объемов данных, поэтому при их использовании нагрузка на ЦП будет достаточно низкой, а на УВВ — высокой.

Для командного интерпретатора bash, текстовых редакторов nano и vim и других интерактивных программ, взаимодействующих с пользователем, характерны длительные ожидания ввода небольших команд, простая и недолгая их обработка и вывод короткого результата. В результате коэффициент полезного использования и ЦП, и УВВ будет приближен к нулю.

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

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

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

В Linux, как и во многих других операционных системах, программы изолируются друг от друга в специальных «виртуальных» средах, обеспечивающих их процесс выполнения. Каждая такая среда называется процессом и получает долю доступных ресурсов — выделенный участок памяти, выделенные промежутки процессорного времени.

Процесс эмулирует для программы «однозадачный» режим выполнения, словно программа выполняется в одиночку, и «безраздельное» использование ресурсов процесса, как будто это все доступные ресурсы.

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

В листинге ниже при помощи команды ps показаны процессы пользователя, упорядоченные в дерево, построенное на основе дочерне-родительских отношений между процессами. Уникальный идентификатор, отличающий процесс от других, выведен в столбце PID (process identifier), а имя и аргументы программы, запущенной в соответствующем процессе, — в столбце COMMAND.

В столбце STAT показано текущее состояние процесса, например S (сон, sleep) или R (выполнение, running, или готовность к выполнению, runnable). Процессы, ожидающие завершения их операций ввода-вывода, находятся в состоянии сна, в противном случае либо выполняются, либо готовы к выполнению, т. е. ожидают, когда текущий выполняющийся процесс заснет, и процессор будет переключен на них.

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

Дерево процессов пользователя

fitz@ubuntu:~$ ps fx

PID     TTY            STAT       TIME     COMMAND

2156    ?                  Ssl           0:02       gnome-session —session=ubuntu

2410    ?                  Ss            0:00        \_/usr/bin/ssh-agent /usr/bin/dbus-launch —exit-with…

2432    ?                  Si             0:51        \_ /usr/lib/gnome-settings-daemon/gnome-settings-daemon

2451     ?                  S              1:01         |     \ syndaemon -l 2.0 -K -R -t

2442    ?                  Rl             27:21       \_ compiz

2569    ?                  Ss             0:00       |       \_ /bin/sh -c /usr/bin/compiz-decorator

2570    ?                  Sl               0:25      |              \_ /usr/bin/gtk-window-decorator

7806    ?                  Ss              0:00      |           /bin/sh -c gnome-terminal

7807     ?                 Si              0:28       |              \_ gnome-terminal

7813      ?                S                0:00       |              \_ gnome-pty-helper

8127      pts/1        Ss               0:00       |              \_ bash

10808   pts/1        R+              0:00       |              |       \_ ps fx

9321       pts/0       Ss               0:00       |              \_ bash

10792     pts/0       S+              0:00       |             |         \_ man ps ,

10803     pts/0      S+               0:00       |             |                  \_ pager -s

10610      pts/2      Ss                0:00       |             \_ bash

Управляющий терминал процесса, показанный в столбце TTY, используется для доставки ему интерактивных сигналов при вводе управляющих символов intr , quit ^\ и пр. У части процессов управляющий терминал отсутствует, потому что они выполняют приложения, взаимодействующие о пользователем не посредством терминалов, а через графическую систему.

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

Использование предназначенных для этого средств межпроцессного взаимодействия при интенсивном обмене приводит к обременению неоправданными накладными расходами, поэтому для эффективного выполнения таких параллельных программ используются легковесные процессы (LWP, light-weight processes), они же нити (threads). Существует еще один (не очень удачный) перевод понятия thread на русский язык — поток. Во-первых, он конфликтует с переводом понятия stream — поток, а во-вторых, в отличие от stream, thread никуда не течет. А вот процесс (process) содержит в себе нити (thread) абсолютно таким же образом, как и обычная веревка состоит из… нитей.

Механизм нитей позволяет переключать центральный процессор между параллельными ветвями одной программы, размещаемыми в одном (!) процессе.

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

В примере из листинга ниже показаны нити процесса в BSD-формате вывода. Выбор процесса производится по его идентификатору PID, предварительно полученному командой pgrep по имени программы,выполняющейся в искомом процессе.

В выводе наличие нитей процесса отмечает флаг l (Iwp) в столбце состояния STAT, а каждая строчка без идентификатора pid символизирует одну нить. Так как в многонитевой программе переключение процессора производится между нитями, то и состояния сна S, выполнения или ожидания R приписываются отдельным нитям.

Нити процессов, BSD-формат вывода

fttz@ubuntu:~$ pgrep skype

24244

fttz@ubuntu:~$ ps mp 24244
PID   TTY          STAT         TIME    COMMAND

24244   ?                —                 13:14      skype

—    —                Sl              11:13       —

—    —                Sl              00:00       —

—    —                Sl              00:00       —

—    —                Sl              00:00       —

—    —                Sl              00:00       —

—    —                Sl              00:02       —

В листинге ниже показаны нити процесса в SYSV-формате вывода. Выбор процесса производится по имени его программы.

Общий для всех нитей идентификатор их процесса отображается в столбце PID, уникальный идентификатор каждой нити — в столбце LWP (иногда называемый TID, thread identifier), а имя процесса (или собственное имя нити, если задано) — в столбце CMD.

Нити процессов, SYSV-формат вывода

 

fitz@ubuntu: ~$ ps -LC gnome-terminal

PID        LWP   TTY                            TIME   CMD

16749 16749     ?                          00:00:08 gnome-terminal

16749 16750     ?                          00:00:08 dconf worker

16749 16751     ?                           00:00:00 gdbus

16749 16758    ?                            00:00:00 gmain

 

Процессы и нити Linux: 1 комментарий

  1. Уведомление: Порождение процессов и нитей, запуск программ Linux | Debian GNU/Linux

Добавить комментарий