.\" -*- coding: UTF-8 -*- .\" Copyright (C) 2008 Michael Kerrisk .\" starting from a version by Davide Libenzi .\" .\" %%%LICENSE_START(GPLv2+_SW_3_PARA) .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, see .\" . .\" %%%LICENSE_END .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH SIGNALFD 2 "1 ноября 2020 г." Linux "Руководство программиста Linux" .SH ИМЯ signalfd \- создаёт файловый дескриптор для приёма сигналов .SH СИНТАКСИС \fB#include \fP .PP \fBint signalfd(int \fP\fIfd\fP\fB, const sigset_t *\fP\fImask\fP\fB, int \fP\fIflags\fP\fB);\fP .SH ОПИСАНИЕ Вызов \fBsignalfd\fP() создаёт файловый дескриптор, который можно использовать для приёма сигналов, предназначенных вызывающему. Его можно использовать как замену обработчику сигналов или \fBsigwaitinfo\fP(2); преимущество в том, что за файловым дескриптором можно следить с помощью \fBselect\fP(2), \fBpoll\fP(2) и \fBepoll\fP(7). .PP В аргументе \fImask\fP указывается набор сигналов, который вызывающий хочет принимать через файловый дескриптор. Этот аргумент, содержащий набор сигналов, можно инициализировать с помощью макросов, описанных в \fBsigsetops\fP(3). Обычно, набор сигналов, принимаемых через файловый дескриптор, должен блокироваться с помощью \fBsigprocmask\fP(2), чтобы предотвратить обработку сигналов назначенными им обработчиками по умолчанию. Через файловый дескриптор signalfd нельзя получить сигнал \fBSIGKILL\fP или \fBSIGSTOP\fP; при указании их в \fImask\fP они просто игнорируются. .PP Если значение аргумента \fIfd\fP равно \-1, то вызов создаёт новый файловый дескриптор и связывает с ним набор сигналов, указанный в \fImask\fP. Если \fIfd\fP не равно \-1, то в нём должен быть указан допустимый существующий файловый дескриптор signalfd, а значение \fImask\fP используется для замены набора сигналов, связанного с этим файловым дескриптором. .PP Начиная с Linux 2.6.27, для изменения поведения \fBsignalfd\fP() можно использовать следующие значения \fIflags\fP (через OR): .TP 14 \fBSFD_NONBLOCK\fP Устанавливает флаг состояния файла \fBO_NONBLOCK\fP для нового открытого файлового описания (смотрите \fBopen\fP(2)), на которое ссылается новый файловый дескриптор. Использование данного флага делает ненужными дополнительные вызовы \fBfcntl\fP(2) для достижения того же результата. .TP \fBSFD_CLOEXEC\fP Устанавливает флаг close\-on\-exec (\fBFD_CLOEXEC\fP) для нового открытого файлового дескриптора. Смотрите описание флага \fBO_CLOEXEC\fP в \fBopen\fP(2) для того, чтобы узнать как это может пригодиться. .PP До версии Linux 2.6.26 аргумент \fIflags\fP не использовался, и должен быть равен нулю. .PP Вызов \fBsignalfd\fP() возвращает файловый дескриптор, который поддерживает следующие операции: .TP \fBread\fP(2) Если один или несколько сигналов, указанных в \fImask\fP, ожидают обработки, то буфер, указанный в \fBread\fP(2), используется для возврата одной или нескольких структур \fIsignalfd_siginfo\fP (см. ниже), описывающих сигналы. Вызов \fBread\fP(2) возвращает информацию о всех ожидающих сигналах, которые поместились в предоставленный буфер. Размер буфера должен быть не менее \fIsizeof(struct signalfd_siginfo)\fP байт. Возвращаемое \fBread\fP(2) значение представляет собой общее количество прочитанных байт. .IP После выполнения \fBread\fP(2) сигналы считаются учтёнными, они больше не считаются ожидающими обработки (т.е., они не будут переданы обработчикам сигналов и не могут быть приняты с помощью \fBsigwaitinfo\fP(2)). .IP Если ни один из сигналов из \fImask\fP не ожидает обработки, то вызов \fBread\fP(2) или блокируется до поступления сигналов согласно \fImask\fP, или завершается с ошибкой \fBEAGAIN\fP, если файловый дескриптор помечен как неблокируемый. .TP \fBpoll\fP(2), \fBselect\fP(2) (и подобные) Файловый дескриптор доступен для чтения (в \fBselect\fP(2) аргумент \fIreadfds\fP; в \fBpoll\fP(2) флаг \fBPOLLIN\fP), если один или более сигналов из \fImask\fP ожидают обработки. .IP Файловый дескриптор signalfd также поддерживает другие мультиплексные вызовы: \fBpselect\fP(2), \fBppoll\fP(2) и \fBepoll\fP(7). .TP \fBclose\fP(2) Если файловый дескриптор больше не требуется, его нужно закрыть. Когда все файловые дескрипторы, связанные с одним объектом signalfd, будут закрыты, ядро освобождает ресурсы объекта. .SS "Структура signalfd_siginfo" Формат структур(ы) \fIsignalfd_siginfo\fP, возвращаемых \fBread\fP(2) из файлового дескриптора signalfd, имеет следующий вид: .PP .in +4n .EX .\" ssi_trapno is unused on most arches .\" ssi_addr_lsb: commit b8aeec34175fc8fe8b0d40efea4846dfc1ba663e struct signalfd_siginfo { uint32_t ssi_signo; /* номер сигнала */ int32_t ssi_errno; /* номер ошибки (не используется) */ int32_t ssi_code; /* код сигнала */ uint32_t ssi_pid; /* PID отправителя */ uint32_t ssi_uid; /* реальный UID отправителя */ int32_t ssi_fd; /* файловый дескриптор (SIGIO) */ uint32_t ssi_tid; /* ID таймера ядра (таймеры POSIX) uint32_t ssi_band; /* внутреннее событие (SIGIO) */ uint32_t ssi_overrun; /* счётчик переполнений таймера POSIX */ uint32_t ssi_trapno; /* номер ловушки, поймавшей сигнал */ int32_t ssi_status; /* код выхода или сигнала (SIGCHLD) */ int32_t ssi_int; /* целое, посланное sigqueue(3) */ uint64_t ssi_ptr; /* указатель, посланный sigqueue(3) */ uint64_t ssi_utime; /* пользовательское потреблённое время ЦП (SIGCHLD) */ uint64_t ssi_stime; /* системное потреблённое время ЦП (SIGCHLD) */ uint64_t ssi_addr; /* сгенерированный сигналом адрес (для сигналов от аппаратуры) */ uint16_t ssi_addr_lsb; /* наименее значимый бит адреса (SIGBUS; начиная с Linux 2.6.37) uint8_t pad[\fIX\fP]; /* заполнитель до 128 байт (для будущих дополнительных полей) */ }; .EE .in .PP Каждое из полей в этой структуре аналогично полям с тем же именем в структуре \fIsiginfo_t\fP. Структура \fIsiginfo_t\fP описана в \fBsigaction\fP(2). Не все поля в возвращаемой структуре \fIsignalfd_siginfo\fP будут заполнены правильно для каждого сигнала; набор допустимых полей можно определить по значению, возвращённому в поле \fIssi_code\fP. Это поле является аналогом поля \fIsi_code\fP в \fIsiginfo_t\fP; подробней смотрите в \fBsigaction\fP(2). .SS "Поведение при fork(2)" После вызова \fBfork\fP(2) потомок наследует копию файлового дескриптора signalfd. Вызов \fBread\fP(2) для файлового дескриптора в потомке вернёт информацию о сигналах для потомка. .SS "Семантика передачи файлового дескриптора" Как и другие файловые дескрипторы, файловые дескрипторы signalfd можно передавать в другой процесс через доменный сокет UNIX (смотрите \fBunix\fP(7)). В принимающем процессе вызов \fBread\fP(2) из принятого файлового дескриптора возвратит информацию о сигналах в очереди этого процесса. .SS "Поведение при execve(2)" Как и любой файловый дескриптор, файловый дескриптор signalfd остаётся открытым после \fBexecve\fP(2), если он не помечен как close\-on\-exec (см. \fBfcntl\fP(2)). Все сигналы, которые были доступны для чтения перед \fBexecve\fP(2), остаются доступными и для новой загруженной программы (аналогично обычному поведению сигналов, когда блокированный сигнал, ожидающий обработки, остаётся в очереди ожидания после \fBexecve\fP(2)). .SS "Поведение в нитях" .\" Поведение файловых дескрипторов signalfd в многонитевых программах отражает стандартное поведение сигналов. Иначе говоря, когда нить выполняет чтение из файлового дескриптора signalfd, она прочтёт сигналы, которые предназначены самой нити и сигналы, предназначенные процессу (т.е., всей группе нитей). Нить не может прочитать сигналы, которые предназначены другим нитям процесса. .SS "Поведение epoll(7)" If a process adds (via \fBepoll_ctl\fP(2)) a signalfd file descriptor to an \fBepoll\fP(7) instance, then \fBepoll_wait\fP(2) returns events only for signals sent to that process. In particular, if the process then uses \fBfork\fP(2) to create a child process, then the child will be able to \fBread\fP(2) signals that are sent to it using the signalfd file descriptor, but \fBepoll_wait\fP(2) will \fBnot\fP indicate that the signalfd file descriptor is ready. In this scenario, a possible workaround is that after the \fBfork\fP(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 \fBfork\fP(2). .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" При успешном выполнении \fBsignalfd\fP() возвращает файловый дескриптор signalfd; это будет или новый файловый дескриптор (если \fIfd\fP равно \-1), или \fIfd\fP, если \fIfd\fP содержит допустимый файловый дескриптор signalfd. При ошибке возвращается \-1, а \fIerrno\fP присваивается соответствующее значение. .SH ОШИБКИ .TP \fBEBADF\fP Неправильный файловый дескриптор в \fIfd\fP. .TP \fBEINVAL\fP .\" or, the .\" .I sizemask .\" argument is not equal to .\" .IR sizeof(sigset_t) ; Значение \fIfd\fP не является правильным файловым дескриптором signalfd. .TP \fBEINVAL\fP Неправильное значение \fIflags\fP или, для Linux 2.6.26 и старее, \fIflags\fP не равно 0. .TP \fBEMFILE\fP Было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс. .TP \fBENFILE\fP Достигнуто максимальное количество открытых файлов в системе. .TP \fBENODEV\fP Не удалось смонтировать (внутреннее) безымянное устройство inode. .TP \fBENOMEM\fP Недостаточно памяти для создания нового файлового дескриптора signalfd. .SH ВЕРСИИ .\" signalfd() is in glibc 2.7, but reportedly does not build Вызов \fBsignalfd\fP() доступен в Linux, начиная с ядра 2.6.22. Поддержка в glibc появилась в версии 2.8. Системный вызов \fBsignalfd4\fP() (см. ЗАМЕЧАНИЯ) доступен в Linux, начиная с ядра 2.6.27. .SH "СООТВЕТСТВИЕ СТАНДАРТАМ" Вызовы \fBsignalfd\fP() и \fBsignalfd4\fP() есть только в Linux. .SH ЗАМЕЧАНИЯ Процесс может создать несколько файловых дескрипторов signalfd. Это позволяет принимать различные сигналы через различные файловые дескрипторы (может быть полезно при слежении за файловым дескриптором с помощью \fBselect\fP(2), \fBpoll\fP(2) или \fBepoll\fP(7): прибытие различных сигналов делает готовым различные файловые дескрипторы). Если сигнал указан в \fImask\fP для нескольких файловых дескрипторов, то появление этого сигнала можно прочесть (однократно) из любого файлового дескриптора. .PP Попытки включить \fBSIGKILL\fP и \fBSIGSTOP\fP в маску \fImask\fP просто игнорируются. .PP .\" Маску сигналов, используемую файловым дескриптором signalfd, можно посмотреть в записи соответствующего файлового дескриптора в каталоге процесса \fI/proc/[pid]/fdinfo\fP. Подробности смотрите в \fBproc\fP(5). .SS Ограничения Механизм signalfd нельзя использовать для приёма сигналов, генерируемых синхронно, например сигнала \fBSIGSEGV\fP при доступе по неправильному адресу памяти, или сигнала \fBSIGFPE\fP при математических ошибках. Такие сигналы можно поймать только через обработчик сигнала. .PP .\" Как сказано выше, обычно все сигналы, принимаемые через \fBsignalfd\fP(), блокируются. Если порождается дочерний процесс для выполнения вспомогательной программы (которой не нужен файловый дескриптор signalfd), то после вызова \fBfork\fP(2), обычно, нужно разблокировать эти сигналы перед вызовом \fBexecve\fP(2) для того, чтобы вспомогательная программа видела все сигналы, которые она ожидает увидеть. Однако имейте в виду, что это может быть невозможно, если вспомогательная программа порождается не вами, а где\-то в библиотечной функции, которую может вызывать программа. В таких случаях нужно использовать обычный обработчик сигналов, который пишет в файловый дескриптор, отслеживаемый \fBselect\fP(2), \fBpoll\fP(2) или \fBepoll\fP(7). .SS "Отличия между библиотекой C и ядром" Лежащий в основе системный вызов Linux требует дополнительного аргумента, \fIsize_t sizemask\fP, в котором указывается размер аргумента \fImask\fP. В обёрточной функции glibc \fBsignalfd\fP() нет этого аргумента — требуемое для системного вызова значение добавляется библиотекой. .PP Существуют два системных вызова Linux: \fBsignalfd\fP() и более новый \fBsignalfd4\fP(). В первом системном вызове не реализован аргумент \fIflags\fP. Во втором системном вызове реализованы значения \fIflags\fP, описанные ранее. Начиная с glibc 2.9, обёрточная функция \fBsignalfd\fP() использует \fBsignalfd4\fP(), если он доступен. .SH ДЕФЕКТЫ .\" The fix also was put into 2.6.24.5 В ядрах до версии 3.6.25, поля \fIssi_ptr\fP и \fIssi_int\fP не заполнялись данными, поступающими при посылке сигнала с помощью \fBsigqueue\fP(3). .SH ПРИМЕРЫ Программа, представленная далее, принимает сигналы \fBSIGINT\fP и \fBSIGQUIT\fP через файловый дескриптор signalfd. Она завершает работу при приёме сигнала \fBSIGQUIT\fP. Вот сеанс работы в оболочке, демонстрирующий использование программы: .PP .in +4n .EX $\fB ./signalfd_demo\fP \fB\(haC\fP # Control\-C generates SIGINT Got SIGINT \fB\(haC\fP Got SIGINT \fB\(ha\e\fP # Control\-\e generates SIGQUIT Got SIGQUIT $ .EE .in .SS "Исходный код программы" \& .EX #include #include #include #include #include #define handle_error(msg) \e do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { sigset_t mask; int sfd; struct signalfd_siginfo fdsi; ssize_t s; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); /* Заблокировать сигналы для того, чтобы они не обрабатывались их обработчиками по умолчанию */ if (sigprocmask(SIG_BLOCK, &mask, NULL) == \-1) handle_error("sigprocmask"); sfd = signalfd(\-1, &mask, 0); if (sfd == \-1) handle_error("signalfd"); for (;;) { s = read(sfd, &fdsi, sizeof(fdsi)); if (s != sizeof(fdsi)) handle_error("read"); if (fdsi.ssi_signo == SIGINT) { printf("Получен SIGINT\en"); } else if (fdsi.ssi_signo == SIGQUIT) { printf("Получен SIGQUIT\en"); exit(EXIT_SUCCESS); } else { printf("Прочитан неожидаемый сигнал\en"); } } } .EE .SH "СМ. ТАКЖЕ" \fBeventfd\fP(2), \fBpoll\fP(2), \fBread\fP(2), \fBselect\fP(2), \fBsigaction\fP(2), \fBsigprocmask\fP(2), \fBsigwaitinfo\fP(2), \fBtimerfd_create\fP(2), \fBsigsetops\fP(3), \fBsigwait\fP(3), \fBepoll\fP(7), \fBsignal\fP(7) .SH ЗАМЕЧАНИЯ Эта страница является частью проекта Linux \fIman\-pages\fP версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу \%https://www.kernel.org/doc/man\-pages/. .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан Alexander Golubev , Azamat Hackimov , Hotellook, Nikita , Spiros Georgaras , Vladislav , Yuri Kozlov и Иван Павлов . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .