read

title: read(2)

summary: читает из файлового дескриптора

text:
# read(2)

## ИМЯ
read - читает из файлового дескриптора

## ОБЗОР

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

```
ssize_t read(int fd, void *buf, size_t count);
```

## ОПИСАНИЕ
Вызов read() пытается прочитать count байт из файлового дескриптора fd в буфер, начинающийся по адресу buf.

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

Если значение count равно 0, то read() может обнаружить ошибки, описанные далее. При отсутствии ошибок, или если read() не выполняет проверки, то read() с count равным 0 возвращает 0 и ничего не меняет.

В соответствие с POSIX.1, если count больше SSIZE_MAX, то результат зависит от реализации; смотрите ЗАМЕЧАНИЯ по верхнему пределу в Linux.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается количество прочитанных байт (ноль означает конец файла), а позиция в файле увеличивается на это значение. Если количество прочитанных байт меньше, чем количество запрошенных, то это не считается ошибкой: например, это могло произойти из-за того, что прямо сейчас доступно меньшее количество байт (может быть из-за того, что позиция ближе к концу файла, или потому что выполняется чтение из канала или терминала), или потому что работа read() была прервана сигналом. См. также ЗАМЕЧАНИЯ.

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

## ОШИБКИ
EAGAIN

Файловый дескриптор fd указывает на файл, не являющийся сокетом и помеченный как неблокирующий ввод/вывод (O_NONBLOCK), а чтение вызовет блокировку. См. open(2) для дальнейшей информации по флагу O_NONBLOCK.

EAGAIN или EWOULDBLOCK

Файловый дескриптор fd указывает на сокет и он помечен как неблокирующий (O_NONBLOCK), а чтение вызвало бы блокировку. POSIX.1-2001 позволяет вернуть любую ошибку в этом случае и не требует, чтобы эти константы имели одинаковое значение, поэтому переносимое приложение должно проверять обе эти возможности.

EBADF

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

EFAULT

buf находится за пределами доступного вам адресного пространства.

EINTR

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

EINVAL

fd присоединён к объекту, который не подходит для чтения; или файл был открыт с указанием флага O_DIRECT, или неправильно выравнены адрес в buf, значение count или файловое смещение.

EINVAL

fd был создан вызовом timerfd_create(2), а в read() был передан неверный размер буфера; подробней см. в timerfd_create(2).

EIO

Ошибка ввода/вывода. Например, это происходит когда процесс, находящийся в фоновой группе процессов, пытается выполнить чтение из своего управляющего терминала, и игнорирует или блокирует сигнал SIGTTIN, или же его группа процессов осталась без родителя. Это также может случиться, если произошла низкоуровневая ошибка ввода-вывода при чтении с диска или ленты. Также EIO может возникать у сетевых файловых систем, когда консультативная блокировка была убрана у дескриптора файла и потеряна. Подробности смотрите в абзаце Потерянные блокировки в fcntl(2).

EISDIR

fd указывает на каталог.

В зависимости от объекта, на который указывает fd, могут происходить и другие ошибки.

## СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, 4.3BSD, POSIX.1-2001.

## ЗАМЕЧАНИЯ
Типы данных size_t и ssize_t представляющие собой, соответственно, беззнаковый и знаковый целочисленные типы, определены в POSIX.1.

В Linux read() (и похожие системные вызовы) передаст не больше 0x7ffff000 (2 147 479 552) байт, возвращая число байт, переданных на самом деле (это утверждение справедливо как к 32-битным, так и к 64-битным системам).

На файловых системах NFS чтение небольших порций данных обновляет отметки времени только в первый раз, последующие вызовы не делают этого. Это вызвано кэшированием атрибутов с клиентской стороны, потому что большинство (если не все) клиентов NFS предоставляют серверу обновлять st_atime (время последнего доступа), а запросы на чтение, которые удовлетворяются из клиентского кэша, не вызывают обновления st_atime, потому что данные не читаются с сервера. Семантика UNIX может быть достигнута запретом кэширования атрибутов на стороне клиента, но в большинстве случаев это увеличит нагрузку на сервер и снизит производительность.

## ДЕФЕКТЫ
Согласно POSIX.1-2008/SUSv4 раздел XSI 2.9.7 («Thread Interactions with Regular File Operations»):

Следующие функции должны выполняться атомарно по отношению друг к другу, чтобы работать с обычными файлами или символическими ссылками так, как указано в POSIX.1-2008: …

Среди перечисленных в программном интерфейсе есть read() и readv(2). И среди действий, которые должны выполняться атомарно между нитями (и процессами), если обновление файлового смещения. Однако в Linux до версии 3.14 это было не так: если два процесса с общим открытым файловым описанием (смотрите open(2)) выполняют read() (или readv(2)) одновременно, то операции ввода-вывода не атомарны при обновлении файлового смещения; в результате прочитанные двумя процессами блоки данных могут (некорректно) перекрываться. Эта ошибка исправлена в Linux 3.14.

## СМОТРИТЕ ТАКЖЕ
close(2), fcntl(2), ioctl(2), lseek(2), open(2), pread(2), readdir(2), readlink(2), readv(2), select(2), write(2), fread(3)


readahead

package: man-pages-ru

title: readahead(2)

text:
# readahead(2)

## ИМЯ
readahead - включает упреждающее чтение файла в кэш страниц

## ОБЗОР

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

```
ssize_t readahead(int fd, off64_t offset, size_t count);
```

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

Аргумент fd — это файловый дескриптор файла для чтения. В аргументе offset указывает начальная точка, от которой нужно читать данные и в count задаётся количество читаемых байт. Ввод-вывод выполняется во все страницы, так что offset эффективно округляется в меньшую сторону к границе страницы и байты читаются до границы следующей страницы, большей или равной (offset+count). Вызов readahead() не выполняет чтения за концом файла. Файловое смещение открытого файлового описания, на который указывает файловый дескриптор fd, остаётся неизменным.

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

## ОШИБКИ
EBADF

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

EINVAL

fd указывает на файл с типом, который нельзя использовать в readahead().

## ВЕРСИИ
Системный вызов readahead() появился в Linux 2.4.13; поддержка в glibc началась с версии 2.3.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Системный вызов readahead() есть только в Linux, и не должен использоваться в переносимых приложениях.

## ЗАМЕЧАНИЯ
На некоторых 32-битных архитектурах интерфейс системного вызова отличается от описанного выше, по причинам указанным в syscall(2).

## ДЕФЕКТЫ
Вызов readahead() пытается запланировать чтение в фоновом режиме и сразу завершается. Однако, он может заблокироваться на время чтения метаданных файловой системы, необходимых для обнаружения запрашиваемых блоков. Это часто происходит ext[234] для больших файлов, у которых используются косвенные (indirect) блоки вместо непрерывных (extents), что приводит к блокировке вызова на время прочтения нужных данных.

## СМОТРИТЕ ТАКЖЕ
lseek(2), madvise(2), mmap(2), posix_fadvise(2), read(2)


readdir

title: readdir(2)

summary: читает элемент каталога

text:
# readdir(2)

## ИМЯ
readdir - читает элемент каталога

## ОБЗОР

```
int readdir(unsigned int fd, struct old_linux_dirent *dirp,
            unsigned int count);
```

Замечание: В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.

## ОПИСАНИЕ
Эта не та функция, которая должна представлять для вас интерес. Смотрите описание функции readdir(3), которая является интерфейсом библиотеки языка C, соответствующим стандарту POSIX. В этой странице описан минимальный интерфейс системного вызова ядра, который заменён на getdents(2).

Вызов readdir() читает структуру old_linux_dirent из каталога, заданного файловым дескриптором fd, в буфер, указываемый в dirp. Аргумент count игнорируется; всегда считывается только одна структура old_linux_dirent.

Структура old_linux_dirent определена (в файле ядра Linux fs/readdir.c, недоступна извне) следующим образом:

```
struct old_linux_dirent {

    unsigned long d_ino;     /* номер иноды */

    unsigned long d_offset;  /* смещение на данную old_linux_dirent */

    unsigned short d_namlen; /* длина данной d_name */

    char  d_name[1];         /* имя файла (с null в конце) */
}
```

Значением d_ino является номер иноды. В d_offset задаётся смещение данной old_linux_dirent от начала каталога. В d_reclen задаётся размер d_name без учета завершающего байта null ('\0'). В d_name указывается имя файла, завершающееся null.

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

## ОШИБКИ
EBADF

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

EFAULT

Аргумент указывает за пределы адресного пространства вызывающего процесса.

EINVAL

Буфер результата слишком мал.

ENOENT

Заданный каталог не существует.

ENOTDIR

Файловый дескриптор указывает не на каталог.

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

## ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2). Структуру old_linux_dirent нужно определить самостоятельно. Однако лучше использовать readdir(3).

Этот системный вызов отсутствует на x86-64.

## СМОТРИТЕ ТАКЖЕ
getdents(2), readdir(3)


readlink

title: readlink(2)

summary: считывает значение символьной ссылки

text:
# readlink(2)

## ИМЯ
readlink, readlinkat - считывает значение символьной ссылки

## ОБЗОР

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

```
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
#include <fcntl.h>           /* определения констант of AT_* */
#include <unistd.h>
```

```
ssize_t readlinkat(int dirfd, const char *pathname,
                   char *buf, size_t bufsiz);
```

```

```

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

readlink():

_XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L

|| /* в версиях glibc <= 2.19: */ _BSD_SOURCE

readlinkat():

Начиная с glibc 2.10:

_POSIX_C_SOURCE >= 200809L

До glibc 2.10:

_ATFILE_SOURCE

## ОПИСАНИЕ
Вызов readlink() помещает содержимое символьной ссылки pathname в буфер buf размером bufsiz. readlink() не добавляет в buf байт null. Если буфер слишком мал для хранения всего содержимого, то содержимое будет урезано (без выдачи ошибки, до длины в bufsiz символов).

### readlinkat()
Системный вызов readlinkat() работает также как системный вызов readlink(), за исключением случаев, описанных здесь.

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

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

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

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

Смотрите в openat(2) объяснение необходимости readlinkat().

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

## ОШИБКИ
EACCES

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

EFAULT

buf выходит за пределы адресного пространства, выделенного процессу.

EINVAL

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

EINVAL

Указанный файл (т. е., последний компонент имени файла pathname) не является символьной ссылкой.

EIO

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

ELOOP

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

ENAMETOOLONG

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

ENOENT

Указанный файл не существует.

ENOMEM

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

ENOTDIR

Компонент в префиксе пути не является каталогом.

В readlinkat() дополнительно могут возникнуть следующие ошибки:

EBADF

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

ENOTDIR

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

## ВЕРСИИ
Системный вызов readlinkat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.

## СООТВЕТСТВИЕ СТАНДАРТАМ
readlink(): 4.4BSD (readlink() появился в 4.2BSD), POSIX.1-2001, POSIX.1-2008.

readlinkat(): POSIX.1-2008.

## ЗАМЕЧАНИЯ
В версиях glibc до glibc 2.4 включительно, тип результата readlink() был объявлен как int. В настоящее время типом возвращаемого результата является ssize_t, как (теперь) это требуется по POSIX.1-2001.

