Поиск…
Синтаксис
- неподписанный сигнал тревоги (беззнаковые секунды);
- int kill (pid_t pid, int sig);
параметры
| Функция, Параметр (ы), Возвращаемое значение | Описание | 
|---|---|
| alarm() | имя функции | 
| unsigned seconds | Секунды, чтобы поднять тревогу или 0, чтобы отменить любой ожидающий сигнал тревоги | 
| > = 0 | 0, если другой сигнал не был отложен, иначе количество секунд, которое ожидающий сигнал тревоги остался открытым. Эта функция не сработает. | 
| - | - | 
| kill() | имя функции | 
| pid_t pid | , | 
| int sig | 0 или идентификатор сигнала | 
| 0, -1 | При успешном ESRCHвозвращается 0, -1 приESRCHс установкойerrnoвEINVAL,EPERMилиESRCH. | 
Поднятие SIGALARM с действием по умолчанию
 Используя alarm , пользователь может назначить сигнал SIGALARM после определенного интервала. В случае, если пользователь не заблокировал, проигнорировал или указал явный обработчик сигнала для этого сигнала, действие по умолчанию для этого сигнала будет выполняться по прибытии. В соответствии со спецификацией по умолчанию для SIGALARM применяется SIGALARM завершения процесса: 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
    printf("Hello!\n");
    // Set the alarm for five second
    alarm(5); // Per POSIX, this cannot fail
    // Now sleep for 15 seconds
    for (int i = 1; i <= 15; i++)
    {
        printf("%d\n", i);
        sleep(1);
    }
    // And print the message before successful exit
    printf("Goodbye!\n");
    return EXIT_SUCCESS;
}
Эти результаты:
Hello!
1
2
3
4
5
[2]    35086 alarm      ./a.out
Установка обработчика сигналов с использованием сигмации и поднятия сигналов с использованием рейза
 Чтобы программа реагировала на определенный сигнал, кроме использования действия по умолчанию, пользовательский обработчик сигнала может быть установлен с использованием sigaction . sigaction получает три аргумента - сигнал действовать, указатель на структуру sigaction_t который, если не NULL , описывает новое поведение и указатель на sigaction_t который, если не NULL будет заполнен старым поведением (поэтому его можно восстановить). Поднять сигналы в том же процессе можно с помощью метода raise . Если требуется больше контроля (чтобы отправить сигнал на какой-либо другой процесс, можно использовать kill или pthread_kill , которые принимают идентификатор процесса назначения или идентификатор потока). 
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Signals are numbered from 1, signal 0 doesn't exist
volatile sig_atomic_t last_received_signal = 0;
// Signal handler, will set the global variable
// to indicate what is the last signal received.
// There should be as less work as possible inside
// signal handler routine, and one must take care only
// to call reentrant functions (in case of signal arriving
// while program is already executing same function)
void signal_catcher(int signo, siginfo_t *info, void *context)
{
    last_received_signal = info->si_signo;
}
int main (int argc, char** argv)
{
    // Setup a signal handler for SIGUSR1 and SIGUSR2
    struct sigaction act;
    memset(&act, 0, sizeof act);
    // sigact structure holding old configuration
    // (will be filled by sigaction):
    struct sigaction old_1;
    memset(&old_1, 0, sizeof old_1);
    struct sigaction old_2;
    memset(&old_2, 0, sizeof old_2);
    act.sa_sigaction = signal_catcher;
    // When passing sa_sigaction, SA_SIGINFO flag
    // must be specified. Otherwise, function pointed
    // by act.sa_handler will be invoked
    act.sa_flags = SA_SIGINFO;
    if (0 != sigaction(SIGUSR1, &act, &old_1))
    {
        perror("sigaction () failed installing SIGUSR1 handler");
        return EXIT_FAILURE;
    }
    if (0 != sigaction(SIGUSR2, &act, &old_2))
    {
        perror("sigaction() failed installing SIGUSR2 handler");
        return EXIT_FAILURE;
    }
    // Main body of "work" during which two signals
    // will be raised, after 5 and 10 seconds, and which
    // will print last received signal
    for (int i = 1; i <= 15; i++)
    {
        if (i == 5)
        {
            if (0 != raise(SIGUSR1))
            {
                perror("Can't raise SIGUSR1");
                return EXIT_FAILURE;
            }
        }
        if (i == 10)
        {
            if (0 != raise(SIGUSR2))
            {
                perror("Can't raise SIGUSR2");
                return EXIT_FAILURE;
            }
        }
        printf("Tick #%d, last caught signal: %d\n",
            i, last_received_signal);
        sleep(1);
    }
    // Restore old signal handlers
    if (0 != sigaction(SIGUSR1, &old_1, NULL))
    {
        perror("sigaction() failed restoring SIGUSR1 handler");
        return EXIT_FAILURE;
    }
    if (0 != sigaction(SIGUSR2, &old_2, NULL))
    {
        perror("sigaction() failed restoring SIGUSR2 handler");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
Эти результаты:
Tick #1, last caught signal: 0
Tick #2, last caught signal: 0
Tick #3, last caught signal: 0
Tick #4, last caught signal: 0
Tick #5, last caught signal: 30
Tick #6, last caught signal: 30
Tick #7, last caught signal: 30
Tick #8, last caught signal: 30
Tick #9, last caught signal: 30
Tick #10, last caught signal: 31
Tick #11, last caught signal: 31
Tick #12, last caught signal: 31
Tick #13, last caught signal: 31
Tick #14, last caught signal: 31
Tick #15, last caught signal: 31
Процесс совершения самоубийства с использованием kill ()
 Процесс может (попытаться) отправить сигнал на любой другой процесс, используя функцию kill() . 
 Для этого процессу отправки необходимо знать процесс приема PID. Поскольку, не вводя гонку, процесс может быть уверен только в собственном PID (и PID своих дочерних элементов), самым простым примером продемонстрировать использование kill() является передача процесса самому себе. 
 Ниже пример процесса, инициирующего его собственное завершение, отправив сам kill-signal ( SIGKILL ): 
#define _POSIX_C_SOURCE 1
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
int main (void)
{
  pid_t pid = getpid(); /* Get my iown process ID. */
  kill(pid, SIGKILL); /* Send myself a KILL signal. */
  puts("Signal delivery initiated.");  /* Although not guaranteed, 
                                  practically the program never gets here. */
  pause(); /* Wait to die. */
  puts("This never gets printed.");
}
Выход:
Killed
(... или аналогично, в зависимости от реализации)
Обрабатывать SIGPIPE, сгенерированный write () потокобезопасным способом
 Когда write() вызывается для именованного или неназванного канала или потока, чей конец чтения закрыт, происходят две вещи: 
-  Сигнал SIGPIPEотправляется процессу, который вызываетwrite()
-  Сигнал SIGPIPEотправляется в поток, который вызываетwrite()
-  Ошибка EPIPEвозвращается командойwrite()
 Существует несколько способов решения SIGPIPE : 
-  Для сокетов SIGPIPEможно отключить, установив параметры платформы, такие какMSG_NOSIGNALв Linux иSO_NOSIGPIPEв BSD (работает только дляsend, но не дляwrite). Это не переносимо.
-  Для FIFO (именованные каналы) SIGPIPEне будет сгенерирован, если автор используетO_RDWRвместоO_WRONLY, так что конец чтения всегда открывается. Однако это также отключаетEPIPE.
-  Мы можем игнорировать SIGPIPEили устанавливать глобальный обработчик. Это хорошее решение, но это неприемлемо, если вы не контролируете все приложение (например, вы пишете библиотеку).
-  С недавними версиями POSIX мы можем использовать тот факт, что SIGPIPEотправляется в поток, который вызываетwrite()и обрабатывает его с использованием технологии синхронного управления сигналами.
 В приведенном ниже коде демонстрируется поточно-безопасная обработка SIGPIPE для POSIX.1-2004 и более поздних версий. 
Это вдохновляет этот пост :
-  Сначала добавьте SIGPIPEчтобы сигнализировать маску текущего потока, используяpthread_sigmask().
-  Убедитесь, что SIGPIPEуже находится на рассмотрении, используяsigpending().
-  Вызов write(). Если конец чтения закрыт,SIGPIPEбудет добавлен в маску ожидающих сигналов, иEPIPEбудет возвращен.
-  Если write()возвратилEPIPE, аSIGPIPEне былEPIPEдоwrite(), удалите его из маски ожидающих сигналов, используяsigtimedwait().
-  Восстановите исходную сигнальную маску с помощью pthread_sigmask().
Исходный код:
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <sys/signal.h>
ssize_t safe_write(int fd, const void* buf, size_t bufsz)
{
    sigset_t sig_block, sig_restore, sig_pending;
    sigemptyset(&sig_block);
    sigaddset(&sig_block, SIGPIPE);
    /* Block SIGPIPE for this thread.
     *
     * This works since kernel sends SIGPIPE to the thread that called write(),
     * not to the whole process.
     */
    if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0) {
        return -1;
    }
    /* Check if SIGPIPE is already pending.
     */
    int sigpipe_pending = -1;
    if (sigpending(&sig_pending) != -1) {
        sigpipe_pending = sigismember(&sig_pending, SIGPIPE);
    }
    if (sigpipe_pending == -1) {
        pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
        return -1;
    }
    ssize_t ret;
    while ((ret = write(fd, buf, bufsz)) == -1) {
        if (errno != EINTR)
            break;
    }
    /* Fetch generated SIGPIPE if write() failed with EPIPE.
     *
     * However, if SIGPIPE was already pending before calling write(), it was
     * also generated and blocked by caller, and caller may expect that it can
     * fetch it later. Since signals are not queued, we don't fetch it in this
     * case.
     */
    if (ret == -1 && errno == EPIPE && sigpipe_pending == 0) {
        struct timespec ts;
        ts.tv_sec = 0;
        ts.tv_nsec = 0;
        int sig;
        while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1) {
            if (errno != EINTR)
                break;
        }
    }
    pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
    return ret;
}