Материал: 396_OS_uchebnoe_posobie_part1_2012

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

суперпользователя (англ. root, UID = 0). При этом ответственность за правильную и допустимую смену пароля несёт passwd. «Настроена» означает, что владельцем файла является пользователь root, и файл имеет специальное право «Установить эффективного пользователя»47. При запуске такого файла

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

пользовательский процесс имеет возможность изменять значения RUID и EUID (менять их местами или делать одинаковыми48). При изменении значения поля EUID его изначальное значение сохраняется в поле «сохранённый идентификатор пользователя» (англ. SUID, Saved UID). Кроме эффективного идентификатора в дескрипторе процессов в ОС Linux имеется нестандартное поле FSUID (англ. File System UID), которое используется при обращении процесса к файловой системе. При запуске процесса FSUID эквивалентен EUID. Всё сказанное про идентификаторы пользователей справедливо и для основной группы пользователя (поля GID или RGID, EGID, SGID, FSGID).

Воперационной системе Linux процессы, выполняющие одну задачу, объединяются в группы. Например, если в командной строке задано, что процессы связаны при помощи программного канала, они обычно помещаются

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

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

5.4.Получение информации о состоянии и атрибутах процессов

5.4.1. Из командной строки

Чтобы получить информацию о том, какие процессы запущены в данный момент в системе и в каком состоянии они находятся, можно использовать команду ps (англ. process status) с определённым набором опций (таблица 9).

47Подробнее о правах на объекты файловой системы говорится в п.4.3.12.

48Пользователю доступны только эти поля. Суперпользователь может изменять поля RUID, EUID,

FSUID.

61

Таблица 9. Опции команды ps.

Опция

Действие

-a

Выдать все процессы системы, включая лидеров сеансов.

-d

Выдать все процессы системы, исключая лидеров сеансов.

-e

Выдать все процессы системы.

-x

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

-o

Определяет формат вывода. Формат задаётся как параметр опции в

 

виде символьной строки, поля которой (таблица 10) разделяются

 

символом «,» (запятая).

-u

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

 

зователь задаётся в параметре опции в символьном виде.

Таблица 10. Поля форматного вывода команды ps.

Формат

Значение

F

Статус процесса.

S

Состояние процесса.

UID

Идентификатор пользователя.

PID

Идентификатор процесса.

PPID

Идентификатор родительского процесса.

PRI

Текущий динамический приоритет процесса.

NI

Значение приоритета процесса.

TTY

Управляющий терминал процесса.

TIME

Суммарное время выполнения процесса процессором.

STIME

Время создания процесса.

COMMAND

Имя команды, соответствующей процессу.

SESS

Идентификатор сеанса процесса.

PGRP

Идентификатор группы процесса.

Например, список запущенных процессов Вашей системы можно получить, используя команду ps -e. Информацию о группах и сессиях процесса можно получить так:

$ ps -axo pid,pgrp,session,command

Можно также посмотреть «дерево» процессов, используя команду pstree. Чтобы увидеть использование ресурсов «в динамике», можно использовать команду top. Выход из просмотра осуществляется нажатием

клавиши «q».

62

5.4.2. При выполнении процессов

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

#include <sys/types.h> #include <unistd.h>

pid_t getpid (void) pid_t getppid (void) uid_t getuid (void); uid_t geteuid (void); gid_t getgid (void); gid_t getegid (void); pid_t getpgrp (void); pid_t getsid (pid_t pid);

Назначение функций очевидно из названия. Например, функция getpid вернёт идентификатор процесса (PID). Все функции, кроме getsid, не принимают никаких параметров и возвращают значение соответствующих полей из дескриптора текущего (вызвавшего функцию) процесса. Функция getsid позволяет узнать идентификатор сеанса для любого процесса в системе (если это позволено соответствующему пользователю), идентификатор которого передаётся в качестве параметра. Если передать вызову getsid значение 0, то он вернёт идентификатор сеанса вызывающего процесса (т.е. это эквивалентно записи getsid(getpid());).

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

#include <sys/types.h> #include <unistd.h>

pid_t setpgid(pid_t pid, pid_t pgid); pid_t setsid(void);

Вызов setpgid устанавливает идентификатор группы процесса с идентификатором, равным pid, в pgid. В случае ошибки возвращается –1.

Изменить значения полей RUID, EUID, FSUID, RGID, EGID, FSGID

можно при помощи системных вызовов:

#include <sys/types.h> #include <unistd.h>

int

setuid

(uid_t

uid);

int

seteuid

(uid_t

euid);

63

int setreuid (uid_t ruid, uid_t euid);

int setfsuid

(uid_t fsuid);

int setgid

(gid_t gid);

int setegid

(gid_t egid);

int

setfsgid (gid_t

fsgid);

int

setregid (gid_t

rgid, gid_t egid);

Назначение функций очевидно из названия. Пояснений требуют лишь функции setreuid и setregid. Обе эти функции предназначены для изменения полей RUID, EUID и RGID, EGID соответственно в ситуации, когда операционная система не поддерживает дополнительных полей SUID, SGID. Эти функции включены в библиотеку для реализации совместимости с такими операционными системами как 4.3 UNIX BSD, которые не имеют в дескрипторах процессов указанных полей. За подробной информацией об использовании этих функции следует обратиться к электронной справочной системе man.

Очевидно, что процесс может получить информацию только о своих атрибутах, и при этом процесс всегда находится в состоянии Running (R).

Использование функции установки значений полей дескриптора процесса рассмотрим на примере создания процесса-демона (листинг 1).

Листинг 1. Создание процесса-демона

1. #include <unistd.h>

2.

3.int main(void){

4.close (0);

5.close (1);

6.close (2);

7.setsid(0);

8.setpgrp(0,0);

9.

10./* тело процесса-демона */

11.sleep(10);

12.return (0);

13.}

В первой строке подключается необходимый заголовочный файл. В данном случае нам нужны только функции по работе с атрибутами процесса, файловыми дескрипторами и функция sleep, которая переводит процесс в состояние ожидания. Далее в строках 4-6 процесс отключается от терминала (вспомним, что «демон» не имеет «присоединённого» терминала). После чего создаёт новый сеанс и группу (строки 7-8). Затем процесс может выполняться независимо от того, находится ли запустивший его пользователь в системе или уже завершил свой сеанс. В нашем случае «демон» просто «спит» 10 секунд (строка 11) и затем завершается (строка 12).

64

5.5 Потоки одного процесса (нити)

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

весными процессами49.

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

5.6. Порождение процессов и запуск программ

5.6.1. Порождение процессов

Новый процесс порождается с помощью системного вызова fork:

#include <sys/types.h> #include <unistd.h>

pid_t fork(void);

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

идентификатор процесса (PID);

идентификатор родительского процесса (PPID). У дочернего процесса он приравнивается к PID родительского процесса (того, кто выполнил вызов fork);

дочерний процесс не имеет очереди сигналов, ожидающих обработки.

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

Чтобы процесс мог определить, кем он является (дочерним или родительским), используется возвращаемое значение вызова fork. В первом случае, когда процесс является дочерним, fork вернёт 0, во втором – PID вновь созданного процесса. Если fork возвращает –1, то это свидетельствует об

49 В операционной системе Windows NT вводится термин «волокно» (англ. fiber) для обозначения потока, планированием которого занимается не операционная система, а сам процесс.

65

Источник: https://studfile.net/preview/16708918/