Процессы изнутри

Многопользовательская работа и многозадачность

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

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

В следующих разделах мы расскажем об устройстве процессов в Linux.

Типы процессов

Интерактивные процессы

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

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

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

Запуск процесса в фоновом режиме, имеет смысл только для программ, которые не нуждаются в пользовательском контроле (через shell). Перевод задания в фоновый режим делается, как правило, когда для его выполнения, как ожидается, потребует длительного времени. Для того, чтобы освободить выдачу терминала после ввода команды, добавляется завершающий амперсанд. В примере, используя графический режим, мы открываем дополнительное окно терминала из имеющегося:

billy:~> xterm &
[1] 26558

billy:~> jobs
[1]+  Running                 xterm &

Подробное описание функции контроля заданий есть в info-страницах bash, так что здесь перечислены только наиболее часто используемые способы управления заданиями:

Таблица 4.1. Управление процессами

Команды (часть из существующих) Значение
regular_command Запуск данной команды на переднем плане.
command & Запуск команды в фоновом режиме (в версии терминала).
jobs Показывает команды запущенные в фоновом режиме.
Ctrl+Z Приостановить (остановить, но не выйти) процесс, выполняемый на переднем плане (засыпание).
Ctrl+C Прервать (прекратить и выйти) процесс, выполняемый на переднем плане.
%n Каждый процесс, выполняемый в фоновом режиме, получает присвоенный ему номер. Используя выражение %, указание может быть отнесено к процессу путем использования его номера, например, fg %2.
bg Возобновить приостановленную программу в фоновом режиме.
fg Поместить фоновое задание на передний план.
kill Завершение процесса (см. также Shell Builtin Commands на info-страницах bash).

Подробные практические примеры можно найти в упражнениях.

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

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

Автоматические процессы

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

  • В определенную дату и время: выполнение, используя команду at, которую мы обсудим во второй части этой главы.
  • В периоды, когда общая загруженность системы достаточно низка, чтобы принять дополнительные работы: делается с помощью команды batch. По умолчанию задачи ставятся в очередь, где они ожидают выполнения в период, когда загрузка системы будет меньше, чем 0,8. В больших средах системный администратор может отдать предпочтение пакетной обработке, когда должны быть обработаны большие объемы данных или когда выполнение задач требуют много системных ресурсов в уже загруженной системе. Пакетная обработка используется также для оптимизации производительности системы.

Демоны

Демоны — это серверные процессы, которые работают постоянно. В большинстве случаев они инициализируются при запуске системы, и затем ожидают в фоновом режиме до того, как их услуги потребуются. Типичным примером является сетевой демон xinetd, которая запускается почти при каждой процедуре загрузки. После того как система загрузится, сетевой демон просто сидит и ждет клиентскую программу, которую необходимо подключить, такую как, например, FTP-клиент.

Свойства процессов

Процесс имеет ряд особенностей, которые могут быть просмотрены с помощью команды ps:

  • Идентификатор процесса или PID: уникальный идентификационный номер, используемый для обращения к процессу.
  • ID родительского процесса или PPID: номер процесса (PID), который запустил данный процесс.
  • Nice-число: степень дружелюбия этого процесса по отношению к другим процессам (не путать с приоритетом процесса, который рассчитывается на основе этого милого числа и последнего использования процессора этим процессом).
  • Терминал или TTY: терминал, к которому привязан данный процесс.
  • Имя реального и эффективного пользователя (RUID и EUID): владелец процесса. Реальным владельцем является пользователь, который ввел команду, эффективный пользователь — тот, кто определяет порядок доступа к системным ресурсам. RUID и EUID обычно это одно и то же, и процесс имеет те же права доступа, которые есть у пользователя его запустившего. Поясним это на примере: браузер mozilla, находящийся в /usr/bin, принадлежит пользователю root:
theo:~> ls -l /usr/bin/mozilla
-rwxr-xr-x  1 root   root      4996 Nov 20 18:28 /usr/bin/mozilla*

theo:~> mozilla &
[1] 26595

theo:~> ps -af
UID     PID  PPID C STIME TTY       TIME CMD
theo  26601 26599 0 15:04 pts/5 00:00:00 /usr/lib/mozilla/mozilla-bin
theo  26613 26569 0 15:04 pts/5 00:00:00 ps -af

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

  • Реальная и эффективная группы владельца (RGID и EGID): реальной группой- владельцем процесса является основная группа пользователя, запустившего процесс. Эффективная группа-владелец - обычно то же самое, за исключением случаев, когда режим доступа SGID применяется к файлу.

Просмотр информации о процессе

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

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

