•
На все вышеприведенные тактики, за исключением последней, повторное использование операционной системой идентификаторов процессов не оказывает отрицательного влияния.
В листинге 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
Иногда полезной практикой является отправка процессом сигнала самому себе. (Мы увидим пример этого в подразделе 34.7.3.) Эту задачу выполняет функция raise().
#include
int raise(int
Возвращает 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
Возвращает 0 при успешном завершении и –1 при ошибке
Вызов функции killpg() эквивалентен следующему вызову функции kill():
kill(-pgrp, sig);
Если аргумент pgrp указан как 0, то сигнал посылается всем процессам той же группы процессов, что и вызывающий процесс. В стандарте SUSv3 это не прописано, однако такой случай интерпретируется в большинстве реализаций UNIX точно так же, как и в Linux.
Для каждого сигнала существует выводимое на печать описание. Все описания хранятся в массиве 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
Возвращает указатель на строку с описанием сигнала
Функция strsignal() выполняет проверку попадания аргумента sig в границы массива, а затем возвращает указатель на пригодное для печати описание сигнала или на строку с сообщением об ошибке, если был указан неверный номер сигнала. (В некоторых других реализациях UNIX функция strsignal() возвращает NULL, если аргумент sig неверный.)
Кроме проверки соблюдения границ, у функции strsignal() есть дополнительное преимущество над непосредственным применением массива sys_siglist. Оно состоит в том, что функция strsignal() чувствительна к локали (см. раздел 10.4), а это значит, что описания сигналов будут представлены на местном языке.