Буфера с фиксированным размером может не хватить для хранения содержимого символьной ссылки. Требуемый размер буфера можно получить как значение stat.st_size, возвращаемое на ссылку вызовом lstat(2). Однако, количество байт, записанное readlink() и readlinkat(), должно быть проверено, так как требуется убедиться, что размер символьной ссылки не увеличился между вызовами. Динамическое выделение буфера для readlink() и readlinkat() также поможет решить проблему с переносимостью, которая возникает, когда для размера буфера используется PATH_MAX, но согласно POSIX для этой константы не гарантируется, что она определена , если система не имеет такого ограничения.

### Замечания по glibc
В старых ядрах, где readlinkat() отсутствует, обёрточная функция glibc использует readlink(). Если pathname является относительным путём, то glibc собирает путь относительно символической ссылки в /proc/self/fd, которая соответствует аргументу dirfd.

## ПРИМЕР
Следующая программа динамически выделяет буфер, необходимый readlink(), из информации, предоставленной lstat(2), или использует буфер размером PATH_MAX, если lstat(2) вернул нулевой размер.

```
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{

    struct stat sb;

    char *buf;

    ssize_t nbytes, bufsiz;

    if (argc != 2) {

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

        exit(EXIT_FAILURE);

    }

    if (lstat(argv[1], &sb) == -1) {

        perror("lstat");

        exit(EXIT_FAILURE);

    }

    /* Добавляем единицу к размеру ссылки, так чтобы можно было определить

       обрезанность буфера, возвращаемого readlink(). */

    bufsiz = sb.st_size + 1;

    /* У некоторых символьных ссылок в (например) /proc и /sys

       значение 'st_size' равно нулю. В этом случае используется

       PATH_MAX как «достаточный» размер. */

    if (sb.st_size == 0)

        bufsiz = PATH_MAX;

    buf = malloc(bufsiz);

    if (buf == NULL) {

        perror("malloc");

        exit(EXIT_FAILURE);

    }

    nbytes = readlink(argv[1], buf, bufsiz);

    if (nbytes == -1) {

        perror("readlink");

        exit(EXIT_FAILURE);

    }

    printf("'%s' указывает на '%.*s'\n", argv[1], (int) nbytes, buf);

    /* Если возвращаемое значение равно размеру буфера, то

       ссылка назначения больше чем ожидалось (возможно, из-за того,

       что цель изменилась между вызовом lstat() и readlink()).

       Предупреждаем пользователя о том, что цель может быть

       обрезана. */

    if (nbytes == bufsiz)

        printf("(Возвращённый буфер мог быть обрезан)\n");

    free(buf);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
readlink(1), lstat(2), stat(2), symlink(2), realpath(3), path_resolution(7), symlink(7)


readv

title: readv(2)

summary: читает или пишет данные

text:
# readv(2)

## ИМЯ
readv, writev, preadv, pwritev, preadv2, pwritev2 - читает или пишет данные в несколько буферов

## ОБЗОР

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

```
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
```

```
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
```

```
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt,
               off_t offset);
```

```
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt,
                off_t offset);
```

```
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
                off_t offset, int flags);
```

```
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
                 off_t offset, int flags);
```

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

preadv(), pwritev():

начиная с glibc 2.19:

_DEFAULT_SOURCE

glibc 2.19 и старее:

_BSD_SOURCE

## ОПИСАНИЕ
Системный вызов readv() считывает iovcnt буферов из файла, связанного с файловым дескриптором fd, в буферы, описываемые iov («разнесённый ввод»).

Системный вызов writev() записывает iovcnt буферов, описанных iov, в файл, связанный с файловым дескриптором fd («сборный вывод»).

Указатель iov указывает на массив структур iovec (определён в <sys/uio.h>:

```
struct iovec {

    void  *iov_base;    /* начальный адрес */

