• Интерфейс /proc/PID. Например, если существует идентификатор процесса 12345, значит, должен существовать и каталог /proc/12345, соответственно, мы можем проверить наличие этого каталога с помощью вызова stat().

На все вышеприведенные тактики, за исключением последней, повторное использование операционной системой идентификаторов процессов не оказывает отрицательного влияния.

В листинге 20.3 демонстрируется применение функции kill(). Эта программа принимает два аргумента командной строки: идентификатор процесса и номер сигнала, а затем вызывает функцию kill() для отправки сигнала в заданный процесс. Если указан сигнал 0 (нулевой сигнал), то программа докладывает о существовании целевого процесса.

Листинг 20.3. Использование системного вызова kill()

signals/t_kill.c

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

int s, sig;

if (argc!= 3 || strcmp(argv[1], "-help") == 0)

usageErr("%s pid sig-num\n", argv[0]);

sig = getInt(argv[2], 0, "sig-num");

s = kill(getLong(argv[1], 0, "pid"), sig);

if (sig!= 0) {

if (s == –1)

errExit("kill");

} else { /* Нулевой сигнал: проверка существования процесса */

if (s == 0) {

printf("Process exists and we can send it a signal\n");

} else {

if (errno == EPERM)

printf("Process exists, but we don't have "

"permission to send it a signal\n");

else if (errno == ESRCH)

printf("Process does not exist\n");

else

errExit("kill");

}

}

exit(EXIT_SUCCESS);

}

signals/t_kill.c

20.7. Другие способы отправки сигналов: raise() и killpg()

Иногда полезной практикой является отправка процессом сигнала самому себе. (Мы увидим пример этого в подразделе 34.7.3.) Эту задачу выполняет функция raise().

#include

int raise(int sig);

Возвращает 0 при успешном завершении и ненулевое значение при ошибке

В программе с одним потоком вызов функции raise() аналогичен следующему вызову функции kill():

kill(getpid(), sig);

В системах, поддерживающих потоки, вызов raise(sig) реализуется таким образом:

pthread_kill(pthread_self(), sig);

Функция pthread_kill() описывается в подразделе 33.2.3, а сейчас достаточно сказать: такая реализация означает, что сигнал будет доставлен именно в тот поток, из которого был выполнен вызов функции raise(). Но вызов kill(getpid(), sig) посылает сигнал в вызывающий процесс, то есть сигнал может быть доставлен в любой поток в рамках процесса.

Функция raise() появилась в языке С89. Стандарты языка С не затрагивают детали реализации операционной системы, такие как идентификаторы процессов, но функция raise() может быть описана в этом стандарте, так как ей не требуется указывать на идентификаторы процессов.

Когда процесс посылает сигнал самому себе с помощью функции raise() (или kill()), сигнал доставляется моментально (иными словами, перед тем, как функция raise() вернет управление в вызвавший ее код).

Обратите внимание, что функция raise() возвращает ненулевой результат (не обязательно –1) при возникновении ошибки. Единственная ошибка, которая может возникнуть при работе raise(), — это EINVAL при указании неверного значения sig. Таким образом, при указании одной из констант SIGxxxx нет необходимости проверять код возврата.

Функция killpg() посылает сигналы всем процессам в группе.

#include

int killpg(pid_t pgrp, int sig);

Возвращает 0 при успешном завершении и –1 при ошибке

Вызов функции killpg() эквивалентен следующему вызову функции kill():

kill(-pgrp, sig);

Если аргумент pgrp указан как 0, то сигнал посылается всем процессам той же группы процессов, что и вызывающий процесс. В стандарте SUSv3 это не прописано, однако такой случай интерпретируется в большинстве реализаций UNIX точно так же, как и в Linux.

20.8. Отображение описаний сигналов

Для каждого сигнала существует выводимое на печать описание. Все описания хранятся в массиве sys_siglist. Например, можно указать элемент массива sys_siglist[SIGPIPE] для получения описания сигнала SIGPIPE (нарушенный канал). Но вместо использования массива sys_siglist напрямую предпочтительнее вызывать функцию strsignal().

#define _BSD_SOURCE

#include

extern const char *const sys_siglist[];

#define _GNU_SOURCE

#include

char *strsingnal(int sig);

Возвращает указатель на строку с описанием сигнала

Функция strsignal() выполняет проверку попадания аргумента sig в границы массива, а затем возвращает указатель на пригодное для печати описание сигнала или на строку с сообщением об ошибке, если был указан неверный номер сигнала. (В некоторых других реализациях UNIX функция strsignal() возвращает NULL, если аргумент sig неверный.)

Кроме проверки соблюдения границ, у функции strsignal() есть дополнительное преимущество над непосредственным применением массива sys_siglist. Оно состоит в том, что функция strsignal() чувствительна к локали (см. раздел 10.4), а это значит, что описания сигналов будут представлены на местном языке.

Перейти на страницу:

Похожие книги