title: epoll_create(2)

summary: открывает файловый дескриптор epoll

text:
# epoll_create(2)

## ИМЯ
epoll_create, epoll_create1 - открывает файловый дескриптор epoll

## ОБЗОР

```
#include <sys/epoll.h>
```

```
int epoll_create(int size);
int epoll_create1(int flags);
```

## ОПИСАНИЕ
Вызов epoll_create() создаёт новый экземпляр epoll(7). Начиная с Linux 2.6.8 аргумент size игнорируется, но должен быть больше нуля; смотрите ЗАМЕЧАНИЯ далее.

epoll_create() возвращает дескриптор файла, указывающий на новый экземпляр epoll. Он используется для всех последующих вызовов к интерфейсу epoll. По окончанию использования дескриптор файла, возвращаемый epoll_create(), должен быть закрыт с помощью close(2). Когда все файловые дескрипторы, указывающие на экземпляр epoll, будут закрыты, ядро уничтожит экземпляр и освободит связанные с ним ресурсы для повторного использования.

### epoll_create1()
Если flags равно 0, то, если не учитывать, что устаревший аргумент size не используется, epoll_create1() выполняет тоже что и epoll_create(). Для различного поведения во flags могут включаться:

EPOLL_CLOEXEC

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

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении данные системные вызовы возвращают неотрицательный файловый дескриптор. При ошибке возвращается -1 и errno устанавливается в соответствующее значение.

## ОШИБКИ
EINVAL

Аргумент size содержит отрицательное значение.

EINVAL

(epoll_create1()) Указано неверное значение в flags.

EMFILE

Был достигнут пользовательский предел на количество экземпляров epoll, налагаемый /proc/sys/fs/epoll/max_user_instances. Подробней см. в epoll(7).

EMFILE

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

ENFILE

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

ENOMEM

Недостаточно памяти для создания объекта ядра.

## ВЕРСИИ
Вызов epoll_create() был добавлен в ядро версии 2.6. В glibc соответствующая функция появилась в версии 2.3.2.

Вызов epoll_create1() был добавлен в ядро версии 2.6.27. В glibc соответствующая функция появилась в версии 2.9.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов epoll_create() есть только в Linux.

## ЗАМЕЧАНИЯ
В первоначальной реализации epoll_create() аргумент size уведомлял ядро о количестве файловых дескрипторов, которые вызывающий предполагал добавить в экземпляр epoll. Ядро использовало эту информацию для оценки требуемого количества памяти при начальном размещении внутренних структур данных, описывающих события (если требовалось, ядро выделяло больше места, если вызывающий превышал значение, указанное в size). Сейчас, эта оценка больше не требуется (ядро динамически выделяет место под структуры данных), но значение size всё равно должно быть больше нуля — для обеспечения обратной совместимости приложений с новым epoll для работы на старых ядрах.

## СМОТРИТЕ ТАКЖЕ
close(2), epoll_ctl(2), epoll_wait(2), epoll(7)


package: man-pages-ru

title: epoll_ctl(2)

text:
# epoll_ctl(2)

## ИМЯ
epoll_ctl - интерфейс управления файловым дескриптором epoll

## ОБЗОР
\#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

## ОПИСАНИЕ
Данный системный вызов, используется для добавления, изменения или удаления записей в списке interest экземпляра epoll(7), на который указывает файловый дескриптор epfd. Он запрашивает выполнение операции op для файлового дескриптора назначения fd.

Допустимые значения аргумента op:

EPOLL_CTL_ADD

Добавить fd в список interest и связать настройки, указанные в event, с внутренним файлом, связанным с fd.

EPOLL_CTL_MOD

Изменить настройки, связанные с fd в списке interest, на новые, указанные в event.

EPOLL_CTL_DEL

Удалить (отменить регистрацию) файлового дескриптора назначения fd из списка interest. Значение event игнорируется и может быть NULL (но смотрите ДЕФЕКТЫ далее).

Аргумент event описывает объект, связанный с файловым дескриптором fd. Структура struct epoll_event определена так:

```
typedef union epoll_data {

    void        *ptr;

    int          fd;

    uint32_t     u32;

    uint64_t     u64;
} epoll_data_t;
struct epoll_event {

    uint32_t     events;      /* События epoll */

    epoll_data_t data;        /* Переменная для данных пользователя */
};
```

Поле events является битовой маской, составляемой из объединяемых (OR) нуля и более следующих возможных типов событий:

EPOLLIN

Связанный файл доступен для чтения с помощью read(2).

EPOLLOUT

Связанный файл доступен для записи с помощью write(2).

EPOLLRDHUP (начиная с Linux 2.6.17)

Одна из сторон потокового сокета закрыла соединение или выключила записывающую часть соединения (этот флаг особенно полезен при написании простого кода для обнаружения отключения стороны с помощью слежения Edge Triggered).

EPOLLPRI

Исключительное состояние файлового дескриптора. Смотрите описание POLLPRI в poll(2).

EPOLLERR

Возникло ошибочное состояние связанного файлового дескриптора. Это событие также возникает на пишущей стороне канала, когда читающий конец закрылся. Вызов epoll_wait(2) всегда будет сообщать об этом событии; его не нужно устанавливать в events.

EPOLLHUP

Произошло зависание связанного файлового дескриптора. Вызов epoll_wait(2) будет всегда ждать этого события; его не нужно указывать в events.

Заметим, что при чтении из канала, такого как канал (pipe) или потоковый сокет, это событие всего-навсего показывает, что партнёр закрыл канал со своего конца. Дальнейшее чтение из канала будет возвращать 0 (конец файла) только после потребления всех неполученных данных в канале.

EPOLLET

Установить поведение Edge Triggered для связанного файлового дескриптора. Поведение по умолчанию для epoll равно Level Triggered. Более подробное описание архитектуры распределения событий Edge и Level Triggered смотрите в epoll(7).

EPOLLONESHOT (начиная с Linux 2.6.2)

Установить однократное получение для связанного файлового дескриптора. Это означает, что после извлечения события с помощью epoll_wait(2) со связанным дескриптором приём отключается и о других событиях интерфейс epoll сообщать не будет. Пользователь должен вызвать epoll_ctl() с операцией EPOLL_CTL_MOD для переустановки новой маски событий для файлового дескриптора.

EPOLLWAKEUP (начиная с Linux 3.5)

Если флаги EPOLLONESHOT и EPOLLET сброшены и процесс имеет мандат CAP_BLOCK_SUSPEND, то убедитесь, что система не находится в режиме «suspend» или «hibernate», пока это событие ожидает обработки или обрабатывается. Событие считается «обрабатывающимся» начиная с момента, когда оно возвращается вызовом epoll_wait(2) и до следующего вызова epoll_wait(2) для того же файлового дескриптора epoll(7), закрытия этого файлового дескриптора, удаление файлового дескриптора события с помощью EPOLL_CTL_DEL или сброс EPOLLWAKEUP для файлового дескриптора события с помощью EPOLL_CTL_MOD. Также смотрите ДЕФЕКТЫ.

EPOLLEXCLUSIVE (начиная с Linux 4.5)

Установить единоличный режим пробуждения файлового дескриптора epoll, присоединённого к целевому файловому дескриптору fd. При появлении события пробуждения и к целевому файлу присоединены несколько файловых дескрипторов epoll с помощью EPOLLEXCLUSIVE, то события получат один или несколько файловых дескрипторов epoll через epoll_wait(2). По умолчанию в этом случае (если EPOLLEXCLUSIVE не установлен) все файловые дескрипторы epoll получают событие. Таким образом EPOLLEXCLUSIVE в некоторых случаях помогает избежать проблем стадной работы.

Если один файловый дескриптор указан в нескольких экземплярах epoll, и одни имеют флаг EPOLLEXCLUSIVE, а другие нет, то события получат все экземпляры epoll, у которых не указан EPOLLEXCLUSIVE, и, как минимум, один экземпляр epoll, у которого есть задан EPOLLEXCLUSIVE.

Следующие значения можно указывать вместе с EPOLLEXCLUSIVE: EPOLLIN, EPOLLOUT, EPOLLWAKEUP и EPOLLET. Также можно указывать EPOLLHUP и EPOLLERR, но они не обязательны: как обычно, события всегда приходят, если они возникают, независимо указаны ли они в events. При указании других значений в events возникает ошибка EINVAL.

EPOLLEXCLUSIVE можно использовать только в операции EPOLL_CTL_ADD; попытка использовать его в EPOLL_CTL_MOD вызывает ошибку. Если EPOLLEXCLUSIVE установлен с помощью epoll_ctl(), то последующая EPOLL_CTL_MOD с той же парой epfd, fd вызывает ошибку. Вызов epoll_ctl(), в котором указан EPOLLEXCLUSIVE в events и целевой файловый дескриптор fd в качестве экземпляра epoll, также вызывает ошибку. Во всех случаях возникает ошибка EINVAL.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении epoll_ctl() возвращается ноль. При возникновении ошибок epoll_ctl() возвращает -1 и устанавливает errno в соответствующее значение.

## ОШИБКИ
EBADF

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

EEXIST

Значение op равно EPOLL_CTL_ADD, и указанный файловый дескриптор fd уже зарегистрирован в данном экземпляре epoll.