    size_t iov_len;     /* количество передаваемых байт */
};
```

Системный вызов readv() работает также как read(2), но считывает несколько буферов.

Системный вызов writev() работает также как write(2), но записывает несколько буферов.

Буферы выбираются в порядке, в каком они указаны в массиве. Это означает, что readv() сначала полностью заполнит iov[0], и только потом перейдёт к iov[1], и так далее. (Если данных недостаточно, то могут быть заполнены не все буферы, на которые указывает iov.) Подобным образом writev() запишет сначала всё содержимое iov[0], затем iov[1], и так далее.

Выполняемые вызовами readv() и writev() пересылки данных атомарны: данные записываются writev() единичным блоком, который не перемешивается с выводом других процессов (см. исключения в pipe(7)); аналогично, readv() гарантированно считывает непрерывный блок данных из файла, независимо от операций чтения из других нитей или процессов, которые имеют файловые дескрипторы, ссылающиеся на это же открытое файловое описание (см. open(2)).

### preadv() и pwritev()
В системном вызове preadv() объединены возможности readv() и pread(2). Он выполняет ту же задачу что и readv(), но имеет четвёртый аргумент offset, задающий файловое смещение, по которому нужно выполнить операцию чтения.

В системном вызове pwritev() объединены возможности readv() и pwrite(2). Он выполняет ту же задачу что и writev(), но имеет четвёртый аргумент offset, задающий файловое смещение, по которому нужно выполнить операцию записи.

Файловое смещение не изменяется данными вызовами. Файл, заданный в fd, должен позволять изменение смещения.

### preadv2() и pwritev2()
Данные системные вызовы подобны preadv() и pwritev(), но имеют дополнительный пятый аргумент flags, который изменяет поведение в зависимости от вызова.

В отличие от preadv() и pwritev(), если аргумент offset равен -1, то текущее файловое смещение используется и обновляется.

Аргумент flags содержит побитовое ИЛИ нуля и более следующих флагов:

RWF_DSYNC (начиная с Linux 4.7)

Эквивалентен флагу O_DSYNC для open(2), но действующий в конкретной операции записи. Этот флаг имеет смысл только для pwritev2(), и его действие распространяется только на диапазон данных, записываемым системным вызовом.

RWF_HIPRI (начиная с Linux 4.6)

Высокоприоритетное чтение/запись. Позволяет в файловых системах на основе блоков использовать опрос устройства с низкой задержкой, но с возможностью использовать дополнительные ресурсы (в настоящий момент это свойство работает только для файлового дескриптора, открытого с флагом O_DIRECT).

RWF_SYNC (начиная с Linux 4.7)

Эквивалентен флагу O_SYNC для open(2), но действующий в конкретной операции записи. Этот флаг имеет смысл только для pwritev2(), и его действие распространяется только на диапазон данных, записываемым системным вызовом.

RWF_NOWAIT (начиная с Linux 4.14)

Не ждать данные, если пока нет. Если указан этот флаг, то системный вызов preadv2() сразу завершает работу, если бы ему пришлось читать данные из хранилища (backing storage) или ждать блокировку. Если данные прочитаны, то возвращается количество прочитанных байт. Если байты не прочитаны, то возвращается -1 и errno присваивается EAGAIN. В настоящее время, этот флаг учитывается только в preadv2().

RWF_APPEND (начиная с Linux 4.16)

Предоставляет эквивалент флага O_APPEND для open(2) для каждой записи. Данный флаг значим только для pwritev2(), и его действие проявляется только для диапазона данных, записанных системным вызовом. Аргумент offset не учитывается при операции записи; данные всегда добавляются в конец файла. Однако, если аргумент offset равен -1, то обновляется текущее смещение файла.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении readv(), preadv() и preadv2() возвращается количество считанных байт; вызовы writev(), pwritev() and pwritev2() возвращают количество записанных байт.

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

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.

## ОШИБКИ
Вызовы могут возвращать те же ошибки что и read(2) и write(2). Кроме этого, preadv(), preadv2(), pwritev() и pwritev2() также могут завершаться с ошибками как у lseek(2). Дополнительно определены следующие ошибки:

EINVAL

Сумма значений iov_len превышает значение ssize_t.

EINVAL

Количество векторов iovcnt меньше нуля или больше разрешённого максимума.

EOPNOTSUPP

В flags указан неизвестный флаг.

## ВЕРСИИ
Вызовы preadv() и pwritev() впервые появились в Linux 2.6.30; поддержка в библиотеке добавлена в glibc 2.10.

Вызовы preadv2() и pwritev2() впервые появились в Linux 4.6. Поддержка в библиотеке glibc добавлена в версии 2.26.

## СООТВЕТСТВИЕ СТАНДАРТАМ
readv(), writev(): POSIX.1-2001, POSIX.1-2008, 4.4BSD (данные системные вызовы впервые появились в 4.2BSD).

preadv(), pwritev(): нет в стандарте, но есть в современных BSD.

preadv2(), pwritev2(): нестандартные расширения Linux.

## ЗАМЕЧАНИЯ
Согласно POSIX1, в реализации можно устанавливать ограничение на количество элементов, которые можно передать в iov. Реализация может объявить это ограничение в IOV_MAX (в файле <limits.h>) или во время выполнения в виде возвращаемого значения sysconf(_SC_IOV_MAX). В современных Linux данное ограничение равно 1024. В времена Linux 2.0 оно было равно 16.

### Отличия между библиотекой C и ядром
Объявления системных вызовов preadv() и pwritev() немного отличаются от им соответствующих обёрточных функций библиотеки GNU C; они показаны в ОБЗОРЕ. Последний аргумент, offset, раскладывается обёрточными функциями на два для системных вызовов:

unsigned long pos_l, unsigned long pos

В этих аргументах содержатся старшая и младшая 32-битная часть offset, соответственно.

### Исторические отличия между библиотекой C и ядром
Для учёта того, что значение IOV_MAX было мало в старых версиях Linux, обёрточные функции glibc readv() и writev() выполняют дополнительные действия, если обнаруживается, что используемый системный вызов ядра завершился неудачно из-за превышения этого ограничения. В случае readv(), обёрточная функция выделяет временный буфер, достаточный для всех элементов, указанных в iov, передаёт этот буфер в вызов read(2), копирует данные из буфера в места, указанные в полях iov_base элемента iov, а затем освобождает буфер. Обёрточная функция writev() выполняет аналогичную задачу с помощью временного буфера и вызова write(2).

Потребность в дополнительных действиях в обёрточных функциях glibc пропала в Linux 2.2 и новее. Однако glibc продолжала так работать до версии 2.10. начиная с glibc 2.9, обёрточные функции так работают только, если библиотека обнаруживает, что система работает с ядром Linux меньше 2.6.18 (произвольно выбранная версия ядра). И начиная с glibc 2.20 (для которой требуется минимальная версия ядра Linux 2.6.32) обёрточные функции glibc всегда просто вызывают системные вызовы.

## ПРИМЕР
Следующий пример кода демонстрирует использование writev():

```
char *str0 = "hello ";
char *str1 = "world\n";
struct iovec iov[2];
ssize_t nwritten;
iov[0].iov_base = str0;
iov[0].iov_len = strlen(str0);
iov[1].iov_base = str1;
iov[1].iov_len = strlen(str1);
nwritten = writev(STDOUT_FILENO, iov, 2);
```

## СМОТРИТЕ ТАКЖЕ
pread(2), read(2), write(2)


reboot

title: reboot(2)

text:
# reboot(2)

## ИМЯ
reboot - перезагружает систему и разрешает/запрещает использование комбинации Ctrl-Alt-Del

## ОБЗОР
/* Начиная с версии ядра 2.1.30 появились символьные имена LINUX_REBOOT_*

для констант и четвёртый аргумент вызова: */

\#include <unistd.h>

\#include <linux/reboot.h>

int reboot(int magic, int magic2, int cmd, void *arg);

/* В glibc и в большинстве альтернативных libc (включая uclibc,

deitlibc, musl и других) некоторым константам присвоены

символьные имена RB_*, а библиотечная функция является

обёрткой с одним аргументом вокруг системного вызова: */

\#include <unistd.h>

\#include <sys/reboot.h>

int reboot(int cmd);

## ОПИСАНИЕ
Вызов reboot() перезагружает систему или разрешает/запрещает использование для перезагрузки специального сочетания клавиш (сокращённо CAD, от комбинации по умолчанию — Ctrl-Alt-Delete; может быть изменена с помощью loadkeys(1)).

Данный системный вызов завершается ошибкой (EINVAL), если magic не равен LINUX_REBOOT_MAGIC1 (0xfee1dead) и magic2 не равен LINUX_REBOOT_MAGIC2 (672274793). Однако, начиная с 2.1.17 в magic2 также можно использовать LINUX_REBOOT_MAGIC2A (85072278) и начиная с 2.1.97 — LINUX_REBOOT_MAGIC2B (369367448) и начиная с 2.5.71 — LINUX_REBOOT_MAGIC2C (537993216) (шестнадцатеричные значения этих констант говорят сами за себя).

Аргумент cmd может принимать следующие значения:

LINUX_REBOOT_CMD_CAD_OFF

(RB_DISABLE_CAD, 0). Запретить использование сочетания клавиш для перезагрузки системы (CAD). Это означает, что нажатие комбинации клавиш CAD приведёт к тому, что процессу init (с идентификатором 1) будет послан сигнал SIGINT, после чего этот процесс может сам решить какие действия выполнять (возможно, послать сигналы процессам, выполнить команду sync, reboot).

LINUX_REBOOT_CMD_CAD_ON

(RB_ENABLE_CAD, 0x89abcdef). Разрешить использование сочетания клавиш для перезагрузки (CAD). Это означает, что нажатие комбинации клавиш CAD приведёт к немедленному выполнению действия, связанного с LINUX_REBOOT_CMD_RESTART.

LINUX_REBOOT_CMD_HALT

(RB_HALT_SYSTEM, 0xcdef0123; начиная с Linux 1.1.76) Выводится сообщение «System halted.» и система останавливается. Управление передается монитору в ПЗУ, если таковой имеется. Если вызову этой функции не предшествует sync(2), то данные будут потеряны.

LINUX_REBOOT_CMD_KEXEC

(RB_KEXEC, 0x45584543, начиная с Linux 2.6.13) Выполняет ядро, которое было загружено ранее с помощью kexec_load(2). Этот параметр доступен только, если ядро собрано с параметром CONFIG_KEXEC.

LINUX_REBOOT_CMD_POWER_OFF

(RB_POWER_OFF, 0x4321fedc; начиная с Linux 2.1.30) Выводится сообщение «Power down.», система останавливается, и у системы отключаются все источники питания, если это возможно. Если вызову этой функции не предшествует sync(2), то данные будут потеряны.

LINUX_REBOOT_CMD_RESTART

(RB_AUTOBOOT, 0x1234567) Выводится сообщение «Restarting system.», и по умолчанию сразу выполняется перезагрузка системы. Если вызову этой функции не предшествует команда sync(2), то данные будут потеряны.

LINUX_REBOOT_CMD_RESTART2

(0xa1b2c3d4; начиная с Linux 2.1.30) Выводится сообщение «Restarting system with command '%s'» и немедленно выполняется перезагрузка системы (с использованием командной строки, заданной в arg). Если вызову этой функции не предшествует sync(2), то данные будут потеряны.

LINUX_REBOOT_CMD_SW_SUSPEND

(RB_SW_SUSPEND, 0xd000fce1; начиная с Linux 2.5.18) Система переводится в режим ожидания (suspended, hibernated) на диск. Этот параметр доступен только, если ядро собрано с параметром CONFIG_HIBERNATION.

Только суперпользователь может вызывать reboot().

Конкретное действие описанных выше команд зависит от архитектуры системы. Что касается i386, то дополнительный аргумент в данное время ничего не даёт (2.1.122), а тип перезагрузки можно задать в командной строке ядра ("reboot=..."), определив, будет ли перезагрузка "тёплой" или "холодной", а также аппаратной или посредством BIOS.

### Поведение внутри пространств имён PID
Начиная с Linux 3.4, если reboot() вызывается из пространства имён PID, отличающегося от начального пространства имён PID, и и значение cmd равно одному из перечисленных ниже, то выполняется «перезагрузка» в этом пространстве имён: процесс «init» пространства имён PID завершается немедленно, что приводит к результатам, описанным в pid_namespaces(7).

Возможные значения в этом случае, передаваемые в cmd при вызове reboot(), следующие:

LINUX_REBOOT_CMD_RESTART, LINUX_REBOOT_CMD_RESTART2

Процесс «init» завершается и wait(2) в родительском процессе возвращает, что поток завершился по сигналу SIGHUP.

LINUX_REBOOT_CMD_POWER_OFF, LINUX_REBOOT_CMD_HALT

Процесс «init» завершается и wait(2) в родительском процессе возвращает, что поток завершился по сигналу SIGINT.

При других значениях cmd вызов reboot() возвращает -1 и errno присваивается значение EINVAL.

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

## ОШИБКИ
EFAULT

Проблема получения данных пользовательского пространства при LINUX_REBOOT_CMD_RESTART2.

EINVAL

Неправильные идентификационные числа или cmd.

EPERM

Вызывающий процесс не имеет достаточно прав для вызова reboot(); вызывающий должен иметь мандат CAP_SETGID в своём пользовательском пространстве имён.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов reboot() есть только в Linux, и он не должен использоваться в переносимых программах.

## СМОТРИТЕ ТАКЖЕ
systemctl(1), systemd(1), kexec_load(2), sync(2), bootparam(7), capabilities(7), ctrlaltdel(8), halt(8), shutdown(8)


recv

title: recv(2)

summary: принимает сообщение из сокета

text:
# recv(2)

## ИМЯ
recv, recvfrom, recvmsg - принимает сообщение из сокета

## ОБЗОР

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

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

```
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
```

```
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
```

```
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
```

## ОПИСАНИЕ
Системные вызовы recv(), recvfrom() и recvmsg() используются для получения сообщений из сокета. Они могут использоваться для получения данных, независимо от того, является ли сокет ориентированным на соединения или нет. В этой странице сперва описаны общие свойства всех трёх системных вызовов, а затем описываются различия между ними.

Вызов recv() отличается от read(2) только наличием аргумента flags. Если значение flags равно нулю, то вызов recv() эквивалентен read(2) (но смотрите ЗАМЕЧАНИЯ). Также, вызов

recv(sockfd, buf, len, flags);

эквивалентен

recvfrom(sockfd, buf, len, flags, NULL, NULL);

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

Если на сокете не доступно ни одного сообщения, то обсуждаемые вызовы ожидают их прибытия, если сокет не помечен как неблокирующий (см. fcntl(2)), в противном случае возвращается значение -1, а внешняя переменная errno устанавливается в значение EAGAIN или EWOULDBLOCK. Все эти вызовы обычно сразу возвращают все доступные данные вплоть до запрошенного объема, а не ждут, пока появятся данные полной запрошенной длины.

Для определения появления новых данных в сокете приложение может использовать select(2), poll(2) или epoll(7).

### Аргумент флагов
Аргумент flags формируется с помощью объединения логической операцией ИЛИ одного или более следующих значений:

MSG_CMSG_CLOEXEC (только для recvmsg(); начиная с Linux 2.6.23)

Установить флаг close-on-exec для файлового дескриптора, полученного через доменный файловый дескриптор UNIX, с помощью операции SCM_RIGHTS (описана в unix(7)). Этот флаг полезен по тем же причинам что и флаг O_CLOEXEC у open(2).

MSG_DONTWAIT (начиная с Linux 2.2)

Включить неблокирующий режим. Если операция могла бы привести к блокировке, возвращается EAGAIN или EWOULDBLOCK. Такое поведение подобно заданию флага O_NONBLOCK (в fcntl(2) операцией F_SETFL), но отличие в том, что MSG_DONTWAIT указывается в вызове, а O_NONBLOCK задаётся в описании открытого файла (смотрите open(2)), что влияет на все нити вызывающего процесса, а также на другие процессы, у которых есть файловые дескрипторы, ссылающиеся на это описание открытого файла.

MSG_ERRQUEUE (начиная с Linux 2.2)

Указание этого флага позволяет получить из очереди ошибок сокета накопившиеся ошибки. Ошибка передаётся в вспомогательном сообщении тип которого зависит от протокола (для IPv4 это IP_RECVERR). Вызывающий должен предоставить буфер достаточного размера. Дополнительная информация приведена в cmsg(3) и ip(7). Содержимое исходного пакета, который привёл к ошибке, передаётся в виде обычных данных через msg_iovec. Исходный адрес назначения датаграммы, которая привела к ошибке, передаётся через msg_name.

Ошибка передаётся в виде структуры sock_extended_err:

```
#define SO_EE_ORIGIN_NONE    0
#define SO_EE_ORIGIN_LOCAL   1
#define SO_EE_ORIGIN_ICMP    2
#define SO_EE_ORIGIN_ICMP6   3
struct sock_extended_err
{

    uint32_t ee_errno;   /* номер ошибки */

    uint8_t  ee_origin;  /* источник её происхождения */

    uint8_t  ee_type;    /* тип */

    uint8_t  ee_code;    /* код */

    uint8_t  ee_pad;     /* заполнение для выравнивания */

    uint32_t ee_info;    /* дополнительная информация */

    uint32_t ee_data;    /* прочие данные */

    /* далее могут содержаться ещё данные */
};
struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