theo:~> ps
  PID TTY          TIME CMD
 4245 pts/7    00:00:00 bash
 5314 pts/7    00:00:00 ps

Поскольку это не дает достаточно информации - как правило, по меньшей мере сотня процессов запущены в вашей системе – мы обычно будем выбирать отдельные процессы из списка всех процессов, используя команду grep в конвейере , см. Раздел "Выход перенаправления с > и | ", как в этой строке, в которой будут выбраны и отображены все процессы, принадлежащие определенному пользователю:

ps -ef | grep username

Этот пример показывает все процессы с процессорным именем bash, наиболее распространенной оболочкой в системах Linux:

theo:> ps auxw | grep bash
brenda   31970  0.0  0.3  6080 1556 tty2   S  Feb23   0:00 -bash
root     32043  0.0  0.3  6112 1600 tty4   S  Feb23   0:00 -bash
theo     32581  0.0  0.3  6384 1864 pts/1  S  Feb23   0:00 bash
theo     32616  0.0  0.3  6396 1896 pts/2  S  Feb23   0:00 bash
theo     32629  0.0  0.3  6380 1856 pts/3  S  Feb23   0:00 bash
theo      2214  0.0  0.3  6412 1944 pts/5  S  16:18   0:02 bash
theo      4245  0.0  0.3  6392 1888 pts/7  S  17:26   0:00 bash
theo      5427  0.0  0.1  3720  548 pts/7  S  19:22   0:00 grep bash

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

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

note.gif|?
Мы расскажем об операторе | в следующей главе, см. Главу 5, "Перенаправление ввода/вывода".

Дополнительная информация может быть найдена как обычно: ps --help или man ps. GNU ps поддерживает различные форматы опций; приведенные выше примеры не содержат ошибок.

Заметьте, что ps выдает только сиюминутное состояние активных процессов, это одномоментный срез. Программа top дает более точный обзор путем обновления результатов, определенных ps (с множеством опций), один раз в 5 секунд, создавая новый список процессов, что периодически вызывает большие нагрузки, поэтому используется подключение дополнительной информации о файле подкачки и состоянии процессора; из файла proc системы:

 12:40pm up 9 days, 6:00, 4 users, load average: 0.21, 0.11, 0.03
89 processes: 86 sleeping, 3 running, 0 zombie, 0 stopped
CPU states:  2.5% user,  1.7% system,  0.0% nice, 95.6% idle
Mem:   255120K av, 239412K used, 15708K free, 756K shrd, 22620K buff
Swap: 1050176K av, 76428K used, 973748K free, 82756K cached

  PID USER  PRI NI SIZE  RSS SHARE STAT %CPU %MEM TIME COMMAND
 5005 root  14  0 91572  15M 11580 R    1.9  6.0  7:53 X
19599 jeff  14  0  1024 1024   796 R    1.1  0.4  0:01 top
19100 jeff   9  0  5288 4948  3888 R    0.5  1.9  0:24 gnome-terminal
19328 jeff   9  0 37884  36M 14724 S    0.5 14.8  1:30 mozilla-bin
    1 root   8  0   516  472   464 S    0.0  0.1  0:06 init
    2 root   9  0     0    0     0 SW   0.0  0.0  0:02 keventd
    3 root   9  0     0    0     0 SW   0.0  0.0  0:00 kapm-idled
    4 root  19 19     0    0     0 SWN  0.0  0.0  0:00 ksoftirqd_CPU0
    5 root   9  0     0    0     0 SW   0.0  0.0  0:33 kswapd
    6 root   9  0     0    0     0 SW   0.0  0.0  0:00 kreclaimd
    7 root   9  0     0    0     0 SW   0.0  0.0  0:00 bdflush
    8 root   9  0     0    0     0 SW   0.0  0.0  0:05 kupdated
    9 root  -1-20     0    0     0 SW<  0.0  0.0  0:00 mdrecoveryd
   13 root   9  0     0    0     0 SW   0.0  0.0  0:01 kjournald
   89 root   9  0     0    0     0 SW   0.0  0.0  0:00 khubd
  219 root   9  0     0    0     0 SW   0.0  0.0  0:00 kjournald
  220 root   9  0     0    0     0 SW   0.0  0.0  0:00 kjournald

Первая строка top содержит такую же информацию, которая отображается командой uptime:

jeff:~> uptime
  3:30pm, up 12 days, 23:29, 6 users, load average: 0.01, 0.02, 0.00