EINVAL

Значение epfd не является файловым дескриптором epoll, или значение fd равно epfd, или запрашиваемая операция op не поддерживается данным интерфейсом.

EINVAL

Указан недопустимый тип события, так как в events установлен EPOLLEXCLUSIVE.

EINVAL

Значение op равно EPOLL_CTL_MOD и events содержит EPOLLEXCLUSIVE.

EINVAL

Значение op равно EPOLL_CTL_MOD, а ранее для этой пары epfd, fd был применён флаг EPOLLEXCLUSIVE.

EINVAL

Флаг EPOLLEXCLUSIVE указан в event и fd ссылается на экземпляр epoll.

ELOOP

Значение fd ссылается на экземпляр epoll и эта операция EPOLL_CTL_ADD привела бы к зацикливанию экземпляров epoll, отслеживающих один другого.

ENOENT

В op было указано EPOLL_CTL_MOD или EPOLL_CTL_DEL, а fd не было зарегистрировано в данном экземпляре epoll.

ENOMEM

Недостаточно памяти для обработки запрошенной управляющей операции op.

ENOSPC

При попытке регистрации (EPOLL_CTL_ADD) нового файлового дескриптора в экземпляре достигнут предел, накладываемый /proc/sys/fs/epoll/max_user_watches. Подробней см. в epoll(7).

EPERM

Файл назначения fd не поддерживает epoll. Эта ошибка может возникнуть, если fd ссылается на, например, обычный файл или каталог.

## ВЕРСИИ
Системный вызов epoll_ctl() был добавлен в ядро версии 2.6.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов epoll_ctl() есть только в Linux. В glibc соответствующая функция появилась в версии 2.3.2.

## ЗАМЕЧАНИЯ
Интерфейс epoll поддерживает все файловые дескрипторы, которые поддерживает poll(2).

## ДЕФЕКТЫ
В ядрах до версии 2.6.9 для операции EPOLL_CTL_DEL в event требовался указатель со значением не равным null, хотя этот аргумент игнорировался. Начиная с Linux 2.6.9, при EPOLL_CTL_DEL в event можно указывать NULL. В переносимых приложениях, которые должны быть работоспособными в системах на ядрах до 2.6.9, в event нужно указывать указатель со значением не равным null.

Если в flags указан EPOLLWAKEUP, но вызывающий не имеет мандата CAP_BLOCK_SUSPEND, то флаг EPOLLWAKEUP просто игнорируется. Такое неуместное поведение необходимо, так как в первоначальной реализации не выполнялась проверка корректности аргумента flags, и добавление EPOLLWAKEUP с проверкой того, что вызов завершился с ошибкой, если вызывающий не имеет мандата CAP_BLOCK_SUSPEND, привело к поломке не одного существующего пользовательского приложения, которое произвольно устанавливало (и зря) этот бит. Корректное приложение должно дважды проверить, что имеет мандат CAP_BLOCK_SUSPEND, если пытается использовать флаг EPOLLWAKEUP.

## СМОТРИТЕ ТАКЖЕ
epoll_create(2), epoll_wait(2), poll(2), epoll(7)


title: epoll_wait(2)

text:
# epoll_wait(2)

## ИМЯ
epoll_wait, epoll_pwait - ждать события ввода/вывода на файловом дескрипторе epoll

## ОБЗОР

```
#include <sys/epoll.h>
```

```
int epoll_wait(int epfd, struct epoll_event *events,
               int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events,
               int maxevents, int timeout,
               const sigset_t *sigmask);
```

## ОПИСАНИЕ
Системный вызов epoll_wait() ожидает события на экземпляре epoll(7), на который указывает файловый дескриптор epfd. Область памяти, на которую указывает events, будет содержать события, доступные для вызываемого. Вызов epoll_wait() может вернуть до maxevents событий. Параметр maxevents должен быть больше нуля.

В аргументе timeout указывается количество миллисекунд, на которые будет заблокирован epoll_wait(). Время отслеживается по часам CLOCK_MONOTONIC. Вызов будет заблокирован пока:

- событие не будет доставлено в файловый дескриптор;

- вызов не прервётся обработчиком сигнала;

- не истечёт время ожидания.

Заметим, что интервал timeout будет округлён в соответствии с точностью системных часов, а задержки ядерного планирования приведут к тому, что интервал блокировки может быть немного больше. Если присвоить timeout значение -1, то epoll_wait() блокируется навсегда; если значение timeout равно 0, то epoll_wait() сразу завершает работу, даже если никаких событий не произошло.

Структура struct epoll_event определена так:

```
typedef union epoll_data {

    void    *ptr;

    int      fd;

    uint32_t u32;

    uint64_t u64;
} epoll_data_t;
struct epoll_event {

    uint32_t     events;    /* События epoll */

    epoll_data_t data;      /* Переменная для данных пользователя */
};
```

Поле data в каждой возвращаемой структуре содержит те же данные, которые были указаны в самом последнем вызове epoll_ctl(2) (EPOLL_CTL_ADD, EPOLL_CTL_MOD) для соответствующего открытого описания файла. В поле events содержится битовое поле возвращаемого события.

### epoll_pwait()
Отношения между epoll_wait() и epoll_pwait() аналогичны родству select(2) и pselect(2): как pselect(2), epoll_pwait() позволяет приложению безопасно ждать, пока файловый дескриптор не станет готов или пока не будет получен сигнал.

Вызов epoll_pwait():

```
ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);
```

эквивалентен атомарному выполнению следующих вызовов:

```
sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = epoll_wait(epfd, &events, maxevents, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
```

Аргумент sigmask может быть равен NULL — в этом случае epoll_pwait() эквивалентен epoll_wait().

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При нормальном выполнении epoll_wait() возвращает количество файловых дескрипторов, готовых для запросов ввода-вывода, или ноль, если ни один файловый дескриптор не стал готов за отведённые timeout миллисекунд. При возникновении ошибки epoll_wait() возвращает -1 и устанавливает errno в соответствующее значение.

## ОШИБКИ
EBADF

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

EFAULT

Память, указанная events, недоступна на запись из-за прав доступа.

EINTR

Вызов был прерван обработчиком сигнала до возникновения любого из запрошенных событий или истечения timeout; см. signal(7).

EINVAL

epfd не является файловым дескриптором epoll, или maxevents меньше или равно нулю.

## ВЕРСИИ
Вызов epoll_wait() был добавлен в ядро версии 2.6. В glibc соответствующая функция появилась в версии 2.3.2.

Вызов epoll_pwait() был добавлен в ядро Linux 2.6.19. В glibc соответствующая функция появилась в версии 2.6.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов epoll_wait() есть только в Linux.

## ЗАМЕЧАНИЯ
Пока одна нить блокирована в вызове epoll_wait(), в другой нити возможно добавить файловый дескриптор, который будет ожидаться экземпляром epoll. Как только новый файловый дескриптор станет готовым, это разблокирует вызов epoll_wait().

Если готово более maxevents файловых дескрипторов при вызове epoll_wait(), то последующие вызовы epoll_wait() циклически обработают весь набор готовых файловых дескрипторов. Такое поведение помогает избежать голодания — когда процесс не уведомляется, что дополнительные файловые дескрипторы готовы, так как он нацелен на набор файловых дескрипторов, про которые уже известно об их готовности.

Заметим, что возможно вызвать epoll_wait() для экземпляра epoll, чей список interest ещё пуст (или чей список interest станет пустым, так как файловые дескрипторы закрыты или удалены из interest в другой нити). Вызов будет заблокирован до тех пор, пока какой-нибудь файловый дескриптор не будет добавлен в список interest (в другой нити) и этот файлоый дескриптор не станет готовым.

## ДЕФЕКТЫ
В ядрах до версии 2.6.37, если значение timeout больше чем приблизительное LONG_MAX / HZ секунд, то оно воспринимается как -1 (т.е., бесконечность). То есть, например, в системе, где sizeof(long) равно 4 и значение ядра HZ равно 1000, задержка более 35,79 минут считается бесконечностью.

### Отличия между библиотекой C и ядром
Ядерный системный вызов epoll_pwait() имеет шестой аргумент, size_t sigsetsize, в котором указывается размер аргумента sigmask в байтах. В обёрточной функции glibc epoll_pwait() в этом аргументе передаётся постоянная величина (равная sizeof(sigset_t)).

## СМОТРИТЕ ТАКЖЕ
epoll_create(2), epoll_ctl(2), epoll(7)


eventfd

title: eventfd(2)

text:
# eventfd(2)

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

## ОБЗОР
\#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)

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

До версии Linux 2.6.26 аргумент flags не использовался, и должен быть равен нулю.

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

read(2)

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

Возвращаемое read(2) значение имеет порядок байт узла, т. е., используемый порядок байт для целых на машине узла.

Семантика 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" без блокировки.