```

В ee_errno содержится значение errno для ожидающей ошибки. В ee_origin содержится источник происхождения ошибки. Смысл остальных полей зависит от протокола. Макрос SOCK_EE_OFFENDER возвращает указатель на адрес сетевого объекта, породившего ошибку. Если этот адрес неизвестен, то поле sa_family структуры sockaddr содержит значение AF_UNSPEC, а прочие поля структуры sockaddr не определены. Содержимое пакета, вызвавшего ошибку, передаётся в виде обычных данных.

Для локальных ошибок адрес не передаётся (это можно выяснить, проверив поле cmsg_len структуры cmsghdr). Для ошибок при приёме устанавливается флаг MSG_ERRQUEUE в msghdr. После того, как ошибка передана программе, следующая ошибка в очереди ошибок становится ожидающей ошибкой и передается программе при следующей операции на сокете.

MSG_OOB

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

MSG_PEEK

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

MSG_TRUNC (начиная с Linux 2.2)

Для «сырых» данных (AF_PACKET), дейтаграмм Интернета (начиная с Linux 2.4.27/2.6.8), netlink (начиная с Linux 2.6.22) и дейтаграмм UNIX (начиная с Linux 3.4) возвращает реальную длину пакета или дейтаграммы, даже если она была больше, чем предоставленный буфер.

Описание использования с потоковым сокетами Интернета смотрите в tcp(7).

MSG_WAITALL (начиная с Linux 2.2)

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

### recvfrom()
Вызов recvfrom() помещает принятое сообщение в буфер buf. Вызывающий должен указать размер буфера в len.

Если значение src_addr не равно NULL, и в нижележащем протоколе используется адрес источника сообщения, то адрес источника помещается в буфер, указанный в src_addr. В этом случае addrlen является аргументом-результатом. Перед вызовом ему должно быть присвоено значение длины буфера, связанного с src_addr. При возврате addrlen обновляется и содержит действительный размер адреса источника. Возвращаемый адрес обрезается, если предоставленный буфер слишком мал; в этом случае addrlen будет содержать значение большее, чем указывалось в вызове.

Если вызывающему адрес источника не нужен, то значение src_addr и addrlen должно быть равно NULL.

### recv()
Вызов recv(), обычно, используется только на соединённом сокете (смотрите connect(2)). Он идентичен вызову:

recvfrom(fd, buf, len, flags, NULL, 0);

### recvmsg()
Для минимизации количества передаваемых аргументов в вызов recvmsg() используется структура msghdr. Она определена в <sys/socket.h> следующим образом:

```
struct iovec {                    /* массив элементов приёма/передачи */

    void  *iov_base;              /* начальный адрес */

    size_t iov_len;               /* количество передаваемых байт */
};
struct msghdr {

    void         *msg_name;       /* необязательный адрес */

    socklen_t     msg_namelen;    /* размер адреса */

    struct iovec *msg_iov;        /* массив приёма/передачи */

    size_t        msg_iovlen;     /* количество элементов в msg_iov */

    void         *msg_control;    /* вспомогательные данные,

                                     см. ниже */

    size_t        msg_controllen; /* размер буфера вспомогательных

                                     данных */

    int           msg_flags;      /* флаги принятого сообщения */
};
```

Поле msg_name указывает на выделенный вызывающим буфер, который используется для возврата адреса источника, если сокет не соединён. Вызывающий должен указать в msg_namelen размер этого буфера перед вызовом; при успешном выполнении вызова в msg_namelen будет содержаться длина возвращаемого адреса. Если приложению не нужно знать адрес источника, то в msg_name можно указать NULL.

В полях msg_iov и msg_iovlen описываются место приёма/передачи, обсуждаемые в readv(2).

Поле msg_control длиной msg_controllen указывает на буфер для других сообщений, связанных с управлением протоколом или на буфер для разнообразных вспомогательных данных. При вызове recvmsg() в поле msg_controllen должен указываться размер доступного буфера, чей адрес передан в msg_control; при успешном выполнении вызова в этом параметре будет находиться длина последовательности контрольных сообщений.

Сообщения имеют следующий вид:

```
struct cmsghdr {

    size_t cmsg_len;    /* счетчик байтов данных с заголовком

                           (тип — socklen_t в POSIX) */

    int    cmsg_level;  /* начальный протокол */

    int    cmsg_type;   /* тип, зависящий от протокола */
/* после

   unsigned char cmsg_data[]; */
};
```

К вспомогательным данным нужно обращаться только с помощью макросов, определённых в cmsg(3).

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

При возврате из recvmsg() устанавливается значение поля msg_flags в msghdr. Оно может содержать несколько флагов:

MSG_EOR

означает конец записи: возвращённые данные заканчивают запись (обычно используется вместе с сокетами типа SOCK_SEQPACKET).

MSG_TRUNC

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

MSG_CTRUNC

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

MSG_OOB

возвращается для индикации, что получены курируемые или внеполосные данные.

MSG_ERRQUEUE

означает, что были получены не данные, а расширенное сообщение об ошибке из очереди ошибок сокета.

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

Когда ответная сторона потока выполняет корректное отключение (shutdown), то возвращается 0 (обычный возврат «конец файла»).

В датаграмных сокетах некоторых доменов (например, доменах UNIX и Internet) разрешены датаграммы нулевой длины. При получении такой датаграммы возвращается значение 0.

Также значение 0 может возвращаться, если запрошенное количество принимаемых байт из потокового сокета равно 0.

## ОШИБКИ
Здесь представлено несколько стандартных ошибок, возвращаемых с уровня сокетов. Могут также появиться другие ошибки, возвращаемые из соответствующих протокольных модулей; их описание находится в соответствующих справочных страницах.

EAGAIN или EWOULDBLOCK

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

EBADF

Аргумент sockfd содержит неверный файловый дескриптор.

ECONNREFUSED

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

EFAULT

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

EINTR

Приём данных был прерван сигналом, а данные ещё не были доступны; смотрите signal(7).

EINVAL

Передан неверный аргумент.

ENOMEM

Не удалось выделить память для recvmsg().

ENOTCONN

Сокет, связанный с протоколом, ориентированным на соединение, не был соединён (см. connect(2) и accept(2)).

ENOTSOCK

Файловый дескриптор sockfd указывает не на каталог.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, 4.4BSD (эти интерфейсы впервые появились в 4.2BSD).

В POSIX.1 описаны только флаги MSG_OOB, MSG_PEEK и MSG_WAITALL.

## ЗАМЕЧАНИЯ
Если ожидает дейтаграмма нулевой длины, то read(2) и recv() с нулевым аргументом flags работают по-разному. В этом случае read(2) ничего не делает (дейтаграмма продолжает ждать), а recv() обрабатывает ожидающую дейтаграмму.

Тип socklen_t появился из POSIX. Также смотрите accept(2).

В соответствие с POSIX.1 поле msg_controllen структуры msghdr должно иметь тип socklen_t, но в настоящее время в glibc оно имеет тип size_t.

В recvmmsg(2) можно найти информацию о специальном системном вызове Linux, который можно использовать для приёма нескольких датаграмм за один вызов.

## ПРИМЕР
Пример использования recvfrom() показан в getaddrinfo(3).

## СМОТРИТЕ ТАКЖЕ
fcntl(2), getsockopt(2), read(2), recvmmsg(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3), ip(7), ipv6(7), socket(7), tcp(7), udp(7), unix(7)


recvmmsg

title: recvmmsg(2)

summary: получает несколько сообщений из сокета

text:
# recvmmsg(2)

## ИМЯ
recvmmsg - получает несколько сообщений из сокета

## ОБЗОР

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

```
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
             int flags, struct timespec *timeout);
```

## ОПИСАНИЕ
Системный вызов recvmmsg() является расширенной версией recvmsg(2), позволяя вызывающему получать несколько сообщений из сокета, используя только один системный вызов (в некоторых приложениях это позволяет получить выигрыш в производительности). Ещё одно улучшение recvmsg(2) — настройка времени ожидания для операции получения.

Аргумент sockfd представляет собой файловый дескриптор сокета приёма данных.

Аргумент msgvec является указателем на массив структур mmsghdr. Размер этого массива указывается в vlen.

Структура mmsghdr определена в <sys/socket.h> следующим образом:

```
struct mmsghdr {

    struct msghdr msg_hdr;  /* Заголовок сообщения */

