Provided by: manpages-ru-dev_4.19.0-7_all bug

ИМЯ

       signalfd - создаёт файловый дескриптор для приёма сигналов

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #include <sys/signalfd.h>

       int signalfd(int fd, const sigset_t *mask, int flags);

ОПИСАНИЕ

       Вызов  signalfd()  создаёт  файловый  дескриптор,  который  можно  использовать для приёма
       сигналов, предназначенных вызывающему.  Его  можно  использовать  как  замену  обработчику
       сигналов  или  sigwaitinfo(2);  преимущество  в  том,  что  за файловым дескриптором можно
       следить с помощью select(2), poll(2) и epoll(7).

       В аргументе mask указывается набор сигналов,  который  вызывающий  хочет  принимать  через
       файловый  дескриптор.  Этот  аргумент, содержащий набор сигналов, можно инициализировать с
       помощью макросов, описанных в sigsetops(3).  Обычно,  набор  сигналов,  принимаемых  через
       файловый  дескриптор,  должен  блокироваться с помощью sigprocmask(2), чтобы предотвратить
       обработку сигналов назначенными им обработчиками по умолчанию. Через  файловый  дескриптор
       signalfd  нельзя  получить  сигнал  SIGKILL или SIGSTOP; при указании их в mask они просто
       игнорируются.

       Если значение аргумента fd  равно  -1,  то  вызов  создаёт  новый  файловый  дескриптор  и
       связывает  с  ним  набор  сигналов, указанный в mask. Если fd не равно -1, то в нём должен
       быть  указан  допустимый  существующий  файловый  дескриптор  signalfd,  а  значение  mask
       используется для замены набора сигналов, связанного с этим файловым дескриптором.

       Начиная  с  Linux  2.6.27, для изменения поведения signalfd() можно использовать следующие
       значения flags (через OR):

       SFD_NONBLOCK  Устанавливает флаг состояния файла O_NONBLOCK для нового открытого файлового
                     описания (смотрите open(2)), на которое ссылается новый файловый дескриптор.
                     Использование данного флага делает ненужными дополнительные вызовы  fcntl(2)
                     для достижения того же результата.

       SFD_CLOEXEC   Устанавливает флаг close-on-exec (FD_CLOEXEC) для нового открытого файлового
                     дескриптора. Смотрите описание флага O_CLOEXEC в  open(2)  для  того,  чтобы
                     узнать как это может пригодиться.

       Up to Linux 2.6.26, the flags argument is unused, and must be specified as zero.

       Вызов signalfd() возвращает файловый дескриптор, который поддерживает следующие операции:

       read(2)
              Если  один  или  несколько сигналов, указанных в mask, ожидают обработки, то буфер,
              указанный в read(2),  используется  для  возврата  одной  или  нескольких  структур
              signalfd_siginfo   (см.   ниже),  описывающих  сигналы.  Вызов  read(2)  возвращает
              информацию о всех ожидающих сигналах, которые поместились в предоставленный  буфер.
              Размер   буфера   должен   быть  не  менее  sizeof(struct  signalfd_siginfo)  байт.
              Возвращаемое read(2) значение представляет собой общее количество прочитанных байт.

              После выполнения read(2) сигналы  считаются  учтёнными,  они  больше  не  считаются
              ожидающими  обработки (т.е., они не будут переданы обработчикам сигналов и не могут
              быть приняты с помощью sigwaitinfo(2)).

              Если ни один из сигналов из  mask  не  ожидает  обработки,  то  вызов  read(2)  или
              блокируется  до  поступления  сигналов  согласно  mask,  или  завершается с ошибкой
              EAGAIN, если файловый дескриптор помечен как неблокируемый.

       poll(2), select(2) (и подобные)
              Файловый дескриптор доступен для чтения (в select(2) аргумент  readfds;  в  poll(2)
              флаг POLLIN), если один или более сигналов из mask ожидают обработки.

              Файловый  дескриптор  signalfd  также  поддерживает  другие  мультиплексные вызовы:
              pselect(2), ppoll(2) и epoll(7).

       close(2)
              Если файловый дескриптор больше не требуется, его нужно закрыть. Когда все файловые
              дескрипторы,  связанные  с одним объектом signalfd, будут закрыты, ядро освобождает
              ресурсы объекта.

   Структура signalfd_siginfo
       Формат  структур(ы)  signalfd_siginfo,  возвращаемых  read(2)  из  файлового   дескриптора
       signalfd, имеет следующий вид:

           struct signalfd_siginfo {
               uint32_t ssi_signo;    /* Signal number */
               int32_t  ssi_errno;    /* Error number (unused) */
               int32_t  ssi_code;     /* Signal code */
               uint32_t ssi_pid;      /* PID of sender */
               uint32_t ssi_uid;      /* Real UID of sender */
               int32_t  ssi_fd;       /* File descriptor (SIGIO) */
               uint32_t ssi_tid;      /* Kernel timer ID (POSIX timers)
               uint32_t ssi_band;     /* Band event (SIGIO) */
               uint32_t ssi_overrun;  /* POSIX timer overrun count */
               uint32_t ssi_trapno;   /* Trap number that caused signal */
               int32_t  ssi_status;   /* Exit status or signal (SIGCHLD) */
               int32_t  ssi_int;      /* Integer sent by sigqueue(3) */
               uint64_t ssi_ptr;      /* Pointer sent by sigqueue(3) */
               uint64_t ssi_utime;    /* User CPU time consumed (SIGCHLD) */
               uint64_t ssi_stime;    /* System CPU time consumed
                                         (SIGCHLD) */
               uint64_t ssi_addr;     /* Address that generated signal
                                         (for hardware-generated signals) */
               uint16_t ssi_addr_lsb; /* Least significant bit of address
                                         (SIGBUS; since Linux 2.6.37) */
               uint8_t  pad[X];       /* Pad size to 128 bytes (allow for
                                         additional fields in the future) */
           };

       Каждое  из  полей в этой структуре аналогично полям с тем же именем в структуре siginfo_t.
       Структура  siginfo_t  описана  в  sigaction(2).  Не  все  поля  в  возвращаемой  структуре
       signalfd_siginfo  будут  заполнены  правильно  для каждого сигнала; набор допустимых полей
       можно определить по значению, возвращённому в поле ssi_code. Это  поле  является  аналогом
       поля si_code в siginfo_t; подробней смотрите в sigaction(2).

   Поведение при fork(2)
       После вызова fork(2) потомок наследует копию файлового дескриптора signalfd. Вызов read(2)
       для файлового дескриптора в потомке вернёт информацию о сигналах для потомка.

   Семантика передачи файлового дескриптора
       Как и другие файловые дескрипторы, файловые дескрипторы signalfd можно передавать в другой
       процесс через доменный сокет UNIX (смотрите unix(7)). В принимающем процессе вызов read(2)
       из принятого файлового  дескриптора  возвратит  информацию  о  сигналах  в  очереди  этого
       процесса.

   Поведение при execve(2)
       Как  и  любой  файловый  дескриптор,  файловый дескриптор signalfd остаётся открытым после
       execve(2), если он не помечен как close-on-exec (см. fcntl(2)). Все сигналы, которые  были
       доступны для чтения перед execve(2), остаются доступными и для новой загруженной программы
       (аналогично обычному поведению сигналов, когда блокированный сигнал, ожидающий  обработки,
       остаётся в очереди ожидания после execve(2)).

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

   Поведение epoll(7)
       If a process adds (via epoll_ctl(2))  a signalfd file descriptor to an epoll(7)  instance,
       then epoll_wait(2)  returns events only for signals sent to that process.  In  particular,
       if  the  process then uses fork(2)  to create a child process, then the child will be able
       to read(2)  signals  that  are  sent  to  it  using  the  signalfd  file  descriptor,  but
       epoll_wait(2)   will  not  indicate  that  the signalfd file descriptor is ready.  In this
       scenario, a possible workaround is that after the fork(2), the child process can close the
       signalfd file descriptor that it inherited from the parent process and then create another
       signalfd file descriptor and add it to the epoll instance.  Alternatively, the parent  and
       the  child could delay creating their (separate) signalfd file descriptors and adding them
       to the epoll instance until after the call to fork(2).

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       При успешном выполнении signalfd() возвращает файловый дескриптор signalfd; это будет  или
       новый файловый дескриптор (если fd равно -1), или fd, если fd содержит допустимый файловый
       дескриптор signalfd. При ошибке возвращается -1,  а  errno  присваивается  соответствующее
       значение.

