В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13 |
Процессы
Например, командная строка, показанная в листинге 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.