    unsigned int  msg_len;  /* Количество полученных байт

                               для заголовка */
};
```

Поле msg_hdr представляет собой структуру msghdr, которая описана в recvmsg(2). В поле msg_len содержится количество байт возвращаемого сообщения в записи. Это поле имеет такое же значение, что и возвращаемое значение одиночного вызова recvmsg(2) в заголовке.

Аргумент flags содержит объединённые с помощью OR флаги. Флаги те же, что и у recvmsg(2), но со следующим дополнением:

MSG_WAITFORONE (начиная с Linux 2.6.34)

Включить MSG_DONTWAIT после получения первого сообщения.

Аргумент timeout указывает на struct timespec (смотрите clock_gettime(2)), задающую время ожидания (в секундах и наносекундах) операции приёма (но смотрите ДЕФЕКТЫ!; (этот интервал будет округлён до точности системных часов, и из-за задержек планировщика ядра интервал блокировки может быть немного больше). Если timeout равно NULL, то операция блокируется на неопределённое время.

Блокирование вызова recvmmsg() происходит до тех пор, пока не будет получено vlen сообщений или не истечёт интервал блокировки. Неблокирующий вызов читает все доступные сообщения (максимальное количество указано в vlen) и сразу завершает работу.

При выходе из recvmmsg() последующие элементы msgvec обновляются информацией о каждом полученном сообщении: в msg_len содержится размер принятого сообщения; подполя msg_hdr обновляются согласно описанию в recvmsg(2). Возвращаемое значение вызова означает количество обновлённых элементов msgvec.

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

## ОШИБКИ
Возникают те же ошибки что и для recvmsg(2). Кроме этого, случается следующая ошибка:

EINVAL

Значение timeout неверно.

Также смотрите ДЕФЕКТЫ.

## ВЕРСИИ
Системный вызов recvmmsg() был добавлен в Linux 2.6.33. Поддержка в glibc появилась в версии 2.12.

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

## ДЕФЕКТЫ
Аргумент timeout работает не так, как планировалось. Время ожидания проверяется только после приёма каждой дейтаграммы, поэтому, если до истечения срока будет получено до vlen-1 дейтаграмм, но затем дейтаграммы не поступят, то вызов заблокируется навсегда.

Если ошибка возникает после получения хотя бы одного сообщения, то вызов выполняется успешно и возвращается количество полученных сообщений. Код ошибки будет возвращён следующим вызовом recvmmsg(). Однако в текущей реализации код ошибки может перезаписаться при возникновении в тоже время события, не связанного с сетью, например, из-за поступившего пакета ICMP.

## ПРИМЕР
Следующая программа использует recvmmsg() для получения нескольких сообщений через сокет и сохранения их в несколько буферов. Вызов завершается при заполнении всех буферов, либо по окончании заданного временного интервала.

Следующий отрывок периодически генерирует датаграммы UDP с произвольным номером внутри:

```
$ while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234;
sleep 0.25; done
```

Эти датаграммы читаются примером приложения, который выдаёт:

```
$ ./a.out
5 сообщений получено
1 11782
2 11345
3 304
4 13514
5 28421
```

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

```
#define _GNU_SOURCE
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
int
main(void)
{
#define VLEN 10
#define BUFSIZE 200
#define TIMEOUT 1

    int sockfd, retval, i;

    struct sockaddr_in addr;

    struct mmsghdr msgs[VLEN];

    struct iovec iovecs[VLEN];

    char bufs[VLEN][BUFSIZE+1];

    struct timespec timeout;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if (sockfd == -1) {

        perror("socket()");

        exit(EXIT_FAILURE);

    }

    addr.sin_family = AF_INET;

    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    addr.sin_port = htons(1234);

    if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {

        perror("bind()");

        exit(EXIT_FAILURE);

    }

    memset(msgs, 0, sizeof(msgs));

    for (i = 0; i < VLEN; i++) {

        iovecs[i].iov_base         = bufs[i];

        iovecs[i].iov_len          = BUFSIZE;

        msgs[i].msg_hdr.msg_iov    = &iovecs[i];

        msgs[i].msg_hdr.msg_iovlen = 1;

    }

    timeout.tv_sec = TIMEOUT;

    timeout.tv_nsec = 0;

    retval = recvmmsg(sockfd, msgs, VLEN, 0, &timeout);

    if (retval == -1) {

        perror("recvmmsg()");

        exit(EXIT_FAILURE);

    }

    printf("%d сообщений получено\n", retval);

    for (i = 0; i < retval; i++) {

        bufs[i][msgs[i].msg_len] = 0;

        printf("%d %s", i+1, bufs[i]);

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
clock_gettime(2), recvmsg(2), sendmmsg(2), sendmsg(2), socket(2), socket(7)


title: remap_file_pages(2)

summary: создаёт нелинейное файловое отображение

text:
# remap_file_pages(2)

## ИМЯ
remap_file_pages - создаёт нелинейное файловое отображение

## ОБЗОР

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

```
int remap_file_pages(void *addr, size_t size, int prot,
                     size_t pgoff, int flags);
```

## ОПИСАНИЕ
Замечание: данный системный вызов, начиная с Linux 3.16, устарел. В Linux 4.0 реализация была заменена на более медленную эмуляцию ядром. В приложениях, где он используется, нужно применять альтернативные вызовы. Данное изменение было сделано из-за сложности кода ядра этого системного вызова, и считается, что им почти никто или вообще никто не пользуется. Какое-то время он использовался в приложениях баз данных на 32-разрядных системах, но этих вариантов использования на 64-разрядных системах замечено не было.

Системный вызов remap_file_pages() используется для создания нелинейного отображения, то есть отображения, в котором страницы файла отображаются в память непоследовательно. Преимущество использования remap_file_pages() по сравнению с повторением вызовов mmap(2) в том, что первый не требует от ядра создания дополнительных структур данных VMA (областей виртуальной памяти).

Для создания нелинейного отображения выполните следующее:

1.

Создайте отображение (пока линейное) с помощью mmap(2). Данное отображение должно создаваться с флагом MAP_SHARED.

2.

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

В аргументах pgoff и size указывается область файла, которая будет перенесёна в отображение: в pgoff задаётся смещение в файле, измеряемое в размерах системных страниц; в size задаётся длина области в байтах.

Аргумент addr предназначен для двух целей. Во-первых, им определяется отображение, чьи страницы мы хотим перенести. То есть в addr должен быть указан адрес в области, которая была ранее отображена с помощью вызова mmap(2). Во-вторых, в addr указывается адрес, по которому должны быть помещены файловые страницы, заданные pgoff и size.

Значения, указанные в addr и size, должны быть кратны размеру системной страницы. Если это не так, то ядро округляет оба значения в меньшую сторону до ближайшего числа, кратного размеру страницы.

Значение аргумента prot должно быть 0.

Аргумент flags предназначен для того же, что и в mmap(2), но все флаги, кроме MAP_NONBLOCK, игнорируются.

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

## ОШИБКИ
EINVAL

Значение addr не ссылается на допустимое отображение, созданное с флагом MAP_SHARED.

EINVAL

Некорректное значение в addr, size, prot или pgoff.

## ВЕРСИИ
Системный вызов remap_file_pages() появился в Linux 2.5.46; поддержка в glibc началась с версии 2.3.3.

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

## ЗАМЕЧАНИЯ
Начиная с Linux 2.6.23, remap_file_pages() создаёт нелинейные отображения только для файловых систем в оперативной памяти, таких как tmpfs(5), hugetlbfs или ramfs. Для файловых систем с хранилищем remap_file_pages() не намного эффективнее чем mmap(2), так как рассчитывает адреса для частей файла.

## СМОТРИТЕ ТАКЖЕ
getpagesize(2), mmap(2), mmap2(2), mprotect(2), mremap(2), msync(2)


removexattr

title: removexattr(2)

summary: удаление расширенных атрибутов

text:
# removexattr(2)

## ИМЯ
removexattr, lremovexattr, fremovexattr - удаление расширенных атрибутов

## ОБЗОР

```
#include <sys/types.h>
#include <sys/xattr.h>
```

```
int removexattr(const char *path, const char *name);
int lremovexattr(const char *path, const char *name);
int fremovexattr(int fd, const char *name);
```

## ОПИСАНИЕ
Расширенные атрибуты представляют собой пару имя:значение и связываются с записями inode (файлы, каталоги, символьные ссылки и т.п.). Они являются расширениями к обычным атрибутам, связанным со всеми записями inode в системе (например, данные stat(2)). Полное описание модели расширенных атрибутов можно найти в xattr(7).

Вызов removexattr() удаляет расширенный атрибут с именем, заданным в name и связанный с заданным path в файловой системе.

Вызов lremovexattr() идентичен removexattr(), за исключением случая работы с символьными ссылками; он удаляет расширенный атрибут на ссылке, а не на файле, на который она указывает.

Вызов fremovexattr() идентичен removexattr(), отличием является то, что расширенный атрибут удаляется у открытого файла, на который указывает fd (возвращаемый open(2)), а не на указанном в path.

Имя расширенного атрибута представляет собой строку, заканчивающуюся NULL. Имя name включает префикс пространства имён; их может быть несколько, разрозненные пространства ассоциируются с разными inode.

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

## ОШИБКИ
ENODATA

Указанный атрибут не существует.

ENOTSUP

Расширенные атрибуты не поддерживаются файловой системой или отключены.

Также могут возникать ошибки, описанные в stat(2).

## ВЕРСИИ
Данные системные вызовы доступны в Linux начиная с ядра версии 2.4; поддержка в glibc появилась в версии 2.3.

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

## СМОТРИТЕ ТАКЖЕ
getfattr(1), setfattr(1), getxattr(2), listxattr(2), open(2), setxattr(2), stat(2), symlink(7), xattr(7)


rename

title: rename(2)

summary: изменяет имя или расположение файла

text:
# rename(2)

## ИМЯ
rename, renameat, renameat2 - изменяет имя или расположение файла

## ОБЗОР

```
#include <stdio.h>
```

```
int rename(const char *oldpath, const char *newpath);
#include <fcntl.h>           /* определения констант AT_* */
#include <stdio.h>
```

```
int renameat(int olddirfd, const char *oldpath,
             int newdirfd, const char *newpath);
```

```
int renameat2(int olddirfd, const char *oldpath,
              int newdirfd, const char *newpath, unsigned int flags);
```

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

renameat():

Начиная с glibc 2.10:

_POSIX_C_SOURCE >= 200809L

До glibc 2.10:

_ATFILE_SOURCE

renameat2():

_GNU_SOURCE

## ОПИСАНИЕ
Вызов rename() переименовывает файл и, если требуется, перемещает его из одного каталога в другой. Все прочие жёсткие ссылки на файл (созданные с помощью link(2)), не изменяются. Открытые файловые дескрипторы на oldpath также не изменяются.

На успешность выполнения операции переименования влияют различные ограничения: смотрите ОШИБКИ далее.

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

Если oldpath и newpath являются жёсткими ссылками на один и тот же файл, то rename() ничего не делает и возвращает код успешного выполнения.

Если newpath существует, но операция завершается ошибкой, то rename() гарантирует, что newpath останется нетронутым.

В oldpath может быть указан каталог. В этом случае каталог в newpath должен или не существовать, или должен быть пуст.

Если oldpath является символьной ссылкой, то она переименовывается; если newpath является символьной ссылкой, то будет вновь записан файл, на который она указывает.

### renameat()
Системный вызов renameat() работает также как системный вызов rename(), за исключением случаев, описанных далее.

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

Если в oldpath указан относительный путь и olddirfd равно специальному значению AT_FDCWD, то oldpath рассматривается относительно текущего рабочего каталога вызывающего процесса (как rename()).

Если в oldpath указан абсолютный путь, то olddirfd игнорируется.

Значение newpath интерпретируется как oldpath, за исключением того, что относительный путь интерпретируется относительно каталога, на который ссылается файловый дескриптор newdirfd.

Смотрите в openat(2) объяснение необходимости renameat().

### renameat2()
Вызов renameat2() имеет дополнительный аргумент flags. Если значение flags равно нулю, то renameat2() эквивалентен renameat().

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

RENAME_EXCHANGE

Атомарно обменять oldpath и newpath. Оба пути должны существовать, но могут быть различных типов (например, один может быть непустым каталогом, а другой символической ссылкой).

RENAME_NOREPLACE

Не перезаписывать newpath. Возвращать ошибку, если newpath уже существует.

RENAME_NOREPLACE не может быть применен вместе с RENAME_EXCHANGE.

Для RENAME_NOREPLACE требуется поддержка в файловой системе; она есть только у нескольких файловых систем:

- ext4 (начиная с Linux 3.15);

- btrfs, shmem, и cifs (начиная с Linux 3.17);

- xfs (начиная с Linux 4.0);

- Поддержка для других файловых систем была добавлена в Linux 4.9: etx2, minix, reiserfs, jfs, vfat и bpf.

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

Эта операция применима только для реализаций оверлейных/объединённых файловых систем.

При указании RENAME_WHITEOUT для источника переименования одновременно с выполнением переименования создаётся «замазанный» объект (whiteout object). Вся операция атомарна, и при успешном выполнении переименования создаётся и замазка.

«Замазка» — это объект, имеющий специальное предназначение в оверлейных/объединённых файловых системах. В них существует несколько слоёв, и для изменения доступен только верхний. Замазка на верхнем слое эффективно скрывает файл из нижнего слоя, и кажется, что файл не существует.

Когда переименовывается файл, существующий в нижнем слое, то первым действием он переписывается (если его уже нет в верхнем слое) и переименовывается в верхнем, доступном на чтение-запись слое. Одновременно с этим, исходный файл требуется «замазать» (что исходный файл в нижнем слое отражался невидимым). Вся операция должна выполняться атомарно.

При отсутствии объединения/оверлея замазка появляется в виде символьного устройства с номером устройства {0,0} (заметим, что в других реализациях объединения/оверлея могут использоваться другие методы хранения элементов замазки; в частности, в BSD для объединения монтирования используется специальный тип иноды, DT_WHT, который, хотя и поддерживается некоторыми файловыми системами, доступными в Linux, например CODA и XFS, но игнорируется кодом поддержки замазки в ядре, по крайней мере, в Linux 4.19).

Для RENAME_WHITEOUT требуются те же права, что и для создания узла устройства (т. е., мандата CAP_MKNOD).

RENAME_WHITEOUT не может быть применён вместе с RENAME_EXCHANGE.

Для RENAME_WHITEOUT требуется поддержка в файловой системе. Такая поддержка имеется в tmpfs (начиная с Linux 3.18), ext4 (начиная с Linux 3.18), XFS (начиная с Linux 4.1), f2fs (начиная с Linux 4.2), btrfs (начиная с Linux 4.7) и ubifs (начиная с Linux 4.9).

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

## ОШИБКИ
EACCES

Запись в каталог, содержащий oldpath или newpath, запрещена, или в одном из каталогов пути oldpath или newpath нельзя производить поиск, или oldpath является каталогом, в который запрещена запись (требует обновления элемента ..); смотрите также path_resolution(7)).

EBUSY

Переименование завершилось неудачно, так как oldpath или newpath является каталогом, который используется другим процессом (возможно в качестве текущего рабочего каталога или в качестве корневого каталога, или он открыт на чтение), или используется системой (например, в качестве точки монтирования), и система считает это ошибкой (заметим, что нет требования возвращать EBUSY в таких случаях — нет ничего неправильного в таком переименовании — но разрешается возвращать EBUSY, если система не может иначе обработать такие ситуации).

EDQUOT

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

EFAULT

Значения oldpath и newpath указывают за пределы доступного адресного пространства.

EINVAL

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

EISDIR

Каталог newpath уже существует, но oldpath не является каталогом.

ELOOP

Во время определения oldpath или newpath встретилось слишком много символьных ссылок.

EMLINK

В oldpath уже имеется максимальное количество ссылок, или каталог, содержащий newpath, уже имеет максимальное количество ссылок.

ENAMETOOLONG

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

ENOENT

Ссылка, на которую ссылается oldpath, не существует; компонент каталога в newpath не существует; в oldpath или newpath указана пустая строка.

ENOMEM

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

ENOSPC

На устройстве, содержащем файл, нет места для создания нового элемента каталога.

ENOTDIR

Компонент, используемый как каталог в oldpath или newpath, в действительности не является каталогом. Или oldpath является каталогом и существует newpath, который не является каталогом.

ENOTEMPTY или EEXIST

Значение newpath является непустым каталогом, то есть содержит элементы, отличные от «.» и «..».

EPERM или EACCES

Каталог, содержащийся в oldpath, имеет закрепляющий бит (S_ISVTX) и эффективный идентификатор процесса не совпадает с идентификатором пользователя удаляемого файла или каталога, его содержащего, и процесс не имеет прав (Linux: нет мандата CAP_FOWNER); или newpath является существующим файлом и каталог, содержащий его, имеет закрепляющий бит и эффективный идентификатор процесса не совпадает с идентификатором пользователя замещаемого файла или каталога, его содержащего, и процесс не имеет прав (Linux: нет мандата CAP_FOWNER); или файловая система, содержащая pathname, не поддерживает переименования запрашиваемого типа.

EROFS

Файл расположен в файловой системе, доступной только для чтения.

EXDEV

Элементы oldpath и newpath находятся не в одной смонтированной файловой системе (Linux позволяет монтировать файловую систему в несколько точек, но rename() не работает с различающимися точками монтирования, даже если в них смонтирована идентичная файловая система).

В renameat() и renameat2() дополнительно могут возникнуть следующие ошибки:

EBADF

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

ENOTDIR

Значение oldpath содержит относительный путь и olddirfd содержит файловый дескриптор, указывающий на файл, а не на каталог; или произошло тоже самое с newpath и newdirfd.

В renameat2() дополнительно могут возникнуть следующие ошибки:

EEXIST

Значение flags содержит RENAME_NOREPLACE, а newpath уже существует.

EINVAL

В flags указан неверный флаг.

EINVAL

В flags указаны оба флага, RENAME_NOREPLACE и RENAME_EXCHANGE.

EINVAL

В flags указаны оба флага, RENAME_WHITEOUT и RENAME_EXCHANGE.

EINVAL

Файловая система не поддерживает один из флагов в flags.

ENOENT

В flags содержится RENAME_EXCHANGE, но newpath не существует.

EPERM

В flags указан флаг RENAME_WHITEOUT , но вызывающий не имеет мандата CAP_MKNOD.

## ВЕРСИИ
Системный вызов renameat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.

Вызов renameat2() был добавлен в Linux 3.15; поддержка в glibc доступна с версии 2.28.

## СООТВЕТСТВИЕ СТАНДАРТАМ
rename(): 4.3BSD, C89, C99, POSIX.1-2001, POSIX.1-2008.

renameat(): POSIX.1-2008.

Вызов renameat2() есть только в Linux.

## ЗАМЕЧАНИЯ

### Замечания по glibc
В старых ядрах, где renameat() отсутствует, обёрточная функция glibc использует rename(). Если oldpath и newpath являются относительными путями, то glibc собирает пути относительно символической ссылки в /proc/self/fd, которая соответствует аргументам olddirfd и newdirfd.

## ДЕФЕКТЫ
При работе с файловыми системами NFS нельзя считать, что если операция завершилась неудачно, то имя файла не изменилось. Если сервер производит операцию переименования, а затем аварийно останавливает свою работу, то перепосланный пакет RPC будет вновь обработан при восстановлении работы сервера, что вызовет сообщение об ошибке. Приложение в этой ситуации должно работать корректно. Смотрите link(2), где описывается подобная проблема.

## СМОТРИТЕ ТАКЖЕ
mv(1), chmod(2), link(2), symlink(2), unlink(2), path_resolution(7), symlink(7)


title: request_key(2)

text:
# request_key(2)

## ИМЯ
request_key - запрашивает ключ из системы управления ключами ядра

## ОБЗОР

```
#include <sys/types.h>
#include <keyutils.h>
```

```
key_serial_t request_key(const char *type, const char *description,
                         const char *callout_info,
                         key_serial_t dest_keyring);
```

В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.

## ОПИСАНИЕ
Системный вызов request_key() пытается найти ключ заданного type с описанием (именем), совпадающим с description. Если ключ найти невозможно, то ключ может быть создан. Если ключ найден или создан, то request_key() присоединяет его к связке ключей, чей идентификатор указан keyring, и возвращает серийный номер ключа.

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

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

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

Если ключ не найден и callout равно NULL, то вызов завершается ошибкой ENOKEY.

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

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

KEY_SPEC_THREAD_KEYRING

Связка ключей вызывающей нити (смотрите thread-keyring(7)).

KEY_SPEC_PROCESS_KEYRING

Связка ключей вызывающего процесса (смотрите process-keyring(7)).

KEY_SPEC_SESSION_KEYRING

Связка ключей сеанса вызывающего (смотрите session-keyring(7)).

KEY_SPEC_USER_KEYRING

Связка ключей по UID вызывающего (смотрите user-keyring(7)).

KEY_SPEC_USER_SESSION_KEYRING

Связка ключей по UID сеанса вызывающего (смотрите user-session-keyring(7)).

Если dest_keyring равно 0 и создание ключа не выполнено, то дополнительных связей не появляется.

В противном случае, если dest_keyring равно 0 и создан новый ключ, то новый ключ будет прицеплен в связку ключей «по умолчанию». Более точно, когда ядро пытается определить в какую связку ключей должен быть прицеплен то только что созданный ключ, оно перебирает связки ключей начиная с со связки, установленной через keyctl(2) с операцией KEYCTL_SET_REQKEY_KEYRING и продолжает в порядке, показанном далее, пока не найдёт существующую связку ключей:

- Связка ключей запрашивающего (KEY_REQKEY_DEFL_REQUESTOR_KEYRING, начиная с Linux 2.6.29).

- Связка ключей нити (KEY_REQKEY_DEFL_THREAD_KEYRING; смотрите thread-keyring(7)).

- Связка ключей процесса (KEY_REQKEY_DEFL_PROCESS_KEYRING; смотрите process-keyring(7)).

- Связка ключей сеанса (KEY_REQKEY_DEFL_SESSION_KEYRING; смотрите session-keyring(7)).

- Связка ключей сеанса для идентификатора пользователя процесса (KEY_REQKEY_DEFL_USER_SESSION_KEYRING; смотрите user-session-keyring(7)). Ожидается, что эта связка ключей всегда существует.

- Связка ключей для идентификатора пользователя процесса (KEY_REQKEY_DEFL_USER_KEYRING; смотрите user-keyring(7)). Ожидается, что эта связка ключей также всегда существует.

Если вызов keyctl(2) с операцией KEYCTL_SET_REQKEY_KEYRING установил KEY_REQKEY_DEFL_DEFAULT (или операция KEYCTL_SET_REQKEY_KEYRING не выполнялась), то ядро ищет связку ключей начиная с начала списка.

### Запрос на создание ключа из пользовательского пространства
Если ядро не может найти ключ с соответствующим type и description, и callout не равно NULL, то ядро пытается вызвать программу из пользовательского пространства для создания ключа с заданными type и description. В этом случае выполняются следующие шаги:

а)

