Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 7:

Процессы

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >

Например, командная строка, показанная в листинге 7.2, породит выдачу, фрагмент которой приведен в листинге 7.3

ps -A -o ruser,user,pid,ppid,tty=TTY -o
	nice,vsz,args
Листинг 7.2. Пример использования утилиты ps.
RUSER USER PID PPID TTY NI VSZ COMMAND
root root 1 0 ? 0 1372 init [5]
root root 4 1 ? 19 0 [ksoftirqd_CPU0]
root root 555 1 ? 0 1428 syslogd -m 0
root root 560 1 ? 0 1364 klogd -x
rpc rpc 580 1 ? 0 1508 portmap
rpcuser rpcuser 608 1 ? 0 1560 rpc.statd
root root 743 1 ? 0 2620 /usr/sbin/sshd
root root 776 1 ? 0 2200 xinetd -stayalive
	-reuse -pidfi
root root 805 1 ? 0 1500 rpc.rquotad
root root 810 1 ? 0 1504 rpc.mountd
root root 897 1 ? 0 3236
	/usr/libexec/postfix/master
postfix postfix 906 897 ? 0 3384 nqmgr -l -n
	qmgr -t fifo -u -c
root root 918 1 ? 0 1400 gpm -t ps/2
	-m /dev/mouse
root root 936 1 ? 0 1548 crond
xfs xfs 968 1 ? 0 4432 xfs -droppriv -daemon
nobody nobody 987 1 ? 0 36488 dictd 1.9.7: 0/0
root daemon 1022 1 ? 0 1404 /usr/sbin/atd
root root 1057 1 ? 0 5768 cupsd
root root 1064 1 tty1 0 1344 /sbin/mingetty tty1
root root 1070 1 ttyS2 0 1352 /sbin/agetty -i -L ttyS2 38400
root root 1072 1 ? 0 2300 login -- galat
galat galat 1086 1072 ttyS4 0 2260 -sh
root root 1124 1085 ? 0 16900
	/usr/bin/kdm_greet
postfix postfix 1826 897 ? 0 3304 pickup -l
	-t fifo -u -c
galat galat 2013 1171 ttyS4 0 1940 /bin/sh -c
	ps -A -o user,pid,pp
galat galat 2014 2013 ttyS4 0 2584 ps -A -o
	user,pid,ppid,tty=TTY
Листинг 7.3. Фрагмент возможного результата использования утилиты ps.

Для опроса идентификаторов процесса, родительского процесса и группы процессов предусмотрены функции getpid() и getppid()   getpgrp() (см. листинг 7.4).

#include <unistd.h>
pid_t getpid (void);

#include <unistd.h>
pid_t getppid (void);

#include <unistd.h>
pid_t getpgrp (void);
Листинг 7.4. getpid(), getppid() и getpgrp().

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

Для установки идентификатора группы процессов в целях управления заданиями предназначена функция setpgid() (см. листинг 7.5).

#include <unistd.h>
int setpgid (pid_t pid, pid_t pgid);
Листинг 7.5. Описание функции setpgid().

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

В случае успешного завершения функции setpgid() (результат при этом равен нулю) идентификатор группы процессов устанавливается равным pgid для заданного аргументом pid процесса. Если значение pid равно нулю, установка производится для вызывающего процесса. А если значение pgid равно нулю, то в качестве идентификатора группы процессов используется идентификатор процесса, заданного аргументом pid.

Для создания сеанса и установки идентификатора группы процессов служит функция setsid() (см. листинг 7.6).

#include <unistd.h>
pid_t setsid (void);
Листинг 7.6. Описание функции setsid().

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

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

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main (void) {
		pid_t ppid;
	pid_t pgid;
	/* Отменим буферизацию стандартного вывода */
	setbuf (stdout, NULL);
	printf ("Атрибуты текущего процесса: pid: %d,
		ppid: %d, pgid: %d\n",
		getpid (), ppid = getppid (), pgid =
		getpgrp ());
	/* Выделимся в новую группу */
	if (setpgid (0, 0) != 0) {
		perror ("setpgid (0, 0)");
	}
	printf ("Новая группа текущего процесса: %d\n",
	getpgrp ());
	/* Попробуем создать новый сеанс */
	if (setsid () == (pid_t) (-1)) {
		perror ("setsid от имени лидера группы");
	}
	/* Вернемся в прежнюю группу */
	if (setpgid (0, pgid) != 0) {
		perror ("setpgid (0, pgid)");
	}
	printf ("Группа текущего процесса после повторной
		смены: %d\n", getpgrp ());
	/* Повторим попытку создать новый сеанс */
	if (setsid () == (pid_t) (-1)) {
		perror ("setsid от имени не-лидера группы");
	}
	printf ("Группа текущего процесса после создания
		нового сеанса: %d\n", getpgrp ());
	/* Попробуем сменить группу родительского
	процесса */
	if (setpgid (ppid, 0) != 0) {
		perror ("setpgid (ppid, 0)");
	}
	/* Попробуем установить несуществующий */
	/* идентификатор группы процессов */
	if (setpgid (0, ppid) != 0) {
		perror ("setpgid (0, ppid)");
	}
	return (0);
}
Листинг 7.7. Пример программы, использующей функции getpid(), getppid(), getpgrp(), setpgid(), setsid().
Атрибуты текущего процесса: pid: 11726, ppid:
	11725, pgid: 1153
Новая группа текущего процесса: 11726
	setsid от имени лидера группы: Operation not permitted
Группа текущего процесса после повторной смены:
	1153
Группа текущего процесса после создания нового
	сеанса: 11726
setpgid (ppid, 0): No such process
setpgid (0, ppid): Operation not permitted
Листинг 7.8. Возможный результат работы программы, показанной в листинге 7.7.

Опрос реальных и действующих идентификаторов пользователя и группы вызывающего процесса осуществляется с помощью функций getuid(), geteuid(), getgid(), getegid() (см. листинг 7.9). Как и getpid(), они всегда завершаются успешно.

#include <unistd.h>
uid_t getuid (void);

#include <unistd.h>
uid_t geteuid (void);

#include <unistd.h>
gid_t getgid (void);

#include <unistd.h>
gid_t getegid (void);
Листинг 7.9. Описание функций getuid(), geteuid(), getgid(), getegid().

Более сложный интерфейс имеет функция getgroups(), предназначенная для получения идентификаторов дополнительных групп вызывающего процесса (см. листинг 7.10). Эти идентификаторы (в их число может входить и действующий идентификатор группы процесса) помещаются в массив grouplist.

#include <unistd.h>
int getgroups (int gidsetsize, 
               gid_t grouplist []);
Листинг 7.10. Описание функции getgroups().

Аргумент gidsetsize задает число элементов в массиве grouplist, а реальное количество записанных идентификаторов групп возвращается в виде результата функции. Если в качестве значения gidsetsize задать нуль, getgroups() выдаст количество дополнительных групп, не модифицируя массив grouplist.

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?