ОШИБКИ

       EBADF  Неправильный файловый дескриптор в fd.

       EINVAL Значение fd не является правильным файловым дескриптором signalfd.

       EINVAL Неправильное значение flags или, для Linux 2.6.26 и старее, flags не равно 0.

       EMFILE Было  достигнуто  ограничение  по  количеству  открытых  файловых  дескрипторов  на
              процесс.

       ENFILE Достигнуто максимальное количество открытых файлов в системе.

       ENODEV Не удалось смонтировать (внутреннее) безымянное устройство inode.

       ENOMEM Недостаточно памяти для создания нового файлового дескриптора signalfd.

ВЕРСИИ

       signalfd()  is available since Linux 2.6.22.  Working support is provided since glibc 2.8.
       The signalfd4()  system call (see NOTES) is available since Linux 2.6.27.

СТАНДАРТЫ

       Вызовы signalfd() и signalfd4() есть только в Linux.

ЗАМЕЧАНИЯ

       Процесс  может  создать  несколько файловых дескрипторов signalfd. Это позволяет принимать
       различные сигналы через различные файловые дескрипторы (может быть полезно при слежении за
       файловым  дескриптором  с  помощью  select(2),  poll(2)  или  epoll(7): прибытие различных
       сигналов делает готовым различные файловые дескрипторы). Если сигнал  указан  в  mask  для
       нескольких  файловых  дескрипторов, то появление этого сигнала можно прочесть (однократно)
       из любого файлового дескриптора.

       Попытки включить SIGKILL и SIGSTOP в маску mask просто игнорируются.

       The signal mask employed by a signalfd file descriptor can be viewed via the entry for the
       corresponding  file  descriptor  in the process's /proc/pid/fdinfo directory.  See proc(5)
       for further details.

   Ограничения
       Механизм  signalfd  нельзя  использовать  для  приёма  сигналов,  генерируемых  синхронно,
       например  сигнала  SIGSEGV  при доступе по неправильному адресу памяти, или сигнала SIGFPE
       при математических ошибках. Такие сигналы можно поймать только через обработчик сигнала.

       Как сказано выше, обычно все сигналы,  принимаемые  через  signalfd(),  блокируются.  Если
       порождается  дочерний  процесс  для выполнения вспомогательной программы (которой не нужен
       файловый дескриптор signalfd), то после вызова fork(2), обычно, нужно  разблокировать  эти
       сигналы  перед  вызовом  execve(2)  для  того,  чтобы вспомогательная программа видела все
       сигналы, которые она ожидает увидеть. Однако имейте в виду, что это может быть невозможно,
       если  вспомогательная  программа  порождается  не  вами,  а где-то в библиотечной функции,
       которую может вызывать программа. В таких случаях нужно  использовать  обычный  обработчик
       сигналов,  который  пишет  в  файловый  дескриптор,  отслеживаемый  select(2), poll(2) или
       epoll(7).

   Отличия между библиотекой C и ядром
       Лежащий в основе системный вызов Linux требует дополнительного аргумента, size_t sizemask,
       в  котором  указывается  размер  аргумента mask. В обёрточной функции glibc signalfd() нет
       этого аргумента — требуемое для системного вызова значение добавляется библиотекой.

       Существуют два системных вызова Linux: signalfd() и  более  новый  signalfd4().  В  первом
       системном  вызове  не  реализован  аргумент  flags. Во втором системном вызове реализованы
       значения flags, описанные ранее.  Начиная  с  glibc  2.9,  обёрточная  функция  signalfd()
       использует signalfd4(), если он доступен.