Ядро создаёт неинициализированный ключ U с запрошенными type и description.

б)

Ядро создаёт ключ авторизации V, который ссылается на ключ U и сохраняются данные вызывающего request_key():

(1)

контекст, в котором ключ U должен быть создан и защищён и

(2)

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

Ключ авторизации создаётся со следующими свойствами:

- Тип ключа — ".request_key_auth".

- UID и GID ключа совпадают с ID в файловой системе для запрашивающего процесса.

- Ключ даёт права на просмотр, чтение и поиск на ключ-владелец, а также право просмотра для ключа пользователя.

- Описание (имя) ключа представляет собой Шестнадцатеричную строку идентификатора ключа, который будет создан в запрашивающей программе.

- Полезные данные ключа берутся из данных callout_info.

- Внутри ядра также сохраняется PID процесса, который был вызван request_key().

в)

Ядро создаёт процесс, который запускает службу пользовательского пространства, такую как request-key(8), с новой связкой ключей сеанса с прицепленным ключом авторизации V.

Данной программе передаются следующие аргументы командной строки:

[0]

Строка "/sbin/request-key".

[1]

Строка "create" (показывающая, что ключ будет создан).

[2]

Идентификатор ключа, который будет создан.

[3]

UID (в файловой системе) вызывающего request_key().

[4]

GID (в файловой системе) вызывающего request_key().

[5]

Идентификатор связки ключей нити вызывающего request_key(). Может быть ноль, если связка ключей не создана.

[6]

Идентификатор связки ключей процесса вызывающего request_key(). Может быть ноль, если связка ключей не создана.

[7]

Идентификатор связки ключей сеанса вызывающего request_key().

Замечание: каждый аргумент командной строки, обозначающий идентификатор ключа, кодируется десятичным числом (в отличие от идентификаторов ключе, показанных в /proc/keys, которые выдаются в виде шестнадцатеричных значений).

г)

Программа, порождённая на предыдущем шаге:

- Принимает полномочия на создание ключа U с помощью keyctl(2) с операцией KEYCTL_ASSUME_AUTHORITY (обычно, с помощью функции keyctl_assume_authority(3)).