- Если обнаружено переполнение счётчика, то select(2) указывает на файловый дескриптор, доступный на чтение и запись, и poll(2) возвращает событие POLLERR. Как упоминалось ранее, write(2) никогда не может вызвать переполнение счётчика. Однако переполнение может произойти, если подсистемой KAIO выполнится (возможно теоретически) 2^64 "передач сигналов" eventfd. Если переполнение произошло, то read(2) вернёт максимальное значение типа uint64_t (т.е., 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() доступен в Linux начиная с ядра 2.6.22. Поддержка в glibc появилась в версии 2.8. Системный вызов eventfd2() (см. ЗАМЕЧАНИЯ) доступен в Linux начиная с ядра 2.6.27. В glibc версии 2.9 в обёртке eventfd() используется системный вызов eventfd2(), если он поддерживается ядром.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в 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 <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>             /* определение uint64_t */
#define handle_error(msg) \

    do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{

    int efd, j;

    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)

        handle_error("eventfd");

    switch (fork()) {

    case 0:

        for (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))

                handle_error("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))

            handle_error("read");

        printf("Parent read %llu (0x%llx) from efd\n",

                (unsigned long long) u, (unsigned long long) u);

        exit(EXIT_SUCCESS);

    case -1:

        handle_error("fork");

    }
}
```

## СМОТРИТЕ ТАКЖЕ
futex(2), pipe(2), poll(2), read(2), select(2), signalfd(2), timerfd_create(2), write(2), epoll(7), sem_overview(7)


execve

title: execve(2)

summary: выполнить программу

text:
# execve(2)

## ИМЯ
execve - выполнить программу

## ОБЗОР
\#include <unistd.h>

int execve(const char *pathname, char *const argv[],

char *const envp[]);

## ОПИСАНИЕ
Вызов execve выполняет программу, задаваемую pathname. При этом программа, выполняющаяся вызвавшим процессом, замещается новой программой, заново инициализируется стек, куча и сегменты данных (инициализированные и не инициализированные).

В pathname должно быть указано имя двоичного исполняемого файла или сценарий, начинающийся со строки вида:

```
#!интерпретатор [необязательный параметр]
```

Подробней о сценариях написано далее в «Интерпретируемые сценарии».

argv — это массив строковых параметров, передаваемых новой программе. По соглашению, в первой строке (т. е., argv[0]) должно содержаться имя файла, относящееся к запускаемой программе. envp — это массив строк в формате ключ=значение, которые передаются новой программе в качестве окружения (environment). Оба массива argv и envp завершаются указателем null.

К массиву параметров и окружению можно обратиться из вызываемой программой главной функции, если она определена как:

```
int main(int argc, char *argv[], char *envp[])
```

Однако заметим, что использование третьего аргумента главной функции не определено в POSIX.1; согласно POSIX.1, окружение должно быть доступно через внешнюю переменную environ(7).

При успешном выполнении execve() управление не возвращается, а код, инициализированные данные, неинициализированные данные (bss) и стек вызвавшего процесса перезаписываются содержимым загруженной программы.

Если текущая программа выполнялась под управлением ptrace, то после успешного вызова execve() ей посылается сигнал SIGTRAP.

Если у файла программы, на который ссылается pathname, установлен бит set-user-ID, то фактический идентификатор пользователя вызывающего процесса меняется на идентификатор владельца файла программы. Точно также, если на файле программы установлен бит set-group-ID, то фактический идентификатор группы вызывающего процесса становится равным группе, которой принадлежит файл программы.

Вышеупомянутые преобразования эффективных IDs не выполняются (т. е., биты set-user-ID и set-group-ID игнорируются), если что-либо из следующего истинно:

- установлен атрибут no_new_privs для вызывающей нити (смотрите prctl(2));

- подлежащая файловая система смонтирована с nosuid (флаг MS_NOSUID для mount(2)); или

- вызывающий процесс выполняется под контролем ptrace.

Также игнорируются мандаты файла программы (смотрите capabilities(7)), если что-то из вышеперечисленного истинно.

Фактический идентификатор пользователя процесса копируется в сохранённый идентификатор пользователя (set-user-ID), также фактический идентификатор группы копируется в сохранённый идентификатор группы (set-group-ID). Это копирование выполняется после изменения любого фактического идентификатора, которое происходит из-за выставленных бит режима set-user-ID и set-group-ID.

Реальные UID и GID процесса, а также его дополнительные ID групп не изменяются при вызове execve().

Если исполняемый файл является динамически-скомпонованным файлом в формате a.out, содержащим заглушки для динамических библиотек, то в начале выполнения этого файла вызывается динамический компоновщик Linux ld.so(8), который начинает выполнение с загрузки общих объектов в память и компонует их с исполняемым файлом.

Если исполняемый файл является динамически компонуемым файлом в формате ELF, то для загрузки необходимых общих объектов используется интерпретатор, указанный в сегменте PT_INTERP. Для программ, скомпонованных с glibc, обычно это /lib/ld-linux.so.2 (смотрите ld-linux.so(8)).

При вызове execve() сохраняются все свойства процесса, за исключением:

- Значения обработчиков всех захватываемых сигналов сбрасываются в значения по умолчанию (signal(7)).

- Любой альтернативный стек сигнала не сохраняется (sigaltstack(2)).

- Проецирование памяти не сохраняется (mmap(2)).

- Подключённые общие сегменты памяти System V отключаются (shmat(2)).

- Области общей памяти POSIX становятся неспроецированными (shm_open(3)).

- Открытые дескрипторы в очереди сообщений POSIX закрываются (mq_overview(7)).

- Все открытые именные семафоры POSIX закрываются (sem_overview(7)).

- Таймеры POSIX не сохраняются (timer_create(2)).

- Все открытые потоки каталогов (directory streams) закрываются (opendir(3)).

- Блокировки памяти не сохраняются (mlock(2), mlockall(2)).

- Обработчики завершения работы (exit handlers) не сохраняются (atexit(3), on_exit(3)).

- Окружения плавающей точки сбрасываются в настройки по умолчанию (fenv(3)).

В POSIX.1 определён список сохраняемых свойств процесса. Следующие свойства процесса, имеющиеся только в Linux, также не сохраняются при execve():

- Устанавливается флаг PR_SET_DUMPABLE (prctl(2)), если выполняемая программа не имеет установленных бит set-user-ID или set-group-ID; в противном случае он очищается.

- Флаг PR_SET_KEEPCAPS (prctl(2)) очищается.

- (Начиная с Linux 2.4.36 / 2.6.23) Если выполняется программа с установленным битом set-user-ID или set-group-ID, то сигнал о смерти родителя, установленный prctl(2) с флагом PR_SET_PDEATHSIG, очищается.

- Имя процесса, установленное через prctl(2) PR_SET_NAME (и отображаемое ps -o comm), изменяется на имя нового исполняемого файла.

- Флаг SECBIT_KEEP_CAPS securebits очищается. Смотрите capabilities(7).

- Сигнал завершения (termination signal) устанавливается в SIGCHLD (clone(2)).

- Таблица файловых дескрипторов не является общей, отменяется действие флага CLONE_FILES у clone(2).

Также стоит учитывать следующее:

- Все нити (threads), отличные от вызывающей, уничтожаются execve(). Мьютексы, условные переменные и другие объекты pthreads не сохраняются.

- При запуске программы выполняется эквивалент setlocale(LC_ALL, "C").

- В POSIX.1 указано, что действия по отношению к любым игнорируемым или имеющим настройку по умолчанию сигналам, остаются неизменными. В POSIX.1 есть одно исключение: если SIGCHLD игнорируется, то реализация может оставить обработку сигнала (disposition) неизменной или вернуть настройку по умолчанию; в Linux используется первое.

- Все ожидающие выполнения асинхронные операции ввода-вывод отменяются (aio_read(3), aio_write(3)).

- Как происходит обработка мандатов (capabilities) при вызове execve(), см. capabilities(7).

- По умолчанию, после execve() файловые дескрипторы остаются открытыми. Файловые дескрипторы, помеченные как close-on-exec (закрывать при запуске), закрываются; смотрите описание FD_CLOEXEC в fcntl(2) (если файловый дескриптор закрыт, это приводит к освобождению всех имеющихся блокировок, полученных на соответствующий файл данным процессом. Подробней смотрите fcntl(2)). В POSIX.1 сказано, что если бы файловые дескрипторы 0, 1 и 2 были закрыты после успешного вызова execve(), и процесс получил бы привилегии из-за установленных битов режима set-user-ID или set-group_ID на исполняемом файле, то система смогла бы открыть произвольный файл для каждого из этих дескрипторов. Считается, что переносимая программа, с привилегиями или без, не может рассчитывать, что эти три файловых дескриптора будут оставаться закрытыми после execve().

### Интерпретируемые сценарии
Интерпретируемый сценарий — это текстовый файл, у которого установлен бит выполнения и первая строка имеет вид:

```
#!интерпретатор [необязательный параметр]
```

В поле интерпретатор должно быть указано имя файла запуска.

Если в аргументе pathname для execve() указан интерпретируемый сценарий, то интерпретатор будет вызван со следующими параметрами:

```
интерпретатор [необязательный параметр] pathname параметр…
```

где pathname — абсолютный путь к файлу, указанному в первом аргументе execve() и параметр... — последовательность слов, указываемых аргументом argv в execve() начиная с argv[1]. Заметим, что нельзя получить argv[0], переданный в вызов execve().

В целях переносимости, необязательный параметр должен быть или пустым, или задаваться одним словом (т.е., не должен содержать пробельных символов); см. ЗАМЕЧАНИЯ далее.

Начиная с Linux 2.6.28 ядро позволяет интерпретатору сценария самому быть сценарием. Это разрешение рекурсивно (до четырёх раз), поэтому сценарий может быть сценарием, который интерпретируется сценарием и т. д.

### Ограничения на размер параметров и окружения
Большинство реализаций UNIX накладывает некоторые ограничения на полный размер параметра командной строки (argv) и окружения (envp), которые можно передать новой программе. POSIX.1 позволяет реализации объявить это ограничение через константу ARG_MAX (определённую в <limits.h> или сделать её доступной во время выполнения через вызов sysconf(_SC_ARG_MAX)).

В ядре Linux до версии 2.6.23 размер памяти, используемый для хранения окружения и строк параметров, был ограничен 32 страницами (определялся ядерной константой MAX_ARG_PAGES). На архитектурах с 4-КиБ размером страницы это давало максимальный размер в 128 КиБ.

Начиная с ядра версии 2.6.23, большинство архитектур поддерживают предельный размер, высчитываемый от мягкого ограничения ресурса RLIMIT_STACK (см. getrlimit(2)), который действует во время вызова execve(). (Исключение составляют архитектуры без механизма управления памятью: в них ограничение рассчитывается как и до версии 2.6.23.) Это изменение позволяет программам иметь больший список параметров и/или окружения. Для этих архитектур полный размер ограничен до 1/4 разрешённого размера стека. (Накладываемое ограничение в 1/4 позволяет новой программе всегда иметь некоторое пространство под стек.) Кроме того, полный размер ограничен 3/4 значения ядерной константы _STK_LIM (8 мибибайт). Начиная с Linux версии 2.6.25, ядро также отводит нижние 32 страницы для этого предельного размера, поэтому, даже когда RLIMIT_STACK задан слишком низко, приложения гарантированно получат, по крайней мере, столько же пространства под параметры и окружение, сколько бы они получили при работе с Linux 2.6.23 и ранее. (Это гарантия не обеспечивалась в Linux 2.6.23 и 2.6.24.) Также, размер строки ограничен 32 страницами (ядерная константа MAX_ARG_STRLEN), а максимальное число строк может быть 0x7FFFFFFF.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении execve() не возвращает управление. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

## ОШИБКИ
E2BIG

Слишком большое общее количество байт для окружения (envp) и списка параметров (argv).

EACCES

В одном из каталогов префикса pathname или интерпретатора не разрешён поиск (смотрите также path_resolution(7)).

EACCES

Файл или интерпретатор не являются обычным файлом.

EACCES

Не установлен бит выполнения на файле или сценарии или интерпретаторе ELF.

EACCES

Файловая система смонтирована с noexec.

EAGAIN (начиная с Linux 3.1)

Из-за изменения реального UID одним из вызовов set*uid() ранее, вызывающий всё ещё превышает ограничитель ресурса RLIMIT_NPROC (смотрите setrlimit(2)). Подробное объяснение этой ошибки смотрите в ЗАМЕЧАНИЯХ.

EFAULT

Значение pathname или один из указателей в векторах argv или envp указывает за пределы доступного адресного пространства.

EINVAL

Исполняемый ELF-файл содержит более одного сегмента PT_INTERP (т.е., в нём указано более одного интерпретатора).

EIO

Произошла ошибка ввода-вывода.

EISDIR

Интерпретатор ELF является каталогом.

ELIBBAD

Не распознан формат интерпретатора ELF.

ELOOP

Во время определения pathname, имени сценария или интерпретатора ELF встретилось слишком много символьных ссылок.

ELOOP

Достигнут предел количества рекурсий при интерпретации сценария (смотрите «Интерпретируемые сценарии» выше). До Linux 3.8 для этого случая возвращалась ошибка ENOEXEC.

EMFILE

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

ENAMETOOLONG

Слишком длинное значение аргумента pathname.

ENFILE

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

ENOENT

Файл pathname, сценарий или интерпретатор ELF не существует, или не найдена динамическая библиотека, необходимая для файлового интерпретатора.

ENOEXEC

Не распознан формат исполняемого файла, он не подходит для архитектуры, или имеет ошибки в формате, из-за чего не может быть выполнен.

ENOMEM

Недостаточное количество памяти ядра.

ENOTDIR

Компонент пути в pathname, сценарии или интерпретаторе ELF в действительности не является каталогом.

EPERM

Файловая система смонтирована с nosuid, пользователь не является суперпользователем, а на файле установлен бит set-user-ID или set-group-ID.

EPERM

Над процессом выполняется трассировка, пользователь не имеет прав суперпользователя, а у файла установлен бит set-user-ID или set-group-ID.

EPERM

Приложение «с недоработанными мандатами» (capability-dumb) не получило бы полный набор ограничивающих мандатов, разрешаемых исполняемым файлом. Смотрите capabilities(7).

ETXTBSY

Заданный исполняемый файл был открыт на запись одним или более процессов.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD. В POSIX не описано поведение #!, но это существует (в нескольких вариантах) в других системах UNIX.

## ЗАМЕЧАНИЯ
Иногда, про execve() (и подобные функции, описанные в exec(3)) говорят, что он «выполняет новый процесс». Это крайне некорректная фраза — не появляется нового процесса; много атрибутов вызывающего процесса остаются неизменными (в частности, его PID). Всё, что делает execve(2), это перестраивает существующий процесс (вызывавший процесс) под выполнение новой программы.

Над процессами с установленными set-user-ID и set-group-ID не может выполняться ptrace(2).

Результат работы при монтировании файловой системы с параметром nosuid различается в разных версиях ядра Linux: некоторые будут отказывать в запуске исполняемых файлов с установленными битами set-user-ID и set-group-ID, если это дало бы пользователю больше прав чем уже есть (и возвращать EPERM), другие просто проигнорируют биты set-user-ID и set-group-ID и успешно выполнят exec().

В Linux значения argv и envp могут быть равны NULL. В обоих случаях, это работает также, как если аргумент бы содержал указатель на список с единственным указателем null. Не пользуйтесь преимуществом данной нестандартной и непереносимой возможностью! В многих других системах UNIX указание argv равным NULL приводит к ошибке (EFAULT). Некоторые другие системы UNIX при envp==NULL работают также как Linux.

В POSIX.1 указано, что значения, возвращаемые sysconf(3), должны быть неизменны в течении существования процесса. Однако, начиная с версии Linux 2.6.23, если изменяется ограничение ресурса RLIMIT_STACK, то значение, возвращаемое для _SC_ARG_MAX, также будет изменено, чтобы отразить, что ограничение на пространство для хранения параметров командной строки и окружения было изменено.

В большинстве случаев отказа execve() управление возвращается в первоначально исполняемый образ и вызывающий execve() может обработать ошибку. Однако в (редких) случаях (обычно вызванных отсутствием ресурсов), ошибка может возникнуть после точки невозврата: первоначально исполняемый образ уже разрушен, а новый образ ещё сознан не полностью. В таких случаях ядро убивает процесс сигналом SIGKILL.

### Интерпретируемые сценарии
Ядро накладывает ограничение на максимальную длину текста после символов «#!» в начале сценария; символы за пределами границ игнорируются. До Linux 5.1 было ограничение в 127 символов. Начиная с Linux 5.1 ограничение установлено в 255 символов.

Семантика необязательного параметра интерпретатора сценариев различна в разных реализациях. В Linux, вся строка после имени интерпретатора передаётся интерпретатору как единый параметр, и эта строка может содержать пробельные символы. Однако, такое поведение отличается от других систем. Некоторые системы используют первый пробел в качестве признака окончания необязательного параметра. В других системах, интерпретатор сценариев может иметь несколько параметров, и пробелы в необязательном параметре используются для их разграничения.

На файлах со сценариями в Linux (как и большинстве других современных системах UNIX) игнорируются биты set-user-ID и set-group-ID.

### execve() и EAGAIN
Это более подробное объяснение ошибки EAGAIN, которая возвращается (начиная с Linux 3.1) при вызове execve().

Ошибка EAGAIN может возникать, когда предшествующий вызов setuid(2), setreuid(2) или setresuid(2) приводит к изменению у процесса реального идентификатора пользователя и это изменение приводит к тому, что процесс превышает свой ограничитель ресурса RLIMIT_NPROC (т. е., количество процессов, принадлежащих новому реальному UID, превышает ограничитель ресурса). В версиях Linux с 2.6.0 по 3.0, это приводит к ошибке вызова set*uid() (до версии 2.6 ограничитель ресурса не учитывался для процессов, которые изменили идентификатор пользователя).

Начиная с Linux 3.1, описанный сценарий больше не приводит к ошибке в вызове set*uid(), так как это слишком часто приводило к дырам в безопасности, когда некорректное приложение не проверяет возвращаемое состояние и предполагает, что если вызывающий имеет права root, то вызов всегда выполняется успешно. Вместо этого вызов set*uid() теперь успешно изменяет реальный UID, но ядро устанавливает внутренний флаг с именем PF_NPROC_EXCEEDED, который означает, что был превышен ограничитель ресурса RLIMIT_NPROC. Если флаг PF_NPROC_EXCEEDED установлен и ограничитель ресурса всё ещё превышен на момент последующего вызова execve(), то вызов завершается с ошибкой EAGAIN. Такая логика ядра гарантирует, что ограничитель ресурса RLIMIT_NPROC будет учтён при обычной последовательности действий для привилегированных служб, а именно — fork(2) + set*uid() + execve().

Если ограничитель ресурса был не превышен на момент вызова execve() (так как другие процессы, принадлежащие этому реальному UID завершили работу между вызовом set*uid() и execve()), то вызов execve() выполнится успешно и ядро очистит флаг PF_NPROC_EXCEEDED у процесса. Флаг также очищается, если при успешном выполнении процессом последующего вызова fork(2).

### Историческая справка
В UNIX V6 список аргументов вызова exec() заканчивался 0, а список аргументов main заканчивался -1. Поэтому, этот список аргументов не мог быть использован напрямую в последующем вызове exec(). Начиная с UNIX V7 оба списка стали оканчиваться NULL.

## ПРИМЕР
Данная программа запускается второй программой, представленной ниже. Она просто выводит свои параметры командной строки по одному на строку.

```
/* myecho.c */
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{

    int j;

    for (j = 0; j < argc; j++)

        printf("argv[%d]: %s\n", j, argv[j]);

    exit(EXIT_SUCCESS);
}
```

Эта программа может использоваться для запуска программы, чьё имя указано в параметре командной строки.

```
/* execve.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{

    char *newargv[] = { NULL, "hello", "world", NULL };

    char *newenviron[] = { NULL };

    if (argc != 2) {

        fprintf(stderr, "Использование: %s <file-to-exec>\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    newargv[0] = argv[1];

    execve(argv[1], newargv, newenviron);

    perror("execve");   /* execve() возвращается только при ошибке */

    exit(EXIT_FAILURE);
}
```

Мы можем использовать вторую программу для запуска первой:

```
$ cc myecho.c -o myecho
$ cc execve.c -o execve
$ ./execve ./myecho
argv[0]: ./myecho
argv[1]: hello
argv[2]: world
```

Также мы можем использовать эти программы для демонстрации использования интерпретатора сценариев. Для этого создадим сценарий, чей "интерпретатор" указывает на нашу программу myecho:

```
$ cat > script
#!./myecho script-arg
^D
$ chmod +x script
```

Теперь мы можем использовать нашу программу для запуска сценария:

```
$ ./execve ./script
argv[0]: ./myecho
argv[1]: script-arg
argv[2]: ./script
argv[3]: hello
argv[4]: world
```

## СМОТРИТЕ ТАКЖЕ
chmod(2), execveat(2), fork(2), get_robust_list(2), ptrace(2), exec(3), fexecve(3), getopt(3), system(3), credentials(7), environ(7), path_resolution(7), ld.so(8)


execveat

title: execveat(2)

text:
# execveat(2)

## ИМЯ
execveat - выполняет программу, определяемую относительно файлового дескриптора каталога

## ОБЗОР
\#include <unistd.h>

int execveat(int dirfd, const char *pathname,

char *const argv[], char *const envp[],

int flags);

## ОПИСАНИЕ
Системный вызов execveat() выполняет программу, на которую ссылается комбинация dirfd и pathname. Он работает также как системный вызов execve(2), за исключением случаев, описанных в данной справочной странице.

Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в execve(2)).

Если в pathname задан относительный путь и dirfd равно специальному значению AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как execve(2)).

Если в pathname задан абсолютный путь, то dirfd игнорируется.

Если pathname — пустая строка и указан флаг AT_EMPTY_PATH, то файловым дескриптором dirfd задаётся выполняемый файл (т. е., dirfd ссылается на исполняемый файл, а не на каталог).

Аргумент flags является битовой маской, которая может включать ноль или более следующих флагов:

AT_EMPTY_PATH

Если значение pathname равно пустой строке, то вызов выполняет действие с файлом, на который ссылается dirfd (может быть получен с помощью open(2) с флагом O_PATH).

AT_SYMLINK_NOFOLLOW

Если файл задаётся dirfd и pathname — символическая ссылка (не NULL), то вызов завершается с ошибкой ELOOP.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении execveat() не возвращает управление. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

## ОШИБКИ
В execveat() могут возникнуть те же ошибки, что и в execve(). Также, в execveat() могут возникнуть следующие ошибки:

EBADF

dirfd не является правильным файловым дескриптором.

EINVAL

Указано неверное значение в flags.

ELOOP

Значение flags содержит AT_SYMLINK_NOFOLLOW и файл задаётся dirfd, а pathname — символическая ссылка (не NULL).

ENOENT

Программа задаётся dirfd и по pathname требуется использовать интерпретирующую программу (то есть сценарий, начинающийся с «#!»), но файловый дескриптор dirfd открыт с флагом O_CLOEXEC, что приводит к недоступности файла программы запускаемому интерпретатору. Смотрите ДЕФЕКТЫ.

ENOTDIR

Значение pathname содержит относительный путь и dirfd содержит файловый дескриптор, указывающий на файл, а не на каталог.

## ВЕРСИИ
Вызов execveat() был добавлен в ядро Linux версии 3.19; поддержки в библиотеке GNU C пока нет.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Системный вызов execveat() есть только в Linux.

## ЗАМЕЧАНИЯ
В дополнении к причинам, описанным в openat(2), системному вызову execveat() также требуется разрешить fexecve(3) для реализации в системах, у которых не смонтированной файловой системы /proc.

При запросе запуска файла сценария, значение argv[0], передаваемое в интерпретатор сценарий, является строкой в виде /dev/fd/N или /dev/fd/N/P, где N — номер файлового дескриптора, передаваемого через аргумент dirfd. Строка в первом формате встречается, когда указан AT_EMPTY_PATH. Строка во втором формате встречается, когда сценарий задаётся сразу через dirfd и pathname; в этом случае P — это значение, указанное в pathname.

По причинам, описанным в fexecve(3), естественным подходом является использование execveat() с установленным флагом close-on-exec у dirfd (но смотрите ДЕФЕКТЫ).

## ДЕФЕКТЫ
Ошибка ENOENT, описанная выше, означает, что невозможно установить флаг close-on-exec у файлового дескриптора, переданного вызову в виде:

execveat(fd, "", argv, envp, AT_EMPTY_PATH);

Однако неспособность установить флаг close-on-exec означает утечку файловых дескрипторов, через ссылку сценария на самого себя. Помимо траты файлового дескриптора, это может привести к исчерпанию файловых дескрипторов, если сценарии рекурсивно вызывают execveat().

## СМОТРИТЕ ТАКЖЕ
execve(2), openat(2), fexecve(3)


title: exit_group(2)

summary: Завершает все нити в процессе

text:
# exit_group(2)

## ИМЯ
exit_group - Завершает все нити в процессе

## ОБЗОР

```
#include <linux/unistd.h>
```

```
void exit_group(int status);
```

## ОПИСАНИЕ
Данный системный вызов эквивалентен _exit(2) за исключением того, что завершает не только вызвавшую нить, то и всю группу нитей вызвавшего процесса.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Данный системный вызов не возвращает результат.

## ВЕРСИИ
Данный вызов появился в Linux 2.5.35.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данный вызов существует только в Linux.

## ЗАМЕЧАНИЯ
Начиная с glibc версии 2.3, данный системный вызов выполняется при запуске обёрточной функции к _exit(2).

## СМОТРИТЕ ТАКЖЕ
exit(2)


fallocate

title: fallocate(2)

summary: управление пространством файла

text:
# fallocate(2)

## ИМЯ
fallocate - управление пространством файла

## ОБЗОР

```
#define _GNU_SOURCE             /* Смотрите feature_test_macros(7) */
#include <fcntl.h>
```

```
int fallocate(int fd, int mode, off_t offset, off_t len);
```

## ОПИСАНИЕ
Это непереносимый системный вызов, существующий только в Linux. В POSIX.1 есть переносимый метод, обеспечивающий выделение пространства под файл (смотрите posix_fallocate(3)).

Вызов fallocate() позволяет вызывающему напрямую управлять выделением дискового пространства под файл, на который указывает fd, для байтового диапазона, начинающегося с offset и имеющего длину len байт.

В аргументе mode задаётся операция, выполняемая над указанным диапазоном. Детали о поддерживаемых операциях представлены в подразделах далее.

### Выделение дискового пространства
По умолчанию (т. е. значение mode равно нулю) fallocate() выделяет место на диске в диапазоне, задаваемом offset и len. Размер файла (получаемый через stat(2)) будет изменён, если offset+len больше чем размер файла. Любая подобласть внутри диапазона, заданного offset и len, которая не содержала данных до вызова, будет заполнена нулями. Такое поведение по умолчанию очень напоминает поведение библиотечной функции posix_fallocate(3), и было введено для оптимальной реализации этой функции.

После успешного выполнения вызова последующие операции записи в диапазон, указанный offset и len, гарантированно не завершатся с ошибкой из-за нехватки места на диске.

Если в mode указан флаг FALLOC_FL_KEEP_SIZE, то поведение по умолчанию почти то же, но размер файла не будет изменён даже, если offset+len больше чем размер файла. Это полезно для предварительного выделения блоков с нулями за концом файла для оптимизации загруженности при добавлении.

Если в modeуказан флаг FALLOC_FL_UNSHARE, то общие файловые extent-данные будут сделаны частными для файла, чтобы гарантировать, что последующая запись не завершится ошибкой из-за нехватки места. Обычно, это выполняется с помощью операции копирования при записи для всех общих данных файла. Данный флаг может поддерживаться не во всех файловых системах.

Так как выделение выполняется кусками размером с блок, fallocate() может выделить больший диапазон дискового пространства, чем было указано.

### Освобождение файлового пространства
Указание флага FALLOC_FL_PUNCH_HOLE (доступен, начиная с Linux 2.6.38) в mode освобождает пространство (т.е., создаёт дыру) в диапазоне начиная с offset и до len байт. Внутри заданного диапазона неполные блоки файловой системы заполняются нулями, а полные блоки файловой системы удаляются из файла. После успешного выполнения вызова, последующие операции чтения из этого диапазона вернут нули.

Флаг FALLOC_FL_PUNCH_HOLE должен быть логически добавлен к флагу FALLOC_FL_KEEP_SIZE в mode; другими словами, даже когда пробивание (punching) выходит за конец файла, размер файла (получаемый с помощью stat(2)) остаётся неизменным.

Не все файловые системы поддерживают FALLOC_FL_PUNCH_HOLE; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:

- XFS (начиная с Linux 2.6.38)

- ext4 (начиная с Linux 3.0)

- Btrfs (начиная с Linux 3.7)

- tmpfs(5) (начиная с Linux 3.5)"

### Сворачивание (Collapsing) файлового пространства
Задание флага FALLOC_FL_COLLAPSE_RANGE (доступен, начиная с Linux 3.15) в mode приводит к удалению байтового диапазона из файла без создания дыры. Сворачиваемый диапазон байт начинается с offset и длится len байт. По завершению операции, содержимое файла, начиная с offset+len, будет добавлено в расположение offset, и файл будет на len байт меньше.

У файловой системы могут быть ограничения на детализацию операции, для большей эффективности реализации. Обычно, значения offset и len должны быть кратны размеру логического блока файловой системы, различающемуся в разных файловых системах и зависящему от настроек. Если файловая система содержит такое требование и оно нарушено, то fallocate() завершается ошибкой EINVAL.

Если область, заданная offset плюс len достигает или выходит за конец файла, то возвращается ошибка; вместо этого используйте ftruncate(2) для обрезания файла.

Вместе с FALLOC_FL_COLLAPSE_RANGE другие флаги в mode указывать нельзя.

В Linux 3.15 флаг FALLOC_FL_COLLAPSE_RANGE поддерживается в ext4 (только для файлов на основе extent) и XFS.

### Зануление файлового пространства
Задание флага FALLOC_FL_ZERO_RANGE (доступен, начиная с Linux 3.15) в mode приводит к обнулению байтового диапазона, начиная с offset и размером len байт. Внутри указанного диапазона блоки выделяются заранее для областей, которые попадают в дыры в файле. После успешного выполнения вызова последующие операции чтения из этого диапазона будут возвращать нули.

Зануление, желательно, выполнять внутри файловой системы, преобразуя диапазон в незаписываемые extents. Этот подход означает, что указанный диапазон на устройстве в действительности не будет содержать нули на физическом уровне (за исключением неполных блоков в одном из концов диапазона), и ввод-вывод требуется только для обновления метаданных.

Если в mode также указан флаг FALLOC_FL_KEEP_SIZE, то поведение вызова похоже, но размер файла не будет изменён даже, если offset+len больше размера файла. Такое поведение совпадает с предварительным выделением пространства с помощью указания флага FALLOC_FL_KEEP_SIZE.

Не все файловые системы поддерживают FALLOC_FL_ZERO_RANGE; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:

- XFS (начиная с Linux 3.15)

- ext4, для файлов на основе extent (начиная с Linux 3.15)

- SMB3 (начиная с Linux 3.17)

- Btrfs (начиная с Linux 4.16)

### Увеличение файлового пространства
Задание флага FALLOC_FL_INSERT_RANGE (доступен начиная с Linux 4.1) в mode увеличивает файловое пространство посредством вставки дыры (hole) в размер файла без перезаписывания существующих данных. Дыра начинается с offset и продолжается len байт. При вставки дыры внутрь файла содержимое файла, начинающееся с offset, будет сдвинуто вперёд (т. е., станет доступно по большему смещению в файле) на len байт. Вставка дыры внутрь файла увеличивает размер файла на len байт.

Данный режим имеет те же ограничения что и FALLOC_FL_COLLAPSE_RANGE, независимо от детализации операции Если требования детализации не удовлетворяются, то fallocate() завершается ошибкой EINVAL. Если offset больше или равно концу файла, то возвращается ошибка. Для таких операций (т. е., вставка дыры в конец файла) нужно использовать ftruncate(2).

Вместе с FALLOC_FL_INSERT_RANGE другие флаги в mode указывать нельзя.

Для работы FALLOC_FL_INSERT_RANGE требуется поддержка в файловой системе; сейчас это XFS (начиная с Linux 4.1) и ext4 (начиная с Linux 4.2).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении fallocate() возвращается 0; при ошибке возвращается -1, а в errno содержится код ошибки.

## ОШИБКИ
EBADF

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

EFBIG

Сумма offset+len превышает максимальный размер файла.

EFBIG

В mode указан FALLOC_FL_INSERT_RANGE, и текущий размер файла+len превышает максимальный файловый размер.

EINTR

При выполнении поступил сигнал; смотрите signal(7).

EINVAL

Значение offset меньше 0, или len меньше или равно 0.

EINVAL

Значение mode равно FALLOC_FL_COLLAPSE_RANGE, но диапазон, указанный в offset плюс len, достиг или перешагнул за конец файла.

EINVAL

Значение mode равно FALLOC_FL_INSERT_RANGE, но диапазон, указанный в offset, достиг или перешагнул за конец файла.

EINVAL

Значение mode равно FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, но значение offset или len не кратно размеру блока файловой системы.

EINVAL

Значение mode содержит FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, а также другие флаги; но с FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE другие флаги указывать нельзя.

EINVAL

Значение mode равно FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_ZERO_RANGE или FALLOC_FL_INSERT_RANGE, но файл, на который указывает fd, не является обычным файлом.

EIO

При чтении или записи в файловую систему произошла ошибка ввода-вывода.

ENODEV

Значение fd не указывает на обычный файл или каталог (если fd — канал или FIFO, то возникнет другая ошибка).

ENOSPC

Недостаточно дискового пространства на устройстве, на котором расположен файл, указанный в fd.

ENOSYS

В данном ядре вызов fallocate() не реализован.

EOPNOTSUPP

Файловая система с файлом, на который указывает fd, не поддерживает данную операцию; или значение mode не поддерживается файловой системой, в которой находится файл, на который указывает fd.

EPERM

Файл, на который указывает fd, помечен как неизменяемый (immutable) (смотрите chattr(1)).

EPERM

Значение mode равно FALLOC_FL_PUNCH_HOLE, FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE и файл, на который указывает fd, помечен как только для добавления (смотрите chattr(1)).

EPERM

Выполнение операции предотвращено опечатыванием (file seal); смотрите fcntl(2).

ESPIPE

Значение fd указывает на канал или FIFO.

ETXTBSY

Значение mode равно FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, но файл, на который указывает fd, в данный момент выполняется.

## ВЕРСИИ
Вызов fallocate() доступен в Linux начиная с ядра 2.6.23. Поддержка в glibc добавлена в версии 2.10. Флаги FALLOC_FL_* определены в заголовочных файлах glibc только начиная с версии 2.18.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов fallocate() есть только в Linux.

## СМОТРИТЕ ТАКЖЕ
fallocate(1), ftruncate(2), posix_fadvise(3), posix_fallocate(3)


title: fanotify_init(2)

text:
# fanotify_init(2)

## ИМЯ
fanotify_init - создаёт и инициализирует группу fanotify

## ОБЗОР
\#include <fcntl.h>

\#include <sys/fanotify.h>

int fanotify_init(unsigned int flags, unsigned int event_f_flags);

## ОПИСАНИЕ
Обзор программного интерфейса fanotify смотрите в fanotify(7).

Вызов fanotify_init() инициализирует новую группу fanotify и возвращает файловый дескриптор очереди событий, связанной с группой.

В файловом дескрипторе, используемом в fanotify_mark(2), задаются файлы, каталоги, точки монтирования и файловые системы, для которых должны создаваться события fanotify. Эти события можно получить с помощью чтения файлового дескриптора. Одни события носят уведомительный характер, показывая что к файлу был получен доступ. Другие события можно использовать для разрешения приложению доступа к файлу или каталогу. Доступ к объектам файловой системы разрешается посредством записи в файловый дескриптор.

Несколько программ могут использовать интерфейс fanotify к одним и тем же файлам одновременно.

В текущей реализации количество групп fanotify ограничено 128 на пользователя. Это значение нельзя изменить.

Для вызова fanotify_init() требуется мандат CAP_SYS_ADMIN. Это требование может быть облегчено в будущих версиях программного интерфейса. Поэтому ниже показаны определённые дополнительные проверки возможностей, которые были реализованы.

Аргумент flags содержит многобитовое поле, определяющее класс уведомления, запрашиваемый приложением, а также однобитовые поля, задающие поведение файлового дескриптора.

Если на события доступа зарегистрировалось несколько слушателей, то класс уведомления используется для установления порядка слушателей при получении событий.

В flags может быть указан только один из следующих классов уведомления:

FAN_CLASS_PRE_CONTENT

Это значение позволяет принимать уведомляющие события об обращении к файлу, и события доступа, запрашивающие доступ к файлу. Он предназначен для слушателей событий, которым требуется доступ к файлам до того, как в них будут содержаться окончательные данные. Этот класс уведомления может быть использован, например, в программах управления иерархического хранения.

FAN_CLASS_CONTENT

Это значение позволяет принимать уведомляющие события об обращении к файлу, и события доступа, запрашивающие доступ к файлу. Он предназначен для слушателей событий, которым требуется доступ к файлам после того, как они содержат окончательные данные. Этот класс уведомления может быть использован, например, в программах обнаружения вредоносного кода.

FAN_REPORT_FID (начиная с Linux 5.1)

Это значение позволяет получать события, которые содержат дополнительную информацию о нижележащем объекте файловой системы, относящемся к событию. Дополнительная структура содержит информацию об объекте, которая добавляется к структуре общих метаданных событий. Файловый дескриптор, используемый для представления объекта, заменяется в событии файловым описателем. Он предназначен для приложений, которым для работы с файлами удобней использовать файловый описатель, а не файловый дескриптор. Также, его можно использовать в приложениях, которым интересны события об элементах каталога, например таких как FAN_CREATE, FAN_ATTRIB, FAN_MOVE и FAN_DELETE. Заметим, что использование событий изменения каталога не поддерживается при слежении за точкой монтирования. Использование FAN_CLASS_CONTENT или FAN_CLASS_PRE_CONTENT с этим флагом не допускается и приводит к ошибке EINVAL. Дополнительную информацию смотрите в fanotify(7).

FAN_CLASS_NOTIF

Значение по умолчанию. Его не нужно указывать. Это значение позволяет принимать только события о доступе к файлу. Право на доступ к файлу задать невозможно.

Слушатели с различными классами уведомлений будут принимать события в таком порядке: FAN_CLASS_PRE_CONTENT, FAN_CLASS_CONTENT, FAN_CLASS_NOTIF. Порядок уведомления слушателей в этом классе уведомления не определён.

Дополнительно в flags могут быть установлены следующие биты:

FAN_CLOEXEC

Устанавливать флаг close-on-exec (FD_CLOEXEC) для нового файлового дескриптора. Смотрите описание флага O_CLOEXEC в open(2).

FAN_NONBLOCK

Включить неблокирующий флаг (O_NONBLOCK) для файлового дескриптора. Чтение из такого файлового дескриптора не вызовет блокирования. Если данные отсутствуют, то read(2) завершается ошибкой EAGAIN.

FAN_UNLIMITED_QUEUE

Снять ограничение в 16384 события в очереди событий. Для использования этого флага требуется мандат CAP_SYS_ADMIN.

FAN_UNLIMITED_MARKS

Снять ограничение в 8192 метки. Для использования этого флага требуется мандат CAP_SYS_ADMIN.

FAN_REPORT_TID (начиная с Linux 4.20)

Хранить ID нити (TID) вместо ID процесса (PID) в поле pid структуры struct fanotify_event_metadata, передаваемой в read(2) (смотрите fanotify(7)).

В аргументе event_f_flags задаются флаги состояния файла, которые будут установлены на открытые файловые описатели, создаваемые для событий fanotify. Подробней об этих флагах смотрите описание значений flags в open(2). Аргумент event_f_flags включает многобитовое поле для режима доступа. Это поел может иметь следующие значения:

O_RDONLY

Это значение разрешает доступ только на чтение.

O_WRONLY

Это значение разрешает доступ только на запись.

O_RDWR

Это значение разрешает доступ на чтение и запись.

В event_f_flags могут быть установлены дополнительные биты. Наиболее полезные значения:

O_LARGEFILE

Включить поддержку файлов более 2 ГБ. Если не удастся установить этот флаг, то при попытке открыть большой файл, отслеживаемый группой fanotify на 32-битной системе, возвращается ошибка EOVERFLOW.

O_CLOEXEC (начиная с Linux 3.18)

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

Также доступны следующие флаги: O_APPEND, O_DSYNC, O_NOATIME, O_NONBLOCK и O_SYNC. Указание любых других флагов в event_f_flagsприводит к ошибке EINVAL (но смотрите ДЕФЕКТЫ).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении fanotify_init() возвращает новый файловый дескриптор. При ошибке возвращается -1, и errno устанавливается в соответствующее значение.

## ОШИБКИ
EINVAL

В flags или event_f_flags указано некорректное значение. Значение FAN_ALL_INIT_FLAGS (устарело, начиная с версии ядра Linux 4.20) определяет все допустимые биты в flags.

EMFILE

Количество групп fanotify для этого пользователя превышает 128.

EMFILE

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

ENOMEM

Не удалось выделить память для группы уведомления.

ENOSYS

В этом ядре не реализован fanotify_init(). Программный интерфейс fanotify доступен только, если ядро было собрано с параметром CONFIG_FANOTIFY.

EPERM

Операция запрещена, так как вызывающий не имеет мандата CAP_SYS_ADMIN.

## ВЕРСИИ
Вызов fanotify_init() появился в версии 2.6.36 ядра Linux и был включён в версии 2.6.37.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данный системный вызов есть только в Linux.

## ДЕФЕКТЫ
В ядрах Linux до версии 3.18 существовали следующие дефекты:

*

При передаче в event_f_flags флаг O_CLOEXEC игнорируется.

В ядрах Linux до версии 3.14 существовали следующие дефекты:

*

Значение аргумента event_f_flags не проверяется на корректность флагов. Могут быть установлены флаги, предназначенные только для внутреннего использования, такие как FMODE_EXEC, и в результате будут установлены для файловых дескрипторов при чтении из файлового дескриптора fanotify.

## СМОТРИТЕ ТАКЖЕ
fanotify_mark(2), fanotify(7)


title: fanotify_mark(2)

text:
# fanotify_mark(2)

## ИМЯ
fanotify_mark - добавляет, удаляет или изменяет метку fanotify для объекта файловой системы

## ОБЗОР

```
#include <sys/fanotify.h>
```

```
int fanotify_mark(int fanotify_fd, unsigned int flags,
                  uint64_t mask, int dirfd, const char *pathname);