ДЕФЕКТЫ

       Before  Linux  2.6.25,  the  ssi_ptr  and  ssi_int  fields are not filled in with the data
       accompanying a signal sent by sigqueue(3).

ПРИМЕРЫ

       Программа, представленная  далее,  принимает  сигналы  SIGINT  и  SIGQUIT  через  файловый
       дескриптор  signalfd.  Она завершает работу при приёме сигнала SIGQUIT. Вот сеанс работы в
       оболочке, демонстрирующий использование программы:

           $ ./signalfd_demo
           ^C                   # Control-C generates SIGINT
           Got SIGINT
           ^C
           Got SIGINT
           ^\                    # Control-\ generates SIGQUIT
           Got SIGQUIT
           $

   Исходный код программы

       #include <err.h>
       #include <signal.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/signalfd.h>
       #include <unistd.h>

       int
       main(void)
       {
           int                      sfd;
           ssize_t                  s;
           sigset_t                 mask;
           struct signalfd_siginfo  fdsi;

           sigemptyset(&mask);
           sigaddset(&mask, SIGINT);
           sigaddset(&mask, SIGQUIT);

           /* Block signals so that they aren't handled
              according to their default dispositions. */

           if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
               err(EXIT_FAILURE, "sigprocmask");

           sfd = signalfd(-1, &mask, 0);
           if (sfd == -1)
               err(EXIT_FAILURE, "signalfd");

           for (;;) {
               s = read(sfd, &fdsi, sizeof(fdsi));
               if (s != sizeof(fdsi))
                   err(EXIT_FAILURE, "read");

               if (fdsi.ssi_signo == SIGINT) {
                   printf("Получен SIGINT\n");
               } else if (fdsi.ssi_signo == SIGQUIT) {
                   printf("Получен SIGQUIT\n");
                   exit(EXIT_SUCCESS);
               } else {
                   printf("Прочитан неожидаемый сигнал\n");
               }
           }
       }

СМ. ТАКЖЕ

       eventfd(2), poll(2), read(2),  select(2),  sigaction(2),  sigprocmask(2),  sigwaitinfo(2),
       timerfd_create(2), sigsetops(3), sigwait(3), epoll(7), signal(7)

ПЕРЕВОД

       Русский    перевод    этой    страницы    руководства   был   сделан   Alexander   Golubev
       <fatzer2@gmail.com>,  Azamat  Hackimov  <azamat.hackimov@gmail.com>,   Hotellook,   Nikita
       <zxcvbnm3230@mail.ru>,       Spiros       Georgaras       <sng@hellug.gr>,       Vladislav
       <ivladislavefimov@gmail.com>,   Yuri   Kozlov   <yuray@komyakino.ru>   и    Иван    Павлов
       <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы  обнаружите  ошибки  в  переводе этой страницы руководства, пожалуйста, отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.