- Получает исходящие данные (callout data) из полезной нагрузки ключа авторизации V (с помощью keyctl(2) с операцией KEYCTL_READ (или, чаще всего, с помощью функции keyctl_read(3)) с значением идентификатора ключа KEY_SPEC_REQKEY_AUTH_KEY.

- Создаёт ключ (или выполняет другую программу, которая делает эту работу), с заданной полезной нагрузкой и связкой ключей назначения (связка ключей назначения та, которую запрашивающий указал при вызове request_key(), и которая быть доступна через специальный идентификатор ключа KEY_SPEC_REQUESTOR_KEYRING). Создание выполняется с помощью keyctl() с операцией KEYCTL_INSTANTIATE (или, чаще всего, с помощью функции keyctl_instantiate(3)). На этот момент вызов request_key() завершается и запрашивающая программа может продолжать выполнение.

Если какой-то из этих шагов завершается ошибкой, то вызвавшему request_key() возвращается ENOKEY и временно в связку ключей dest_keyring будет установлен отрицательно инициализированный ключ. Он устареет через несколько секунд, но пока этого не произойдёт все последующие вызовы request_key() будут завершаться ошибкой. Целью данного отрицательно инициализированного ключа является предотвращение повторяющихся запросов (возможно разными) процессами (они требуют затратных восходящих вызовов request-key(8)) для ключа, который невозможно (в данный момент) положительно инициализировать.

После инициализации ключа, ключ авторизации (KEY_SPEC_REQKEY_AUTH_KEY) отзывается и связка ключей назначения (KEY_SPEC_REQUESTOR_KEYRING) становится недоступной программе request-key(8).

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

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

## ОШИБКИ
EACCES

Изменение связки ключей пользователю недоступно.

EDQUOT

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

EFAULT

Значение type, description или callout_info указывают вне доступного адресного пространства процесса.

EINTR

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

EINVAL

Размер строки (включая конечный байт null), заданной в type или description, превышает ограничение (32 байта и 4096 байт, соответственно).

EINVAL

Размер строки (включая конечный байт null), заданной в callout_info, превышает размер системной страницы.

EKEYEXPIRED

Найден просроченный ключ, и замена не может быть получена.

EKEYREJECTED

Попытка генерации нового ключа была отвергнута.

EKEYREVOKED

Найден отозванный ключ, и замена не может быть получена.

ENOKEY

Искомый ключ не найден.

ENOMEM

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

EPERM

Аргумент type начинается с точки ('.').

## ВЕРСИИ
Данный системный вызов впервые появился в Linux 2.6.10. Возможность инициализации ключей по запросу была добавлена в Linux 2.6.13.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Этот системный вызов является нестандартным расширением Linux.

## ЗАМЕЧАНИЯ
В glibc нет обёрточной функции для этого системного вызова. Такая функция предоставляется пакетом libkeyutils. Для работы с функцией подключите библиотеку с помощью -lkeyutils.

## ПРИМЕР
В программе, представленной ниже, показано использование request_key(). Аргументы type, description и callout_info для системного вызова берутся из значений, переданных в аргументах командной строки. В качестве связки ключей назначения вызов использует связку ключей сеанса.

Чтобы показать работу программы сначала нужно создать подходящую запись в файле /etc/request-key.conf.

```
$ sudo sh
# echo 'create user mtk:* *   /bin/keyctl instantiate %k %c %S' \

          > /etc/request-key.conf
# exit
```

Эта запись говорит о том, что когда должен быть создан новый ключ «user» с префиксом «mtk:», задача должна выполняться посредством команды keyctl(1) с операцией instantiate. Аргументы, передаваемые операции instantiate: идентификатор неинициализированного ключа (%k); исходящие данные, переданные в вызов request_key() (%c); связка ключей сеанса (%S) запрашивающего (т. е., вызывающий request_key()). Описание значений % смотрите в request-key.conf(5).

Теперь запускаем программу и проверяем содержимое /proc/keys, чтобы удостовериться, что запрашиваемый ключ создан:

```
$ ./t_request_key user mtk:key1 "Payload data"
$ grep '2dddaf50' /proc/keys
2dddaf50 I--Q---  1 perm 3f010000  1000  1000 user  mtk:key1: 12
```

Другой пример смотрите использования этой программы смотрите в keyctl(2).

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

```
/* t_request_key.c */
#include <sys/types.h>
#include <keyutils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{

    key_serial_t key;

    if (argc != 4) {

        fprintf(stderr, "Использование: %s тип описание callout-data\n",

                argv[0]);

        exit(EXIT_FAILURE);

    }

    key = request_key(argv[1], argv[2], argv[3],

                      KEY_SPEC_SESSION_KEYRING);

    if (key == -1) {

        perror("request_key");

        exit(EXIT_FAILURE);

    }

    printf("ID ключа = %lx\n", (long) key);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
keyctl(1), add_key(2), keyctl(2), keyctl(3), capabilities(7), keyrings(7), keyutils(7), persistent-keyring(7), process-keyring(7), session-keyring(7), thread-keyring(7), user-keyring(7), user-session-keyring(7), request-key(8)

Файлы исходного кода ядра Documentation/security/keys/core.rst и Documentation/keys/request-key.rst (или, до Linux 4.13, файлы Documentation/security/keys.txt и Documentation/security/keys-request-key.txt).


title: restart_syscall(2)

text:
# restart_syscall(2)

## ИМЯ
restart_syscall - перезапускает системный вызов после прерывания сигналом останова

## ОБЗОР
int restart_syscall(void);

Замечание: В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.

## ОПИСАНИЕ
Системный вызов restart_syscall() предназначен для перезапуска некоторых системных вызовов после того, как процесс, остановленный сигналом (например, SIGSTOP или SIGTSTP), продолжил выполнение после получения сигнала SIGCONT. Этот системный вызов создан только для внутреннего использования ядром.

Вызов restart_syscall() используется только для тех системных вызовов, которые при перезапуске должны обновить свои параметры, относящиеся к времени, а именно — poll(2) (начиная с Linux 2.6.24), nanosleep(2) (начиная с Linux 2.6), clock_nanosleep(2) (начиная с Linux 2.6), futex(2) при использовании с FUTEX_WAIT (начиная с Linux 2.6.22) и FUTEX_WAIT_BITSET (начиная с Linux 2.6.31). Вызов restart_syscall() перезапускает прерванный системный вызов с аргументом времени, который позволят рассчитать прошедшее время (включая время, когда процесс был остановлен сигналом). Без механизма restart_syscall() при перезапуске этих системных вызовов было бы невозможно вычесть правильное время, прошедшее на момент продолжения выполнение процесса.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Возвращаемым значением restart_syscall() является возвращаемое значение перезапущенного системного вызова.

## ОШИБКИ
Значение errno устанавливается в соответствии с ошибками системного вызова, перезапущенного restart_systemcall().

## ВЕРСИИ
Системный вызов restart_systemcall() появился в Linux 2.6.

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

## ЗАМЕЧАНИЯ
Для этого системного вызова в glibc нет обёрточной функции, потому что он используется только ядром и не должен вызываться приложениями.

Ядро использует restart_syscall() для гарантии того, что когда системный вызов перезапускается после остановки процесса по сигналу и затем возобновляется по SIGCONT, время, которое процесс пробыл в остановленном состоянии будет учтено в интервале ожидания, заданного в первоначальном системном вызове. У системных вызовов, у которых есть аргумент интервала ожидания и которые автоматически перезапускаются после сигнала останова плюс SIGCONT, но которые не имеют встроенного механизма restart_syscall(2), после возобновления работы процесса время, которое процесс пробыл в остановленном состоянии, не учитывается в значении интервала ожидания. Весомыми примерам системных вызовов, которые подвержены этой проблеме, являются ppoll(2), select(2) и pselect(2).

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

## СМОТРИТЕ ТАКЖЕ
sigaction(2), sigreturn(2), signal(7)


rmdir

title: rmdir(2)

summary: удалить каталог

text:
# rmdir(2)

## ИМЯ
rmdir - удалить каталог

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

int rmdir(const char *pathname);

## ОПИСАНИЕ
rmdir() удаляет каталог, который должен быть пуст.

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

## ОШИБКИ
EACCES

Нет прав на запись в каталог, содержащийся в pathname, или в одном из каталогов в pathname не разрешён поиск (см. также path_resolution(7)).

EBUSY

В данный момент pathname используется системой или одним из процессов, что предотвращает удаление. В Linux это означает, что pathname используется в качестве точки монтирования или является корневым каталогом вызвавшего процесса.

EFAULT

Аргумент pathname указывает за пределы доступного адресного пространства.

EINVAL

pathname содержит . в качестве последнего компонента.

ELOOP

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

ENAMETOOLONG

pathname слишком длинен.

ENOENT

Один из каталогов в pathname не существует или является повисшей символьной ссылкой.

ENOMEM

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

ENOTDIR

pathname, или его компонент, используемый в качестве каталога в pathname, фактически, не является каталогом.

ENOTEMPTY

pathname содержит элементы, отличные от . и .. ; или последним компонентом pathname является ... POSIX.1 также позволяет возвращать EEXIST в такой ситуации.

EPERM

На каталоге, содержащемся в pathname, установлен закрепляющий (sticky) бит (S_ISVTX) и эффективный идентификатор пользователя не совпадает с пользовательским ID файла или каталога, его содержащего, что требуется для удаления, и процесс не имеет прав (Linux: не имеет мандата CAP_FOWNER).

EPERM

Файловая система, содержащая pathname, не поддерживает удаление каталогов.

EROFS

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

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

## ДЕФЕКТЫ
Неточности в протоколе NFS могут приводить к неожиданному исчезновению каталогов, которые всё ещё используются.

## СМОТРИТЕ ТАКЖЕ
rm(1), rmdir(1), chdir(2), chmod(2), mkdir(2), rename(2), unlink(2), unlinkat(2)


title: rt_sigqueueinfo(2)

summary: ставит сигнал и данные в очередь

text:
# rt_sigqueueinfo(2)

## ИМЯ
rt_sigqueueinfo, rt_tgsigqueueinfo - ставит сигнал и данные в очередь

## ОБЗОР

```
int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info);
```

```
int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig,
                      siginfo_t *info);
