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

ИМЯ

       eventfd - создаёт файловый дескриптор для уведомления о событиях

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #include <sys/eventfd.h>

       int eventfd(unsigned int initval, int flags);

ОПИСАНИЕ

       Вызов  eventfd() создаёт «объект eventfd», который можно использовать в качестве механизма
       ожидания/уведомления о событиях в приложениях пространства  пользователя  и  ядра.  Объект
       содержит  беззнаковое  64-битный  (uint64_t)  счётчик,  обслуживаемый  ядром. Этот счётчик
       инициализируется значением, указанным в аргументе initval.

       При завершении работы  eventfd()  возвращает  новый  файловый  дескриптор,  который  можно
       использовать для ссылки на объект eventfd.

       Для изменения поведения eventfd() можно использовать следующие значения flags (через OR):

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

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

       EFD_SEMAPHORE (начиная с Linux 2.6.30)
              Предоставляет  семафоро-подобную  семантику  для   чтения   из   нового   файлового
              дескриптора. Смотрите ниже.

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

       Следующие операции могут выполняться над полученным файловым дескриптором eventfd():

       read(2)
              Каждый  завершившийся  без  ошибок  вызов read(2) возвращает 8-байтное целое. Вызов
              read(2) завершается с ошибкой EINVAL, если размер указанного буфера меньше 8 байт.

              The value returned by read(2)  is in host byte order—that is, the native byte order
              for integers on the host machine.

              Семантика  read(2) зависит от значения счётчика eventfd — равно оно нулю или нет, и
              был ли указан флаг EFD_SEMAPHORE при создании файлового дескриптора eventfd:

              •  Если флаг EFD_SEMAPHORE не указан и счётчик eventfd не равен  нулю,  то  read(2)
                 возвращает 8 байт с его значением и значение счётчика сбрасывается в ноль.

              •  Если флаг EFD_SEMAPHORE задан указан и счётчик eventfd не равен нулю, то read(2)
                 возвращает 8 байт, содержащие значение 1, и значение счётчика уменьшается на 1.

              •  Если счётчик eventfd равен нулю во время вызова read(2), то вызов блокируется до
                 тех  пор, пока счётчик станет не равным нулю (время работы read(2) описано выше)
                 или завершается с ошибкой EAGAIN, если файловый дескриптор создан неблокируемым.

       write(2)
              При вызове write(2) из его буфера к счётчику добавляется 8-байтовое целое значение.
              Максимальное  значение,  которое  может  храниться  в  счётчике,  равно наибольшему
              64-битному беззнаковому значению  минус  1  (т.е.,  0xfffffffffffffffe).  Если  при
              добавлении  значение  счётчика  превысит максимум, то write(2) заблокируется до тех
              пор, пока для файлового дескриптора не будет выполнен вызов read(2), или завершится
              с ошибкой EAGAIN, если файловый дескриптор создан неблокируемым.

              Вызов write(2) завершается с ошибкой EINVAL, если размер указанного буфера меньше 8
              байт, или если попытаться записать значение 0xffffffffffffffff.

       poll(2), select(2) (и подобные)
              Возвращённый файловый дескриптор поддерживает poll(2) (и, аналогично,  epoll(7))  и
              select(2) следующим образом:

              •  Файловый дескриптор доступен для чтения (в select(2) аргумент readfds; в poll(2)
                 флаг POLLIN), если счётчик больше 0.

              •  Файловый дескриптор доступен  для  записи  (в  select(2)  аргумент  writefds;  в
                 poll(2) флаг POLLOUT), если можно записать значение равное, как минимум, "1" без
                 блокировки.

              •  If an overflow of the counter value was detected, then select(2)  indicates  the
                 file  descriptor  as  being  both  readable and writable, and poll(2)  returns a
                 POLLERR event.  As noted  above,  write(2)   can  never  overflow  the  counter.
                 However  an  overflow can occur if 2^64 eventfd "signal posts" were performed by
                 the KAIO subsystem (theoretically possible, but practically  unlikely).   If  an
                 overflow  has  occurred,  then  read(2)  will return that maximum uint64_t value
                 (i.e., 0xffffffffffffffff).

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

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

       Копия  файлового  дескриптора,  созданного  eventfd(),  наследуется  потомком, созданным с
       помощью fork(2). Копия файлового  дескриптора  связывается  с  тем  же  объектом  eventfd.
       Файловые  дескрипторы,  созданные  eventfd(),  сохраняются  при  вызове execve(2), если не
       указан флаг close-on-exec.

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

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

ОШИБКИ

       EINVAL В flags указано неподдерживаемое значение.

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

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

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

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

ВЕРСИИ

       eventfd()  is available since Linux 2.6.22.  Working support is provided since glibc  2.8.
       The eventfd2()  system call (see NOTES) is available since Linux 2.6.27.  Since glibc 2.9,
       the eventfd()  wrapper will employ the eventfd2()  system call, if it is supported by  the
       kernel.