Данных для этих программ хранятся среди других в /var/run/utmp (информация о текущих подключенных пользователях) и в виртуальной файловой системе /proc, например, /proc/loadavg (обычная загрузочная информация). Есть разные виды графических приложений для просмотра этой информации, такие как Gnome System Monitor и lavaps. На FreshMeat и SourceForge и вы найдете десятки приложений, которые централизируют эту информацию наряду с другими серверными данными и журналами со множества серверов на один (web) сервер, что позволяет осуществлять мониторинг всей ИТ-инфраструктуры с одной рабочей станции.

Отношения между процессами могут быть отображены с использованием команды pstree:

sophie:~> pstree
init-+-amd
     |-apmd
     |-2*[artsd]
     |-atd
     |-crond
     |-deskguide_apple
     |-eth0
     |-gdm---gdm-+-X
     |           `-gnome-session-+-Gnome
     |                           |-ssh-agent
     |                           `-true
     |-geyes_applet
     |-gkb_applet
     |-gnome-name-serv
     |-gnome-smproxy
     |-gnome-terminal-+-bash---vim
     |                |-bash
     |                |-bash---pstree
     |                |-bash---ssh
     |                |-bash---mozilla-bin---mozilla-bin---3*[mozilla-bin]
     |                `-gnome-pty-helper
     |-gpm
     |-gweather
     |-kapm-idled
     |-3*[kdeinit]
     |-keventd
     |-khubd
     |-5*[kjournald]
     |-klogd
     |-lockd---rpciod
     |-lpd
     |-mdrecoveryd
     |-6*[mingetty]
     |-8*[nfsd]
     |-nscd---nscd---5*[nscd]
     |-ntpd
     |-3*[oafd]
     |-panel
     |-portmap
     |-rhnsd
     |-rpc.mountd
     |-rpc.rquotad
     |-rpc.statd
     |-sawfish
     |-screenshooter_a
     |-sendmail
     |-sshd---sshd---bash---su---bash
     |-syslogd
     |-tasklist_applet
     |-vmnet-bridge
     |-xfs
     `-xinetd-ipv6

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

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

Жизнь и смерть процесса

Создание процесса

Новый процесс появляется вследствие того, что существующий процесс создает точную копию самого себя. У этого дочернего процесса тоже окружение, что и у родителя, отличается только номер ID процесса. Эта процедура называется forking (порождение).

После рождения, адресное пространство дочернего процесса переписывается с новыми данными процесса. Это делается посредством вызова ехес в системе.

Таким образом, механизм fork-and-exec переключает старые команды на новые, пока окружение, в котором выполняется новая программа остается таким же, в том числе конфигурация устройств ввода/вывода, переменные окружения и приоритет. Этот механизм используется для создания всех процессов UNIX, также это относится и к операционной системе Linux. Даже первый процесс, init, с процессорным ID 1, порождается во время загрузки в так называемой процедуре bootstrapping (начальной загрузки).

Эта схема иллюстрирует механизм fork-and-exec. ID процесса изменяется после процедуры порождения:

Рисунок 4.1. Механизм fork-and-exec

fork-and-exec.png

Есть несколько случаев, в которых init становится родителем процесса, хотя процесс не был запущен init, как мы уже видели в примере pstree. Многие программы, например, daemonize - их дочерние процессы, так они могут продолжать работать, когда родитель завершается или его завершают. Оконный менеджер является типичным примером; он запускается процессом xterm, который создает оболочку (shell), принимающую команды. Затем оконный менеджер отстраняется от какой-либо дальнейшей ответственности и передает дочерний процесс init. С помощью этого механизма можно менять оконные менеджеры, не прерывая запущенных приложений.

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

Завершение процесса

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

Коды возврата могут быть интерпретированы родителем или скриптами. Значения кодов возврата специфичны для программ. Эту информацию обычно можно найти в man-страницах указанной программы, например команда grep возвращает -1, если не найдено совпадений, при этом в строке может быть выведено сообщение: "Нет найденных файлов". Другим примером является встроенная команда Bash true, которая не делает ничего, кроме возвращения статуса выхода 0, что означает успех.

Сигналы

Процессы заканчиваются, если они получают сигнал. Есть несколько сигналов, которые вы можете отправить процессу. Используйте команду kill, чтобы послать сигнал процессу. Команда kill -i отображается список сигналов. Большинство сигналов предназначены для внутреннего использования системой или для программистов, когда они пишут код. Как пользователю вам потребуются следующие сигналы:

Таблица 4.2. Часто используемые сигналы

Имя сигнала Номер сигнала Значение
SIGTERM 15 Завершить процесс надлежащим образом.
SIGINT 2 Прерывание процесса. Процесс может игнорировать этот сигнал.
SIGKILL 9 Прерывание процесса. Процесс не может игнорировать этот сигнал.
SIGHUP 1 Для демонов: перечитать конфигурационный файл.

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

SUID и SGID

Как и было обещано в предыдущей главе, теперь мы будем обсуждать специальные режимы SUID и SGID более подробно. Эти режимы существуют, чтобы обеспечить обычным пользователям возможность выполнять задачи, которые они, как правило, не могут осуществить из-за строгой схемы управления доступом к файлам, используемой в UNIX-системах. В идеальной ситуации специальные режимы используются так редко, насколько это возможно, так как они включают в себя риски для безопасности. Разработчики Linux, как правило, стараются также избегать их по возможности. Версия ps в Linux, например, использует информацию, хранящуюся в файловой системе /proc, которая доступна каждому, что позволяет избегать демонстрации важных системных данных и ресурсов для широкой общественности. До этого (и до сих пор на старых системах UNIX) программа ps нуждалась в доступе к файлам, таким как /dev/mem и /dev/kmem, что имело свои недостатки из-за разрешений и владельцев этих файлов:

rita:~> ls -l /dev/*mem
crw-r-----    1 root     kmem       1,   2 Aug 30 22:30 /dev/kmem
crw-r-----    1 root     kmem       1,   1 Aug 30 22:30 /dev/mem

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

Хотя мы обычно стараемся избегать применения каких-либо специальных режимов, иногда бывает необходимо использовать SUID. Примером может служить механизм смены пароля. Очевидно, что пользователи хотят делать это самостоятельно вместо того, чтобы их пароль устанавливал системный администратор. Как мы знаем, имена пользователей и пароли перечислены в файле /etc/passwd, который имеет следующие права доступа и владельцев:

bea:~> ls -l /etc/passwd
-rw-r--r--    1 root     root     1267 Jan 16 14:43 /etc/passwd

Тем не менее, у пользователей должна быть возможность изменять свою информацию в этом файле. Это достигается путем предоставления программой passwd специальных разрешений:

mia:~> which passwd
passwd is /usr/bin/passwd

mia:~> ls -l /usr/bin/passwd
-r-s--x--x    1 root     root    13476 Aug  7 06:03 /usr/bin/passwd*

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

SGID режимы на файл не распространяются так же часто, как SUID, потому что SGID зачастую включает в себя создание дополнительных групп. В некоторых случаях, однако, мы должны пройти через эту неприятность, с тем чтобы выполнить элегантное решение (слишком об этом не беспокойтесь - необходимые группы обычно создаются при установке). Это происходит для программ write и wall, которые используются для отправки сообщений другим пользовательским терминалами (ttys). Команда writeвыводит сообщение одному пользователю, а wall пишет всем подключенным пользователям.

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

В приведенном ниже примере пользователь joe в начале узнает, с каким терминалом связан его корреспондент, для этого он использует команду who. Затем он отправляет ей сообщение с помощью команды write. Кроме того, иллюстрируются права доступа на программу write и какие терминалы занимает принимающий пользователь: очевидно, что отличные от пользователя-владельца не имеют разрешения на устройство, за исключением владельца-группы, которая может писать в него.

joe:~> which write
write is /usr/bin/write

joe:~> ls -l /usr/bin/write
-rwxr-sr-x    1 root     tty      8744 Dec  5 00:55 /usr/bin/write*

joe:~> who
jenny     tty1     Jan 23 11:41
jenny     pts/1    Jan 23 12:21 (:0)
jenny     pts/2    Jan 23 12:22 (:0)
jenny     pts/3    Jan 23 12:22 (:0)
joe       pts/0    Jan 20 10:13 (lo.callhost.org)

joe:~> ls -l /dev/tty1
crw--w----    1 jenny   tty  4,     1 Jan 23 11:41 /dev/tty1

joe:~> write jenny tty1
hey Jenny, shall we have lunch together?
^C

Пользователь jenny получает это на ее экране:

Message from joe@lo.callhost.org on ptys/1 at 12:36 ...
hey Jenny, shall we have lunch together?
EOF

После получения сообщения, терминал может быть очищен помощью комбинации клавиш Ctrl + L. Для того, чтобы не получать никакие сообщения вообще (кроме тех, что от системного администратора), используйте команду mesg. Чтобы узнать, какие подключенные пользователи принимают сообщения от других, используют who -w. Все особенности полностью разъяснены на info-страницах для каждой команды.

note.gif Названия групп могут быть различными. 
Групповая схема специфична для дистрибутива. Разные дистрибутивы могут использовать разные имена или различные решения.

Создано