```

Замечание: В glibc нет обёрточных функций для этих системных вызовов; смотрите ЗАМЕЧАНИЯ.

## ОПИСАНИЕ
Системные вызовы rt_sigqueueinfo() и rt_tgsigqueueinfo() предоставляют низкоуровневый интерфейс для отправки сигнала с данными процессу или нити. Приёмник сигнала может получить сопутствующие данные, установив обработчик сигнала с помощью sigaction(2) с флагом SA_SIGINFO.

Данные системные вызовы не предназначены для использования непосредственно из приложения; они нужны для реализации библиотечных функций sigqueue(3) и pthread_sigqueue(3).

Системный вызов rt_sigqueueinfo() отправляет сигнал sig группе нитей с идентификатором tgid (термин «группа нитей» является синонимом «процесс», а tid соответствует обычному идентификатору процесса UNIX). Сигнал будет доставлен произвольному члену группы нитей (т. е., одной из нитей, которая в этот момент не блокирует сигнал).

В аргументе info задаются сопутствующие сигналу данные. Этот аргумент является указателем на структуру типа siginfo_t, описанную в sigaction(2) (и определённую в <sigaction.h>). Вызывающий должен заполнить следующие поля структуры:

si_code

Значением должен быть один из кодов SI_*, перечисленных в файле исходного кода ядра Linux include/asm-generic/siginfo.h. посылается любому процессу, но не самому вызывающему, то накладываются следующие ограничения:

- Значение кода не может быть больше или равно нулю. В частности нельзя указывать SI_USER, используемый ядром для обозначения того, что сигнал послан kill(2), и нельзя указать SI_KERNEL, который используется для обозначения того, что сигнал сгенерирован ядром.

- Кодом не может быть (начиная с Linux 2.6.39) SI_TKILL, который используется ядром для обозначения того, что сигнал послан с помощью tgkill(2).

si_pid

Должно хранить идентификатор процесса, обычно PID отправителя.

si_uid

Должно хранить идентификатор пользователя, обычно UID реального пользователя отправителя.

si_value

Это поле хранит пользовательские данные, сопровождающие сигнал. Подробности смотрите в описании последнего аргумента (union sigval) функции sigqueue(3).

Внутри ядра полю si_signo устанавливается значение, переданное в sig, так что получатель сигнала может также получить его номер через это поле.

Системный вызов rt_tgsigqueueinfo() похож на rt_sigqueueinfo(), но посылает сигнал и данные одной нити, указываемой комбинацией tgid — идентификатором группы нитей — и tid — нити из этой группы.

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

## ОШИБКИ
EAGAIN

Достигнуто ограничение на количество сигналов в очереди (подробней об этом смотрите в signal(7)).

EINVAL

Некорректное значение sig, tgid или tid.

EPERM

Вызывающий не имеет прав для отправки сигнала по назначению. Требуемые права смотрите в kill(2).

EPERM

В tgid указан процесс, отличный от вызывающего и значение info->si_code некорректно.

ESRCH

rt_sigqueueinfo(): Группа нитей tgid не найдена.

rt_tgsigqueinfo(): Нить tid из tgid не найдена.

## ВЕРСИИ
Системный вызов rt_sigqueueinfo() был добавлен в Linux версии 2.2. Системный вызов rt_tgsigqueueinfo() был добавлен в Linux версии 2.6.31.

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

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

Как и в случае с kill(2), может быть использован сигнал null (0), чтобы проверить, существует ли указанный процесс или нить.

## СМОТРИТЕ ТАКЖЕ
kill(2), sigaction(2), sigprocmask(2), tgkill(2), pthread_sigqueue(3), sigqueue(3), signal(7)


title: s390_guarded_storage(2)

text:
# s390_guarded_storage(2)

## ИМЯ
s390_guarded_storage - операции со средством защищённого хранения z/Architecture

## ОБЗОР

```
#include <asm/guarded_storage.h>
```

```
int s390_guarded_storage(int command, struct gs_cb *gs_cb);
```

## ОПИСАНИЕ
Системный вызов s390_guarded_storage() задействует средство защищённого хранения (Guarded Storage Facility, свойство z/Architecture) для процессов пользовательского пространства.

Средство защищённого хранения — это аппаратное свойство, позволяющее пометить до 64 областей памяти (в z14) для защиты; при чтении указателя новыми инструкциями «Load Guarded» (LGG) или «Load Logical and Shift Guarded» (LLGFSG) будет проверяться диапазон согласно загружаемому значению и вызываться (установленный ранее) обработчик пользовательского пространства, если затронута одна из защищённых областей.

В аргументе command задаётся выполняемая функция. Поддерживаются следующие команды:

GS_ENABLE

Включает средство защищённого хранения для вызывающей задачи. Первоначально, содержимое блока управления защищённым хранением будет заполнено нулями. После включения из кода пользовательского пространства можно вызвать инструкцию «Load Guarded Storage Controls» (LGSC) (или обёрточную функцию load_gs_cb(), предоставляемую заголовочным файлом asm/guarded_storage.h) для загрузки произвольного блока управления. Пока задача включена, ядро будет сохранять и восстанавливать вызывающее содержимое регистров защищённого хранения при переключении контекста.

GS_DISABLE

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

GS_SET_BC_CB

Устанавливает широковещательный блок управления защищённым хранением равным из предоставленного в аргументе gs_cb. Вызывается для нити и связывает заданный широковещательный блок управления защищённым хранением с вызывающей задачей. Данный блок управления будет использован в команде широковещания GS_BROADCAST.

GS_CLEAR_BC_CB

Стирает широковещательный блок управления защищённым хранением. Блок управления защищённым хранением больше не имеет связи, установленной с помощью команды GS_SET_BC_CB.

GS_BROADCAST

Посылает широковещание всем нитям, родственным вызывающей задаче. Каждый родственник с установленным широковещательным блоком управления защищённым хранением загрузит этот блок управления и включит защищённое хранение. Широковещательный блок управления защищённым хранением уничтожается; второе широковещание без обновления хранимого блока управления с помощью GS_SET_BC_CB ни сработает.

В аргументе gs_cb указывается адрес структуры блока управления защищённым хранением и пока используется только в команде GS_SET_BC_CB; все остальные упомянутые команды игнорируют этот аргумент.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении s390_guarded_storage() возвращает значение 0.

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.

## ОШИБКИ
EFAULT

Значение command равно GS_SET_BC_CB и копирование структуры блока управления защищённым хранением, указанное в аргументе gs_cb завершилось ошибкой.

EINVAL

Значение аргумента command некорректно.

ENOMEM

Значение command равно GS_ENABLE или GS_SET_BC_CB и выделение места под новый блока управления защищённым хранением завершилось ошибкой.

EOPNOTSUPP

Средство защищённого хранения не поддерживается оборудованием.

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

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

Средство защищённого хранения доступно начиная с System z14.

## ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2).

Описание средства защищённого хранения вместе с инструкциями, блоком управления защищённым хранением, структурой списка событий защищённого хранения доступно в «z/Architecture Principles of Operations» начиная с 12-го выпуска.

В структуре gs_cb есть поле gsepla (Guarded Storage Event Parameter List Address), которое является указателем пользовательского пространства на структуру Guarded Storage Event Parameter List (содержащей адрес вышеупомянутого обработчика событий в поле gseha), а её описание доступно как определение структурного типа gs_epl в заголовочном файле asm/guarded_storage.h.

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


title: s390_pci_mmio_write(2)

summary: обмен данными со страницей памяти

text:
# s390_pci_mmio_write(2)

## ИМЯ
s390_pci_mmio_write, s390_pci_mmio_read - обмен данными со страницей памяти PCI MMIO

## ОБЗОР

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

```
int s390_pci_mmio_write(unsigned long mmio_addr,
                        void *user_buffer, size_t length);
int s390_pci_mmio_read(unsigned long mmio_addr,
                        void *user_buffer, size_t length);
```

## ОПИСАНИЕ
Системный вызов s390_pci_mmio_write() записывает length байт данных из буфера user_buffer пользовательского пространства в память PCI MMIO по адресу, указанному в mmio_addr. Системный вызов s390_pci_mmio_read() читает length байт данных начиная с адреса mmio_addr в памяти PCI MMIO и записывает их в буфер пользовательского пространства user_buffer.

Данные системные вызовы должны использоваться вместо простых операций назначения данных, используемых для доступа к областям памяти PCI MMIO, отображенным в пользовательское пространство на платформе Linux System z. Адрес, указываемый в mmio_addr, должен принадлежать отображению страницы памяти PCI MMIO в адресном пространстве вызывающего, а записываемые или читаемые данные не должны пересекать границу страницы. Значение length не может быть больше размера системной страницы.

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

## ОШИБКИ
EFAULT

Некорректный адрес в mmio_addr.

EFAULT

Адрес user_buffer не ссылается на корректную точку в адресном пространстве вызывающего.

EINVAL

Некорректное значение аргумента length.

ENODEV

Поддержка PCI выключена.

ENOMEM

Недостаточно памяти.

## ВЕРСИИ
Данные системные вызовы появились в Linux 3.19.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данный системный вызов есть только в Linux и доступен только на архитектуре s390. Требуемая поддержка PCI доступна начиная с System z EC12.

## ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2).

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


title: s390_runtime_instr(2)

text:
# s390_runtime_instr(2)

## ИМЯ
s390_runtime_instr - включает/выключает технические средства ЦП s390 времени выполнения

## ОБЗОР

```
#include <asm/runtime_instr.h>
```

```
int s390_runtime_instr(int command, int signum);
```

## ОПИСАНИЕ
Системный вызов s390_runtime_instr() запускает или останавливает технические средства ЦП времени выполнения для вызывающей нити.

В аргументе command указывается, что технические средства времени выполнения нужно запустить (S390_RUNTIME_INSTR_START, 1) или остановить (S390_RUNTIME_INSTR_STOP, 2) для вызывающей нити.

В аргументе signum задаётся номер сигнала реального времени. Сигнал реального времени посылается нити, если буфер технических средств времени выполнения заполнился или произошло прерывание run-time-instrumentation-halted.

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

## ОШИБКИ
EINVAL

Значение command не является допустимой командой, или значение signum не является номером сигнала реального времени.

ENOMEM

Не удалось выделить память под блок управления техническими средствами времени выполнения.

EOPNOTSUPP

Технические средства времени выполнения недоступны.

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

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данный системный вызов есть только в Linux и только на архитектуре s390. Технические средства времени выполнения доступны начиная с System z EC12.

## ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2).

Заголовочный файл asm/runtime_instr.h доступен в Linux начиная с версии 4.16.

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


title: s390_sthyi(2)

summary: эмулирует инструкцию STHYI

text:
# s390_sthyi(2)

## ИМЯ
s390_sthyi - эмулирует инструкцию STHYI

## ОБЗОР

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

```
int s390_sthyi(unsigned long function_code, void *resp_buffer,
               uint64_t *return_code, unsigned long flags);
```

## ОПИСАНИЕ
Системный вызов s390_sthyi() эмулирует инструкцию STHYI (Store Hypervisor Information). Он предоставляет информацию о ресурсах машины и её уровни виртуализации. В частности, возвращается тип ЦП и ёмкость, а также модель машины и другие свойства.

В аргументе function_code указывается какую функцию нужно выполнить. Поддерживаются следующие коды:

0

Вернуть информацию о CP (Central Processor) и ёмкости IFL (Integrated Facility for Linux).

В аргументе resp_buffer указывается адрес буфера результата. При function_code равном 0, размер буфера должен быть равен странице (4K). Если системный вызов вернул 0, то буфер результата будет заполнен информацией о ёмкости ЦП. В противном случае содержимое буфера результата не меняется.

В аргументе return_code хранится код возврата инструкции STHYI; возможно одно из следующих значений:

0

Успешно.

4

Неподдерживаемый код функции.

Дополнительную информацию о return_code, function_code и resp_buffer смотрите по ссылкам, приведённым в ЗАМЕЧАНИЯХ.

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

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении (т. е. эмуляция прошла успешно), возвращаемое s390_sthyi() значение совпадает с кодом условия инструкций STHYI — значением в диапазоне [0..3]. Возвращаемое значение 0 означает, что информация о ёмкости ЦП сохранена в *resp_buffer. Возвращаемое значение 3 указывает на «неподдерживаемый код функции» и содержимое *resp_buffer не изменяется. Значения 1 и 2 зарезервированы.

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.

## ОШИБКИ
EFAULT

Значение, указанное в resp_buffer или return_code, содержит некорректный адрес.

EINVAL

Значение, указанное в flags, не равно нулю.

ENOMEM

Не удалось выделить память для обработки информации о ёмкости ЦП.

EOPNOTSUPP

Некорректное значение в function_code.

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

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

## ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2).

Описание инструкции STHYI смотрите на странице документации.

При использовании интерфейса системного вызова буфер результата не имеет требований по выравниванию, описанных в инструкции STHYI.

Ядро кэширует результат (в Linux 4.16 каждую секунду). Последующие запуски системного вызова могут вернуть кэшированный ответ.

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