АТРИБУТЫ

       Описание терминов данного раздела смотрите в attributes(7).

       ┌───────────────────────────────────────────────────────┬──────────────────────┬──────────┐
       │ИнтерфейсАтрибутЗначение │
       ├───────────────────────────────────────────────────────┼──────────────────────┼──────────┤
       │eventfd()                                              │ Безвредность в нитях │ MT-Safe  │
       └───────────────────────────────────────────────────────┴──────────────────────┴──────────┘

СТАНДАРТЫ

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

ЗАМЕЧАНИЯ

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

       При использовании в ядре файловый дескриптор eventfd может предоставлять мост из  ядерного
       в  пользовательское пространство, позволяя например работать, подобно KAIO ( ядерный AIO),
       сигнализируя, что завершена какая-то операция над файловым дескриптором.

       Важным моментом файлового дескриптора eventfd является то, что за ним можно следить как за
       обычным файловым дескриптором с помощью select(2), poll(2) или epoll(7). Это означает, что
       приложение может одновременно отслеживать готовность "обычных" файлов и готовность  других
       механизмов  ядра,  которые  поддерживают  интерфейс eventfd. (Без интерфейса eventfd() эти
       механизмы невозможно мультиплексировать через select(2), poll(2) или epoll(7).)

       Текущее значение счётчика eventfd можно найти  в  записи  для  соответствующего  файлового
       дескриптора в каталоге процесса /proc/pid/fdinfo. Подробности смотрите в proc(5).

   Отличия между библиотекой C и ядром
       Основу составляют два системных вызова Linux: eventfd() и более новый eventfd2(). В первом
       системном вызове не  реализован  аргумент  flags.  Последний  системный  вызов  использует
       значения   flags,   которые  были  описаны  ранее.  Обёрточная  функция  glibc  использует
       eventfd2(), если он доступен.

   Дополнительные возможности glibc
       В библиотеке GNU C определён дополнительный тип и две функции, которые пытаются  устранить
       сложности чтения и записи из файлового дескриптора eventfd:

           typedef uint64_t eventfd_t;

           int eventfd_read(int fd, eventfd_t *value);
           int eventfd_write(int fd, eventfd_t value);

       Функции  выполняют операции чтения и записи из файлового дескриптора eventfd, и возвращают
       0, если передано правильное количество байт и -1 в противном случае.

ПРИМЕРЫ

       Следующая программа создаёт файловый дескриптор eventfd и затем создаёт дочерний  процесс.
       Пока  родительский процесс на короткое время засыпает, потомок пишет все числа, переданные
       в командной строке программы, в файловый дескриптор eventfd. Когда  родитель  просыпается,
       он читает их из файлового дескриптора eventfd.

       Пример сеанса работы с программой:

           $ ./a.out 1 2 4 7 14
           Child writing 1 to efd
           Child writing 2 to efd
           Child writing 4 to efd
           Child writing 7 to efd
           Child writing 14 to efd
           Child completed write loop
           Parent about to read
           Parent read 28 (0x1c) from efd

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

       #include <err.h>
       #include <inttypes.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/eventfd.h>
       #include <unistd.h>

       int
       main(int argc, char *argv[])
       {
           int       efd;
           uint64_t  u;
           ssize_t   s;

           if (argc < 2) {
               fprintf(stderr, "Использование: %s <num>...\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           efd = eventfd(0, 0);
           if (efd == -1)
               err(EXIT_FAILURE, "eventfd");

           switch (fork()) {
           case 0:
               for (size_t j = 1; j < argc; j++) {
                   printf("Child writing %s to efd\n", argv[j]);
                   u = strtoull(argv[j], NULL, 0);
                           /* в strtoull() разрешены различные основания */
                   s = write(efd, &u, sizeof(uint64_t));
                   if (s != sizeof(uint64_t))
                       err(EXIT_FAILURE, "write");
               }
               printf("Child completed write loop\n");

               exit(EXIT_SUCCESS);

           default:
               sleep(2);

               printf("Parent about to read\n");
               s = read(efd, &u, sizeof(uint64_t));
               if (s != sizeof(uint64_t))
                   err(EXIT_FAILURE, "read");
               printf("Parent read %"PRIu64" (%#"PRIx64") from efd\n", u, u);
               exit(EXIT_SUCCESS);

           case -1:
               err(EXIT_FAILURE, "fork");
           }
       }

СМ. ТАКЖЕ

       futex(2),  pipe(2), poll(2), read(2), select(2), signalfd(2), timerfd_create(2), write(2),
       epoll(7), sem_overview(7)

ПЕРЕВОД

       Русский   перевод   этой    страницы    руководства    был    сделан    Azamat    Hackimov
       <azamat.hackimov@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⟩.