```

## ОПИСАНИЕ
Обзор программного интерфейса fanotify смотрите в fanotify(7).

Системный вызов fanotify_mark() добавляет, удаляет или изменяет метку fanotify для объекта файловой системы. Вызывающий должен иметь право на чтение помеченного объекта файловой системы.

Аргумент fanotify_fd — файловый дескриптор, возвращаемый fanotify_init(2).

Аргумент flags — битовая маска, описывающая выполняемое изменение. Она должна содержать только одно значение из:

FAN_MARK_ADD

События в mask будут добавлены в маску меток (или в маску игнорирования). Если значение mask пусто, то возвращается ошибка EINVAL.

FAN_MARK_REMOVE

События в mask будут удалены из маски меток (или маски игнорирования). Если значение mask пусто, то возвращается ошибка EINVAL.

FAN_MARK_FLUSH

Удалить все метки файловых систем, все метки монтирований или все метки каталогов и файлов из группы fanotify. Если в flags содержится FAN_MARK_MOUNT, то все метки монтирований удаляются из группы. Если в flags содержится FAN_MARK_FILESYSTEM, то все метки файловых систем удаляются из группы. В противном случае удаляются все метки и каталогов и файлов. Вместе с FAN_MARK_FLUSH может быть указан только либо FAN_MARK_MOUNT, либо FAN_MARK_FILESYSTEM.Значение mask игнорируется.

Если не задано ни одно из этих значений, или указано больше одного, то вызов завершается с ошибкой EINVAL.

Кроме этого в flags могут быть указаны (побитовым сложением):

FAN_MARK_DONT_FOLLOW

Если pathname — символьная ссылка, то помечается сама ссылка, а не файл, на который она ссылается (по умолчанию fanotify_mark() разыменовывает pathname, если это символьная ссылка).

FAN_MARK_ONLYDIR

Если объект файловой системы для пометки не является каталогом, то возвращается ошибка ENOTDIR.

FAN_MARK_MOUNT

Пометить точку монтирования, заданную в pathname. Если само значение pathname не является точкой монтирования, то будет помечена точка монтирования, которая содержит pathname. Будут отслеживаться все каталоги, подкаталоги и содержащиеся в точке монтирования файлы. Это значение нельзя использовать, если файловый дескриптор fanotify_fd инициализирован с флагом FAN_REPORT_FID или если в качестве маски mask указано любое событие изменения нового каталога. Результатом попытки это сделать будет возврат ошибки EINVAL.

FAN_MARK_FILESYSTEM (начиная с Linux 4.20)

Пометить файловую систему, заданную в pathname. Будет помечена файловая система, содержащая pathname. Будут отслеживаться все файлы и каталоги файловой системы любой точки монтирования.

FAN_MARK_IGNORED_MASK

События в mask должны быть добавлены или удалены из маски игнорирования.

FAN_MARK_IGNORED_SURV_MODIFY

Маска игнорирования должна остаться неизменной при событиях изменения. Если этот флаг не указан, то маска игнорирования очищается при появлении событий изменения игнорируемого файла или каталога.

В mask указывается какие события должны прослушиваться (или игнорироваться). Данная битовая маска состоит из следующих значений:

FAN_ACCESS

Создать событие при доступе (для чтения) к файлу или каталогу (но смотрите ДЕФЕКТЫ).

FAN_MODIFY

Создать событие при изменении (при записи) файла.

FAN_CLOSE_WRITE

Создать событие при закрытии файла, открытого на запись.

FAN_CLOSE_NOWRITE

Создать событие при закрытии файла или каталога, открытого только для чтения.

FAN_OPEN

Создать событие при открытии файла или каталога.

FAN_OPEN_EXEC (начиная с Linux 5.0)

Создать событие при открытии файла для начала выполнения. Подробней об этом в ЗАМЕЧАНИЯХ.

FAN_ATTRIB (начиная с Linux 5.1)

Создать событие при изменении метаданных файла или каталога.

FAN_CREATE (начиная с Linux 5.1)

Создать событие при создании файла или каталога в помеченном родительском каталоге.

FAN_DELETE (начиная с Linux 5.1)

Создать событие при удалении файла или каталога в помеченном родительском каталоге.

FAN_DELETE_SELF (начиная с Linux 5.1)

Создать событие при удалении самого помеченного файла или каталога.

FAN_MOVED_FROM (начиная с Linux 5.1)

Создать событие при перемещении файла или каталога из помеченного родительского каталога.

FAN_MOVED_TO (начиная с Linux 5.1)

Создать событие при перемещении файла или каталога в помеченный родительский каталог.

FAN_MOVE_SELF (начиная с Linux 5.1)

Создать событие при перемещении самого помеченного файла или каталога.

FAN_Q_OVERFLOW

Создать событие при переполнении очереди сообщений. Размер очереди сообщений ограничен 16384 элементами, если в fanotify_init(2) не указан FAN_UNLIMITED_QUEUE.

FAN_OPEN_PERM

Создать событие при запросе открытия файла или каталога. Требуется файловый дескриптор fanotify, созданный с FAN_CLASS_PRE_CONTENT или FAN_CLASS_CONTENT.

FAN_OPEN_EXEC_PERM (начиная с Linux 5.0)

Создать событие при запросе открытия файла или каталога на выполнение. Требуется файловый дескриптор fanotify, созданный с FAN_CLASS_PRE_CONTENT или FAN_CLASS_CONTENT. Дополнительная информация представлена в ЗАМЕЧАНИЯХ.

FAN_ACCESS_PERM

Создать событие при запросе чтения файла или каталога. Требуется файловый дескриптор fanotify, созданный с FAN_CLASS_PRE_CONTENT или FAN_CLASS_CONTENT.

FAN_ONDIR

Создать события для каталогов, например, когда вызывается opendir(3), readdir(3) (но смотрите ДЕФЕКТЫ) и closedir(3). Без этого флага события создаются только для файлов. Флаг FAN_ONDIR возвращается в маске событий только, если файловый дескриптор fanotify_fd инициализирован с флагом FAN_REPORT_FID. В контексте события элементов каталога, например таких как FAN_CREATE, FAN_DELETE, FAN_MOVED_FROMи FAN_MOVED_TO, требуется задавать флаг FAN_ONDIR для создания событий, когда изменяются элементы подкаталогов (т. е., mkdir(2)/ rmdir(2)). События изменения элемента подкаталога никогда не будут объединены с с событиями изменений элементов не подкаталога. Этот флаг никогда не возвращается один в событии и всегда задаётся вместе с другим типом события.

FAN_EVENT_ON_CHILD

Должны создаваться события для прямых потомков помеченных каталогов. Флаг не влияет на помеченные точки монтирования и файловые системы. Заметим, что события не генерируются для потомков подкаталогов помеченных каталогов. Для слежения за всем деревом каталогов нужно пометить соответствующую точку монтирования.

Определены следующие составные значения:

FAN_CLOSE

Файл закрыт (FAN_CLOSE_WRITE|FAN_CLOSE_NOWRITE).

FAN_MOVE

Файл или каталог был перемещён (FAN_MOVED_FROM|FAN_MOVED_TO).

Объект файловой системы для пометки задаётся файловым дескриптором dirfd и путём, указанным в pathname:

- Если значение pathname равно NULL, то в dirfd указан объект файловой системы для пометки.

- Если значение pathname равно NULL и dirfd равно специальному значению AT_FDCWD, то помечается текущий рабочий каталог.

- Если в pathname задан абсолютный путь, то им определяется объект файловой системы для пометки, а dirfd игнорируется.

- Если в pathname задан относительный путь и dirfd не равно AT_FDCWD, то помечаемый объект файловой системы определяется из pathname относительно каталога, заданного в dirfd.

- Если в pathname задан относительный путь и dirfd равно AT_FDCWD, то помечаемый объект файловой системы определяется из pathname относительно текущего рабочего каталога.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении fanotify_mark() возвращает 0; при ошибке возвращается -1, а в errno задаётся причина ошибки.

## ОШИБКИ
EBADF

В fanotify_fd передан некорректный файловый дескриптор.

EINVAL

В flags или mask указано некорректное значение, или в fanotify_fd не файловый дескриптор fanotify.

EINVAL

Файловый дескриптор fanotify был открыт с FAN_CLASS_NOTIF или FAN_REPORT_FID и маска содержит флаг для событий доступа (FAN_OPEN_PERM или FAN_ACCESS_PERM).

ENODEV

Объект файловой системы, указанный в pathname, не связан с файловой системой, которая поддерживает fsid (например, tmpfs(5)). Эта ошибка может вернуться только, когда файловый дескриптор fanotify, возвращаемый fanotify_init(2), был создан с флагом FAN_REPORT_FID.

ENOENT

Объект файловой системы, указанный в dirfd и pathname, не существует. Эта ошибка также возникает при попытке удаления метки с не помеченного объекта.

ENOMEM

Невозможно выделить необходимую память.

ENOSPC

Количество меток превышает ограничение в 8192 и флаг FAN_UNLIMITED_MARKS не был указан при создании файлового дескриптора fanotify с помощью fanotify_init(2).

ENOSYS

В этом ядре не реализован fanotify_mark(). Программный интерфейс fanotify доступен только, если ядро было собрано с параметром CONFIG_FANOTIFY.

ENOTDIR

В значении flags содержится FAN_MARK_ONLYDIR, а в dirfd и pathname указан не каталог.

EOPNOTSUPP

Объект, указанный в pathname, связан с файловой системой, которая не поддерживает кодирование файловых описателей. Эта ошибка может вернуться только, когда файловый дескриптор fanotify, возвращаемый fanotify_init(2), был создан с флагом FAN_REPORT_FID.

EXDEV

Объект файловой системы, указанный в pathname, располагается в подтоме файловой системы (например, btrfs(5)), которая использует fsid отличный от используемого в её корневом суперблоке. Эта ошибка может вернуться только, когда файловый дескриптор fanotify, возвращаемый fanotify_init(2), был создан с флагом FAN_REPORT_FID.

## ВЕРСИИ
Вызов fanotify_mark() появился в версии 2.6.36 ядра Linux и был включён в версии 2.6.37.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данный системный вызов есть только в Linux.

## ЗАМЕЧАНИЯ

### FAN_OPEN_EXEC и FAN_OPEN_EXEC_PERM
При использовании FAN_OPEN_EXEC или FAN_OPEN_EXEC_PERM в mask события этих типов будут возвращаться только, когда происходит непосредственное выполнение программы. Точнее говоря, события этих типов будут сгенерированы для файлов, которые открываются с помощью execve(2), execveat(2) или uselib(2). События данных типов не будут возникать в ситуации, когда интерпретатору передаётся (или он читает) файл интерпретируемого сценария.

Также, если метка помещается на динамический компоновщик Linux, то пользователь должен также ожидать приём сообщения, когда он открывает объект ELF с помощью execve(2) или execveat(2).

Например, если вызывается следующий двоичный ELF и меткой FAN_OPEN_EXEC отмечен /:

```
$ /bin/echo foo
```

Слушающее приложение в этом случае получило бы события FAN_OPEN_EXEC для исполняемого файла ELF и интерпретатора, соответственно:

```
/bin/echo
/lib64/ld-linux-x86-64.so.2
```

## ДЕФЕКТЫ
В ядрах Linux до версии 3.16 существуют следующие дефекты:

- Если flags содержит FAN_MARK_FLUSH, то dirfd и pathname должны задавать корректный объект файловой системы, даже если этот объект не используется.

- Вызов readdir(2) не генерирует событие FAN_ACCESS.

- Если fanotify_mark() вызван с FAN_MARK_FLUSH, то значение flags не проверяется на корректность.

## СМОТРИТЕ ТАКЖЕ
fanotify_init(2), fanotify(7)