title: ioctl_tty(2)

text:
# ioctl_tty(2)

## ИМЯ
ioctl_tty - вызовы ioctl для терминалов и последовательных портов

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

int ioctl(int fd, int cmd, ...);

## ОПИСАНИЕ
Вызов ioctl(2) для терминалов и последовательных портов принимает много разных параметров команд. Большинство из них требуют при этом третий аргумент разных типов, далее по тексту называемый argp или arg.

Вызовы ioctl используются только в непереносимых программах. По возможности старайтесь везде использовать интерфейс POSIX, описанный в termios(3).

### Определение и установка атрибутов терминала
TCGETS struct termios *argp

Эквивалентно tcgetattr(fd, argp).

Получить текущие настройки последовательного порта.

TCSETS const struct termios *argp

Эквивалентно tcsetattr(fd, TCSANOW, argp).

Установить новые текущие настройки последовательного порта.

TCSETSW const struct termios *argp

Эквивалентно tcsetattr(fd, TCSADRAIN, argp).

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

TCSETSF const struct termios *argp

Эквивалентно tcsetattr(fd, TCSAFLUSH, argp).

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

Следующие четыре вызова ioctl аналогичны TCGETS, TCSETS, TCSETSW, TCSETSF, за исключением того, что они работают с struct termio *, а не с struct termios *.

TCGETA struct termio *argp

TCSETA const struct termio *argp

TCSETAW const struct termio *argp

TCSETAF const struct termio *argp

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

TIOCGLCKTRMIOS struct termios *argp

Получить состояние блокировки структуры termios терминала.

TIOCSLCKTRMIOS const struct termios *argp

Установить состояние блокировки структуры termios терминала. Это может делать только процесс с мандатом CAP_SYS_ADMIN.

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

Следующие константы и структура определены в <sys/ioctl.h>.

TIOCGWINSZ struct winsize *argp

Получить размер окна.

TIOCSWINSZ const struct winsize *argp

Установить размер окна.

Структура, используемая этими системными вызовами ioctl, определяется так:

```
struct winsize {

    unsigned short ws_row;

    unsigned short ws_col;

    unsigned short ws_xpixel;   /* не используется */

    unsigned short ws_ypixel;   /* не используется */
};
```

При изменении размера окна отправляется сигнал SIGWINCH группе активных (foreground) процессов.

### Отправка сигнала Break
TCSBRK int arg

Эквивалентно tcsendbreak(fd, arg).

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

(В SVr4, UnixWare, Solaris, Linux tcsendbreak(fd,arg) ненулевые значение arg воспринимается аналогично вызову tcdrain(fd). В SunOS arg воспринимается как множитель и отправляет поток битов в arg раз дольше, чем для нулевого значения arg. В DG/UX и AIX arg (если оно не равно нулю) воспринимается как временной интервал в миллисекундах. В HP-UX arg игнорируется.)

TCSBRKP int arg

Так называемая «POSIX-версия» TCSBRK. Она воспринимает ненулевые значения arg как временной интервал в децисекундах (1/10 секунды), и ничего не делает, если драйвер не поддерживает сигналы break.

TIOCSBRK void

Включить сигнал break, то есть начать отправку нулевых битов.

TIOCCBRK void

Выключить сигнал break, то есть прекратить отправку нулевых битов.

### Программное управление потоком
TCXONC int arg

Эквивалентно tcflow(fd, arg).

Смотрите tcflow(3) со значениями аргументов TCOOFF, TCOON, TCIOFF, TCION.

### Счетчик буфера и очистка
FIONREAD int *argp

Получить количество байтов в буфере ввода.

TIOCINQ int *argp

То же что и FIONREAD.

TIOCOUTQ int *argp

Получить количество байтов в буфере вывода.

TCFLSH int arg

Эквивалентно tcflush(fd, arg).

Смотрите tcflush(3) со значениями аргументов TCIFLUSH, TCOFLUSH, TCIOFLUSH.

### Мнимый ввод
TIOCSTI const char *argp

Вставить заданный байт в очередь ввода.

### Перенаправление вывода консоли
TIOCCONS void

Перенаправляет вывод, который должен идти на /dev/console или /dev/tty0, на указанный терминал. Если это был основной псевдо-терминал, то вывод отправляется на подчинённый. В Linux до версии 2.6.10 кто угодно мог делать это, пока вывод не был ещё ни разу перенаправлен; начиная с версии 2.6.10 только процесс с мандатом CAP_SYS_ADMIN может делать это. Если вывод уже был перенаправлен, то будет выдана ошибка EBUSY, но перенаправление можно остановить с помощью этого вызова ioctl с fd, указывающим на /dev/console или /dev/tty0.

### Управляющий терминал
TIOCSCTTY int arg

Сделать заданный терминал управляющим для вызывающего процесса. Вызывающий процесс должен быть лидером сеанса и не иметь управляющего терминала. Для этого случая значение arg должно быть равно 0.

Если этот терминал уже является управляющим для другой группы сеансов, то ioctl завершается с ошибкой EPERM, если только вызывающий не имеет мандата CAP_SYS_ADMIN и arg не равно 1 — в этом случае терминал отбирается и все процессы, где он был управляющим, теряют его.

TIOCNOTTY void

Если заданный терминал является управляющим для вызывающего процесса, то выполняется отключение этого управляющего терминала. Если процесс был лидером сеанса, то активной группе процессов посылаются сигналы SIGHUP и SIGCONT, и все процессы в этом сеансе теряют управляющий терминал.

### Группа процессов и идентификатор сеанса
TIOCGPGRP pid_t *argp

При успешном выполнении эквивалентно *argp = tcgetpgrp(fd).

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

TIOCSPGRP const pid_t *argp

Эквивалентно tcsetpgrp(fd, *argp).

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

TIOCGSID pid_t *argp

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

### Закрытый (Exclusive) режим
TIOCEXCL void

Перевести терминал в закрытый режим. Дальнейшие операции open(2) с терминалом запрещены (выдают ошибку EBUSY, если процесс не имеет мандата CAP_SYS_ADMIN).

TIOCGEXCL int *argp

(начиная с Linux 3.8) Если терминал находится в закрытом режиме, поместить ненулевое значение в расположение, указанное argp; в противном случае, поместить ноль в *argp.

TIOCNXCL void

Отменить закрытый режим.

### Параметры линии
TIOCGETD int *argp

Получить параметры линии для терминала.

TIOCSETD const int *argp

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

### Вызовы ioctl для псевдо-терминала
TIOCPKT const int *argp

Включить (если *argp не равно нулю) или отключить пакетный режим. Может применяться только к основному псевдо-терминалу (иначе будет возвращено ENOTTY). В пакетном режиме каждый последующий read(2) возвращает пакет, содержащий либо один ненулевой управляющий байт, либо один нулевой байт (' ') с последующими данными, записанными на подчинённом псевдо-терминале. Если первый байт не равен TIOCPKT_DATA (0), то он логически складывается с одним или несколькими следующими битами:

```
TIOCPKT_FLUSHREAD   Очередь чтения терминала очищается.
TIOCPKT_FLUSHWRITE  Очередь записи терминала очищается.
TIOCPKT_STOP        Вывод на терминал останавливается.
TIOCPKT_START       Вывод на терминал перезапускается.
TIOCPKT_DOSTOP      Символами запуска/останова являются ^S/^Q.
TIOCPKT_NOSTOP      Символами запуска/останова не являются ^S/^Q.
```

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

Этот режим используется rlogin(1) и rlogind(8) для реализации удалённого эха с локально управляемым потоком с помощью ^S/^Q для удалённого входа.

TIOCGPKT const int *argp

(начиная с Linux 3.8) Вернуть текущую настройку пакетного режима в виде целого в память, на которую указывает argp.

TIOCSPTLCK int *argp

Назначить (если *argp не равно нулю nonzero) или удалить (если *argp равно нулю) устройство подчинённого псевдо-терминала (также смотрите unlockpt(3)).

TIOCGPTLCK int *argp

(начиная с Linux 3.8) Поместить текущее состояние блокировки устройства подчинённого псевдо-терминала в расположение, на которое указывает argp.

TIOCGPTPEER int flags

(начиная с Linux 4.13) Открыть (флаги flags как у open(2)) переданный в fd файловый дескриптор, который ссылается на основной псевдо-терминал, и вернуть новый файловый дескриптор, который ссылается на ответное устройство подчинённого псевдо-терминала. Данная операция может выполняться независимо от доступности имени подчинённого устройства в пространстве монтирования вызывающего процесса.

Безопасным приложениям, работающим с пространствами имён, лучше использовать эту операцию вместо open(2) с путём, возвращаемым ptsname(3) и подобных библиотечных функций, имеющих небезопасные программные интерфейсы (например, в некоторых случаях может получиться путаница при использовании ptsname(3) с путём, если файловая система devpts была смонтирована в другое пространство имён).

Вызовы ioctl для BSD — TIOCSTOP, TIOCSTART, TIOCUCNTL, TIOCREMOTE — не реализованы в Linux.

### Управление модемом
TIOCMGET int *argp

Получить состояние битов модема.

TIOCMSET const int *argp

Установить состояние битов модема.

TIOCMBIC const int *argp

Очистить указанные биты модема.

TIOCMBIS const int *argp

Установить указанные биты модема.

Приведёнными выше ioctl используются следующие биты:

```
TIOCM_LE        DSR (источник данных готов/линия включена)
TIOCM_DTR       DTR (сигнал готовности терминала)
TIOCM_RTS       RTS (запрос на передачу)
TIOCM_ST        Вторичный TXD (передача)
TIOCM_SR        Вторичный RXD (приём)
TIOCM_CTS       CTS (разрешение на передачу)
TIOCM_CAR       DCD (обнаружен информационный сигнал)
TIOCM_CD         см. TIOCM_CAR
TIOCM_RNG       RNG (звонок)
TIOCM_RI         см. TIOCM_RNG
TIOCM_DSR       DSR (источник данных готов)
```

TIOCMIWAIT int arg

Ждать изменения любого из 4 битов модема (DCD, RI, DSR, CTS). Интересующие биты указываются в arg в виде битовой маски с помощью операции OR значений TIOCM_RNG, TIOCM_DSR, TIOCM_CD и TIOCM_CTS. Чтобы понять какие биты изменились вызывающий должен использовать TIOCGICOUNT.

TIOCGICOUNT struct serial_icounter_struct *argp

Получить счётчики входных прерываний последовательной линии (DCD, RI, DSR, CTS). Счётчики записываются в структуру serial_icounter_struct, на которую указывает argp.

Замечание: считаются переходы 1->0 и 0->1, за исключением RI, где учитывается только переход 0->1.

### Маркировка линии как локальной
TIOCGSOFTCAR int *argp

(«получение флага программной несущей») Получить состояние флага CLOCAL в поле c_cflag структуры termios.

TIOCSSOFTCAR const int *argp

(«установка флага программной несущей») Установить флаг CLOCAL в поле c_cflag структуры termios при *argp не равном нулю или очистить его в противном случае.

Если флаг CLOCAL для линии не установлен, то учитывается сигнал DCD, а вызов open(2) для соответствующего терминала будет блокирован, пока не появится сигнал DCD ( если не установлен флаг O_NONBLOCK). Если флаг CLOCAL установлен, то линия ведёт себя так, как если DCD установлен всегда. Программное задание несущего сигнала обычно включено для локальных устройств и выключено для модемных линий.

### Вызовы, определённые только в Linux
Описание вызова ioctl TIOCLINUX смотрите в ioctl_console(2).

### Отладка ядра
\#include <linux/tty.h>

TIOCTTYGSTRUCT struct tty_struct *argp

Получить структуру tty_struct, соответствующую fd. Эта команда удалена в Linux 2.5.67.

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

## ОШИБКИ
EINVAL

Неизвестный параметр команды.

ENOIOCTLCMD

Неизвестная команда.

ENOTTY

Неподходящий fd.

EPERM

Недостаточно прав.

## ПРИМЕР
Проверка состояния DTR на последовательном порту.

```
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int
main(void)
{

    int fd, serial;

    fd = open("/dev/ttyS0", O_RDONLY);

    ioctl(fd, TIOCMGET, &serial);

    if (serial & TIOCM_DTR)

        puts("TIOCM_DTR установлен");

    else

        puts("TIOCM_DTR не установлен");

    close(fd);
}
```

## СМОТРИТЕ ТАКЖЕ
ldattach(1), ioctl(2), ioctl_console(2), termios(3), pty(7)


package: man-pages-ru

title: ioctl_userfaultfd(2)

text:
# ioctl_userfaultfd(2)

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

## ОБЗОР

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

```
int ioctl(int fd, int cmd, ...);
```

## ОПИСАНИЕ
Над объектом userfaultfd (созданным вызовом userfaultfd(2)) можно выполнять различные операции ioctl(2) используя вызовы вида:

```
ioctl(fd, cmd, argp);
```

Здесь fd — файловый дескриптор, ссылающийся на объект userfaultfd, cmd — одна из команд, перечисленных ниже, а argp — указатель на структуру данных, используемую командой cmd. Операции ioctl(2) описаны ниже. Операции UFFDIO_API, UFFDIO_REGISTER и UFFDIO_UNREGISTER используются для настройки поведения userfaultfd. Они позволяют вызывающему выбрать какие свойства нужно включить и какие типы событий будут доставляться приложению. Остальные операции являются операциями над диапазоном. Эти операции позволяют вызывающему приложению воспринимать события страничных ошибок.

### UFFDIO_API
(начиная с Linux 4.3) Включить работу с userfaultfd и выполнить согласование программного интерфейса.

В аргументе argp содержится указатель на структуру uffdio_api, определённую следующим образом:

```
struct uffdio_api {

    __u64 api;        /* запрашиваемая версия API (входные данные) */

    __u64 features;   /* запрашиваемые свойства (входные/выходные) */

    __u64 ioctls;     /* доступные операции ioctl() (выходные данные) */
};
```

В поле api задаётся версия программного интерфейса, запрашиваемого приложением.

Ядро проверяет, что поддерживает запрашиваемую версию программного интерфейса и изменять поля features и ioctls в битовой маске, представляющей все доступные свойства и общие операции ioctl(2).

В ядрах Linux до версии 4.11 полю features должен быть присвоен ноль перед вызовом UFFDIO_API, и при возврате из ioctl(2) ядро помещает ноль (т. е., нет бит свойств) в поле features.

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

Чтобы включить свойство userfaultfd приложение должно установить соответствующий бит в поле features. Если ядро поддерживает все запрошенные свойств, то он включит их. В противном случае оно обнулит возвращаемую структуру uffdio_api и вернёт EINVAL.

Могут устанавливаться следующие биты свойств:

UFFD_FEATURE_EVENT_FORK (начиная с Linux 4.11)

Если это свойство включено, то объекты userfaultfd, связанные с родительским процессом, дублируются в дочернем процессе при вызове fork(2), а событие UFFD_EVENT_FORK доставляется отслеживающему userfaultfd.

UFFD_FEATURE_EVENT_REMAP (начиная с Linux 4.11)

Если это свойство включено, то при вызове mremap(2) процессом с ошибкой отслеживающий userfaultfd будет получать событие с типом UFFD_EVENT_REMAP.

UFFD_FEATURE_EVENT_REMOVE (начиная с Linux 4.11)

Если это свойство включено, то при вызове madvise(2)со значением совета MADV_DONTNEED или MADV_REMOVE для освобождения области виртуальной памяти процессом с ошибкой отслеживающий userfaultfd будет получать событие с типом UFFD_EVENT_REMOVE.

UFFD_FEATURE_EVENT_UNMAP (начиная с Linux 4.11)

Если это свойство включено, то при явном вызове mremap(2) или неявном вызове mmap(2) или mremap(2) процессом с ошибкой отслеживающий userfaultfd будет получать событие с типом UFFD_EVENT_UNMAP.

UFFD_FEATURE_MISSING_HUGETLBFS (начиная с Linux 4.11)

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

UFFD_FEATURE_MISSING_SHMEM (начиная с Linux 4.11)

Если этот бит установлен, то ядро включает поддержку регистрации диапазонов userfaultfd для общих областей виртуальной памяти. К ним относятся все программные интерфейсы общей памяти ядра: общая память System V, tmpfs(5), общие отображения /dev/zero, mmap(2) с флагом MAP_SHARED, memfd_create(2) и т. д.

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

Если этот бит установлен, то события о страничных ошибках (UFFD_EVENT_PAGEFAULT) не доставляются. Вместо них в ошибшийся процесс будет послан сигнал SIGBUS. Приложениям, использующим этой свойство, не потребуется использовать слежение за userfaultfd для обработки доступа к областям памяти, зарегистрированным в userfaultfd.

Возвращаемое поле ioctls можно содержать следующие биты:

1 << _UFFDIO_API

Поддерживается операция UFFDIO_API.

1 << _UFFDIO_REGISTER

Поддерживается операция UFFDIO_REGISTER.

1 << _UFFDIO_UNREGISTER

Поддерживается операция UFFDIO_UNREGISTER.

При успешном выполнении операции ioctl(2) возвращается 0. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EFAULT

Значение argp ссылается на адрес, который находится вне доступного адресного пространства вызывающего процесса.

EINVAL

Дескриптор userfaultfd уже включён предыдущей операцией UFFDIO_API.

EINVAL

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

### UFFDIO_REGISTER
(начиная с Linux 4.3) Зарегистрировать диапазон адресов памяти в объекте userfaultfd. Страницы в диапазоне должны быть «совместимыми».

До ядра Linux 4.11 только частные анонимные диапазоны совместимы для регистрации с помощью UFFDIO_REGISTER.

Начиная с Linux 4.11 общие диапазоны памяти и hugetlbfs также совместимы с UFFDIO_REGISTER.

В аргументе argp содержится указатель на структуру uffdio_register, определённую следующим образом:

```
struct uffdio_range {

    __u64 start;    /* начало диапазона */

    __u64 len;      /* длина диапазона (в байтах) */
};
struct uffdio_register {

    struct uffdio_range range;

    __u64 mode;     /* желаемый режим операции (входные данные) */

    __u64 ioctls;   /* доступные операции ioctl() (результат) */
};
```

В поле range задаётся диапазон памяти (начинающийся с start и длиной len байт), который должен обрабатываться userfaultfd.

В поле mode задаётся режим операции на этим диапазоном памяти. У режима userfaultfd могут быть указаны следующие значения (через операцию ИЛИ) для задаваемого диапазона:

UFFDIO_REGISTER_MODE_MISSING

Отслеживать страничные ошибки отсутствия страниц.

UFFDIO_REGISTER_MODE_WP

Отслеживать страничные ошибки защищённых от записи страниц.

В настоящее время поддерживается только режим UFFDIO_REGISTER_MODE_MISSING.

При успешном выполнении ядро изменяет битовую маску ioctls показывая какие операции ioctl(2) доступны для задаваемого диапазона. Здесь возвращается битовая маска как для UFFDIO_API.

При успешном выполнении операции ioctl(2) возвращается 0. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EBUSY

Отображение в указанном диапазоне зарегистрировано в другом объекте userfaultfd.

EFAULT

Значение argp ссылается на адрес, который находится вне доступного адресного пространства вызывающего процесса.

EINVAL

В поле mode указан некорректный или неподдерживаемый бит или поле mode равно нулю.

EINVAL

Отображение в указанном адресном диапазоне отсутствует.

EINVAL

Значение range.start или range.len не кратно размеру системной страницы или значение range.len равно или эти поля содержат другие некорректные значения.

EINVAL

В указанном адресном диапазоне имеется несовместимое отображение.

### UFFDIO_UNREGISTER
(начиная с Linux 4.3) Снять регистрацию диапазона адресов памяти в userfaultfd. Страницы в диапазоне должны быть «совместимыми» (смотрите описание UFFDIO_REGISTER).

Снимаемый с регистрации диапазон адресов задаётся в структуре uffdio_range, которая указывается в argp.

При успешном выполнении операции ioctl(2) возвращается 0. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EINVAL

Поле start или len структуры ufdio_range не кратно размеру системной страницы или поле len равно нулю или эти поля содержат другие некорректные значения.

EINVAL

В указанном адресном диапазоне имеется несовместимое отображение.

EINVAL

Отображение в указанном адресном диапазоне отсутствует.

### UFFDIO_COPY
(начиная с Linux 4.3) Атомарно копировать непрерывный участок памяти в зарегистрированный в userfault диапазон и разбудить заблокированную нить (не обязательно). Адреса источника и назначения и количество копируемых байт задаётся в полях src, dst и len структуры uffdio_copy, на которую указывает argp:

```
struct uffdio_copy {

    __u64 dst;    /* источник копирования */

    __u64 src;    /* назначение копирования */

    __u64 len;    /* количество копируемых байт */

    __u64 mode;   /* флаги, управляющие поведением копирования */

    __s64 copy;   /* количество скопированных байт или отрицательная ошибка */
};
```

Для изменения поведения операции UFFDIO_COPY можно использовать следующие значения mode (побитовое ИЛИ):

UFFDIO_COPY_MODE_DONTWAKE

Не будить нить, которая ждёт решения страничной ошибки

Поле copy используется ядром для возврата количества байт, которые были скопированы, или ошибки (отрицательное значение, подобное errno). Если значение, возвращённое в copy, не совпадает со значением, указанным в len, то операция завершается ошибкой EAGAIN. Поле copy используется только для результата; оно не читается операцией UFFDIO_COPY.

При успешном выполнении операции ioctl(2) возвращается 0. В этом случае была скопирована область целиком. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EAGAIN

Количество скопированных байт (т. е., значение, возвращаемое в поле copy) не равно значению, указанному в поле len.

EINVAL

Значение dst или len не кратно размеру системной страницы или диапазон, заданный в src и len или dst и len является неправильным.

EINVAL

В поле mode установлен недопустимый бит.

ENOENT (начиная с Linux 4.11)

Процесс с ошибкой изменил раскладку своей виртуальной памяти одновременно имея незавершённую операцию UFFDIO_COPY.

ENOSPC (в Linux 4.11 по Linux 4.13)

Процесс с ошибкой завершил работу в момент выполнения операции UFFDIO_COPY.

ESRCH (начиная с Linux 4.13)

Процесс с ошибкой завершил работу в момент выполнения операции UFFDIO_COPY.

### UFFDIO_ZEROPAGE
(начиная с Linux 4.3) Обнулить диапазон памяти, зарегистрированный в userfaultfd.

Запрашиваемый диапазон указывается в поле range структуры uffdio_zeropage, на которую указывает argp:

```
struct uffdio_zeropage {

    struct uffdio_range range;

    __u64 mode;     /* флаги, определяющие поведение копирования */

    __s64 zeropage; /* количество обнуляемых байт или отрицательная ошибка */
};
```

Для изменения поведения операции UFFDIO_ZEROPAGE можно использовать следующие значения mode (побитовое ИЛИ):

UFFDIO_ZEROPAGE_MODE_DONTWAKE

Не будить нить, которая ждёт решения страничной ошибки.

Поле zeropage используется ядром для возврата количества байт, которые были обнулены, или ошибки (также, как для UFFDIO_COPY). Если значение, возвращённое в zeropage, не совпадает со значением, указанным в range.len, то операция завершается ошибкой EAGAIN. Поле zeropage используется только для результата; оно не читается операцией UFFDIO_ZEROPAGE.

При успешном выполнении операции ioctl(2) возвращается 0. В этом случае была обнулена вся область. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EAGAIN

Количество обнулённых байт (т. е., значение, возвращаемое в поле zeropage) не равно значению, указанному в поле range.len.

EINVAL

Значение range.start или range.len не кратно размеру системной страницы, значение range.len равно нулю, указанный диапазон является неправильным.

EINVAL

В поле mode установлен недопустимый бит.

ESRCH (начиная с Linux 4.13)

Процесс с ошибкой завершил работу в момент выполнения операции UFFDIO_ZEROPAGE.

### UFFDIO_WAKE
(начиная с Linux 4.3) Разбудить нить, которая ждёт решения страничной ошибки в указанном диапазоне адресов памяти.

Операция UFFDIO_WAKE используется вместе с UFFDIO_COPY и UFFDIO_ZEROPAGE, у которых установлен бит UFFDIO_COPY_MODE_DONTWAKE или UFFDIO_ZEROPAGE_MODE_DONTWAKE в поле mode. При отслеживании userfault можно выполнять несколько операций UFFDIO_COPY и UFFDIO_ZEROPAGE вместе и затем явно будить нить с ошибкой с помощью UFFDIO_WAKE.

В аргументе argp содержится указатель на структуру uffdio_range (показана выше), в которой задаётся диапазон адресов.

При успешном выполнении операции ioctl(2) возвращается 0. При ошибке возвращается -1 и в errno записывается причина ошибки. Возможные значения:

EINVAL

Поле start или len структуры ufdio_range не кратно размеру системной страницы или поле len равно нулю или указанный диапазон является неправильным.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Смотрите описание приведённое выше для каждой операции.

## ОШИБКИ
Смотрите описание приведённое выше для каждой операции. Также для всех описанных выше операций могут возникать общие ошибки:

EFAULT

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

EINVAL

(для все операций кроме UFFDIO_API) Объект userfaultfd пока не включён (с помощью операции UFFDIO_API).

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные операции ioctl(2) есть только в Linux.

## ДЕФЕКТЫ
Чтобы определить доступные свойства userfault и включить некоторые из них нужно закрыть файловый дескриптор userfaultfd после первой операции UFFDIO_API, которая запрашивает доступность свойств, и повторно открыть его перед второй операцией UFFDIO_API, которая теперь включит желаемый свойства.

## ПРИМЕР
Смотрите userfaultfd(2).

## СМОТРИТЕ ТАКЖЕ
ioctl(2), mmap(2), userfaultfd(2)

Файл Documentation/admin-guide/mm/userfaultfd.rst из дерева исходного кода ядра Linux

branch: sisyphus


ioperm

title: ioperm(2)

text:
# ioperm(2)

## ИМЯ
ioperm - устанавливает права на работу с портами ввода/вывода

## ОБЗОР
\#include <sys/io.h> /* для glibc */

int ioperm(unsigned long from, unsigned long num, int turn_on);

## ОПИСАНИЕ
Вызов ioperm() устанавливает num бит прав доступа вызывающей нити, начиная с адреса порта from. Если turn_on не равно 0, то права для указанных битов устанавливаются, иначе сбрасываются. Если turn_on не равно 0, вызывающая нить должна быть привилегированной (CAP_SYS_RAWIO).

До Linux 2.6.8, можно было указывать только первые 0x3ff портов ввода-вывода. Для остальных портов нужно было использовать системный вызов iopl(2) (с аргументом level равным 3). Начиная с Linux 2.6.8, можно указывать 65536 портов ввода-вывода.

Права наследуются дочерним процессом, созданным fork(2) (но смотрите ЗАМЕЧАНИЯ). Права сохраняются при вызове execve(2); это полезно для предоставления доступа к портам ввода-вывода непривилегированным программам.

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

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

## ОШИБКИ
EINVAL

Неверные значения from или num.

EIO

(на PowerPC) Этот системный вызов не поддерживается.

ENOMEM

Не хватает памяти.

EPERM

Вызывающая нить не имеет достаточно прав.

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

## ЗАМЕЧАНИЯ
В /proc/ioports показываются все порты ввода-вывода, которые выделены в системе в настоящий момент.

До Linux 2.4 права не наследовались потомком, созданным fork(2).

В glibc прототип ioperm() расположен в <sys/io.h> и <sys/perm.h>. Не используйте последний вариант, он существует только для i386.

## СМОТРИТЕ ТАКЖЕ
iopl(2), outb(2), capabilities(7)


iopl

title: iopl(2)

summary: меняет уровень привилегий ввода\-вывода

text:
# iopl(2)

## ИМЯ
iopl - меняет уровень привилегий ввода-вывода

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

int iopl(int level);

## ОПИСАНИЕ
iopl() изменяет уровень привилегий ввода/вывода вызывающего процесса, задаваемый двумя младшими битами в значении level.

Этот вызов необходим для того, чтобы 8514-совместимые X-серверы могли работать под управлением Linux. Этим X-серверам необходим доступ ко всем 65536-и портам ввода/вывода, вызова ioperm(2) для этого недостаточно.

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

Права не наследуются дочерним процессом, созданным fork(2) и не сохраняются при вызове execve(2) (но смотрите ЗАМЕЧАНИЯ).

Уровень привилегий ввода/вывода обычного процесса равен 0.

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

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

## ОШИБКИ
EINVAL

Значение level больше 3.

ENOSYS

Этот вызов не реализован.

EPERM

У вызывающего процесса недостаточно прав вызвать iopl(); для повышения уровня привилегий ввода-вывода выше текущего значения требуется мандат CAP_SYS_RAWIO.

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

## ЗАМЕЧАНИЯ
В glibc2 прототип расположен в <sys/io.h> и <sys/perm.h>. Не используйте последний вариант, он существует только для i386.

До Linux 3.7 на некоторых архитектурах (например, i386), права наследовались потомком, созданным fork(2), и сохранялись при execve(2). Такое поведение было неумышленно изменено в Linux 3.7, и не будет возвращено назад.

## СМОТРИТЕ ТАКЖЕ
ioperm(2), outb(2), capabilities(7)


title: ioprio_set(2)

text:
# ioprio_set(2)

## ИМЯ
ioprio_get, ioprio_set - получает/устанавливает класс и приоритет планирования ввода-вывода

## ОБЗОР

```
int ioprio_get(int which, int who);
int ioprio_set(int which, int who, int ioprio);
```

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

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

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

IOPRIO_WHO_PROCESS

Значением who является идентификатор процесса или нити, определяющий один процесс или нить. Если who равно 0, то операции выполняются над вызвавшей нитью.

IOPRIO_WHO_PGRP

Значением who является идентификатор группы, определяющий всех членов группы процесса. Если who равно 0, то операции выполняются над группой процессов, членом которой является вызвавший.

IOPRIO_WHO_USER

Значением who является идентификатор пользователя, определяющий все процессы, которые имеют этот реальный идентификатор.

Если при вызове ioprio_get() в which указано IOPRIO_WHO_PGRP или IOPRIO_WHO_USER, и под шаблон who подходит более одного процесса, то возвращаемый приоритет будет равен самому высокому значению среди процессов этой группы. Считается, что один приоритет больше другого, если он принадлежит более высокому классу процессов (IOPRIO_CLASS_RT является самым высоким классом приоритетов; IOPRIO_CLASS_IDLE — самым низким), или если оба процесса принадлежат одному классу, то тогда самым высоким будет приоритет с большим уровнем (меньший номер приоритета, означает более высокий уровень).

Аргумент ioprio, задаваемый в ioprio_set(), является битовой маской, в которой указываются класс планирования и приоритет, назначаемый заданному процессу(ам). Для компоновки и разделения значений ioprio используются следующие макросы:

IOPRIO_PRIO_VALUE(class, data)

Объединяет заданный класс планирования class и приоритет (data) в значение ioprio, которое возвращается как результат макроса.

IOPRIO_PRIO_CLASS(mask)

Из указанной маски mask (значение ioprio) возвращает значение класса ввода-вывода, то есть одно из значений: IOPRIO_CLASS_RT, IOPRIO_CLASS_BE или IOPRIO_CLASS_IDLE.

IOPRIO_PRIO_DATA(mask)

Из указанной маски mask (значение ioprio) возвращает значение приоритета (data).

Подробней о классах планирования и приоритетах, а также о значении 0 в ioprio смотрите в разделе ЗАМЕЧАНИЯ.

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

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

При успешном выполнении ioprio_set() возвращается 0. При ошибке возвращается -1, а в errno содержится код ошибки.

## ОШИБКИ
EINVAL

Неправильное значение which или ioprio. Обратитесь к разделу ЗАМЕЧАНИЯ, в нём приведены доступные классы планировщика и уровни приоритета ioprio.

EPERM

У вызывающего процесса нет прав, необходимых для назначения данного ioprio указанному процессу(ам). Более подробную информацию о необходимых правах ioprio_set() можно найти в разделе ЗАМЕЧАНИЯ.

ESRCH

Не найдено процессов, которые бы соответствовали заданным в which и who критериям.

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

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

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

Два или более процесса или нити могут использовать общий контекст ввода-вывода. Это может происходить в случае, если вызывается clone(2) с флагом CLONE_IO. Однако по умолчанию разные нити процесса не будут использовать общий контекст ввода-вывода. Это означает, что если вы хотите изменить приоритет ввода-вывода всех нитей процесса, то вам может потребоваться вызвать ioprio_set() для каждой нити. Идентификатор нити, требуемый для этой операции, можно получить с помощью gettid(2) или clone(2).

Данные системные вызовы действительно работают только, если используется планировщик ввода-вывода, поддерживающий приоритеты ввода-вывода. В ядре 2.6.17 такой планировщик только один: Completely Fair Queuing (CFQ).

Если для нити не был задан планировщик ввода-вывода, то значением приоритета ввода-вывода будет значение уступчивости ЦП (setpriority(2)). В ядрах Linux до версии 2.6.24 после назначения приоритета ввода-вывода с помощью ioprio_set() нет способа переустановить поведение планировщика ввода-вывода в значение по умолчанию. Начиная с Linux 2.6.24 для установки поведения планировщика ввода-вывода в значение по умолчанию можно указать ioprio значение 0.

### Выбор планировщика ввода-вывода
Планировщики ввода-вывода устанавливаются в каждом устройстве через специальный файл /sys/block/<устройство>/queue/scheduler.

Используемый в данный момент планировщик ввода-вывода можно посмотреть через файловую систему /sys. Например, следующая команда покажет список всех планировщиков, загруженных в ядро:

```
$ cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
```

Планировщик, работающий на устройстве (в примере sda), указан в скобках. Замена планировщика выполняется с помощью записи имени нового планировщика в этот файл. Например, следующая команда установит планировщик cfq для устройства sda:

```
$ su
Password:
# echo cfq > /sys/block/sda/queue/scheduler
```

### Планировщик ввода-вывода с полностью справедливой очерёдностью (CFQ)
Начиная с версии 3 (т. н. CFQ Time Sliced) в CFQ реализованы уровни уступчивости ввода-вывода, подобно используемым в планировщике ЦП. Эти уровни уступчивости сгруппированы в три класса планирования, в каждом содержится один и более уровней приоритета:

IOPRIO_CLASS_RT (1)

Класс ввода-вывода реального времени. Данному классу планирования назначен самый высокий приоритет по сравнению с другими: процессам с этим классом всегда предоставляется первоочередной доступ к диску. Поэтому данный класс следует использовать с осторожностью: одним процессом ввода-вывода реального времени можно затормозить все остальные. В классе реального времени есть 8 уровней данных класса (приоритетов), которые уточняют сколько времени нужно процессу для работы с диском для каждого сервиса. Самый высокий уровень приоритета реального времени имеет значение 0; самый низкий — 7. В будущем это может измениться и можно будет непосредственно задавать желаемую скорость обмена данными с диском.

IOPRIO_CLASS_BE (2)

Класс лучшего из возможного (best-effort) планирования, устанавливается по умолчанию для всех процессов, которым не назначен определённый приоритет ввода-вывода. Данными класса (приоритет) определяется пропускная способность ввода-вывода процесса. Уровни приоритета данного класса аналогичны значениям nice для ЦП (см. getpriority(2)). Уровень приоритета определяет первоочерёдность относительно других процессов с классом лучшего из возможного планирования. Уровни приоритета находятся в диапазоне от 0 (самый высший) до 7 (самый низший).

IOPRIO_CLASS_IDLE (3)

Класс свободного (idle) планирования. Процессы, работающие с этим уровнем, получат время для ввода-вывода только когда нет обмена с диском процессов с другими классами. Свободный класс не имеет данных класса. Обратите внимание, что процесс с этим классом приоритета может испытывать нехватку ресурсов, если процессы с более высокими приоритетами постоянно обращаются к диску.

Более подробную информацию о планировщике ввода-вывода CFQ и пример программы можно найти в файле исходного кода ядра Documentation/block/ioprio.txt.

### Необходимые права для установки приоритетов ввода-вывода
Право на изменение приоритета процесса зависит от двух условий:

Владелец процесса

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

Требуемый приоритет

Попытка установить очень высокий приоритет (IOPRIO_CLASS_RT) требует мандата CAP_SYS_ADMIN. Ядра версий до 2.6.24 также требуют мандата CAP_SYS_ADMIN для установки очень низкого приоритета (IOPRIO_CLASS_IDLE), но начиная с Linux 2.6.25 это отменено.

Вызов ioprio_set() должен соблюдать оба правила, или он завершится с ошибкой EPERM.

## ДЕФЕКТЫ
В glibc пока нет заголовочного файла, определяющего прототип и макросы, описанные в этой странице. Нужные определения можно найти в linux/ioprio.h.

## СМОТРИТЕ ТАКЖЕ
ionice(1), getpriority(2), open(2), capabilities(7), cgroups(7)

Файл Documentation/block/ioprio.txt в дереве исходного кода ядра Linux


ipc

title: ipc(2)

summary: системные вызовы System V IPC

text:
# ipc(2)

## ИМЯ
ipc - системные вызовы System V IPC

## ОБЗОР

```
int ipc(unsigned int call, int first, int second, int third,
        void *ptr, long fifth);
```

## ОПИСАНИЕ
ipc() является обобщённым системным вызовом для работы с сообщениями, семафорами и разделяемой памятью согласно System V IPC (InterProcess Communication — межпроцессное взаимодействие). В параметре call задаётся какая функция IPC вызывается; значения других аргументов определяется используемой функцией.

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

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

## ЗАМЕЧАНИЯ
На некоторых архитектурах, например x86-64 и ARM, нет системного вызова ipc(); вместо него реализованы системные вызовы msgctl(2), semctl(2), shmctl(2) и т.д.

## СМОТРИТЕ ТАКЖЕ
msgctl(2), msgget(2), msgrcv(2), msgsnd(2), semctl(2), semget(2), semop(2), semtimedop(2), shmat(2), shmctl(2), shmdt(2), shmget(2), sysvipc(7)


kcmp

title: kcmp(2)

text:
# kcmp(2)

## ИМЯ
kcmp - сравнивает два процесса, определяя используют ли они общий ресурс ядра

## ОБЗОР

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

```
int kcmp(pid_t pid1, pid_t pid2, int type,
         unsigned long idx1, unsigned long idx2);
```

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

## ОПИСАНИЕ
Системный вызов kcmp() может использоваться для проверки, используют ли два процесса pid1 и pid2 общий ресурс ядра, например виртуальную память, файловые дескрипторы и т.д.

Право вызывать kcmp() определяется проверкой режима доступа ptrace PTRACE_MODE_READ_REALCREDS вместе с pid1 и pid2; смотрите ptrace(2).

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

KCMP_FILE

Проверить, что файловый дескриптор idx1 в процессе pid1 указывает на то же открытое файловое описание (смотрите open(2)) что и файловый дескриптор idx2 в процессе pid2. Существование двух файловых дескрипторов, ссылающихся на одно файловое описание, может возникнуть в результате вызова dup(2) (и подобного) в fork(2), или передачи файловых дескрипторов через доменный сокет (смотрите unix(7)).

KCMP_FILES

Проверить, используют ли процессы общий одинаковый набор открытых файловых дескрипторов. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_FILES в clone(2).

KCMP_FS

Проверить, используют ли процессы общую одинаковую информацию о файловой системе (т. е. маску прав создания, рабочий каталог и корень файловой системы). Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_FS в clone(2).

KCMP_IO

Проверить, используют ли процессы общее контекст ввода-вывода. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_IO в clone(2).

KCMP_SIGHAND

Проверить, используют ли процессы общую одинаковую таблицу обработчиков сигналов. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_SIGHAND в clone(2).

KCMP_SYSVSEM

Проверить, используют ли процессы общий одинаковый список отмены операций семафоров System V. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_SYSVSEM в clone(2).

KCMP_VM

Проверить, используют ли процессы общее адресное пространство. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_VM в clone(2).

KCMP_EPOLL_TFD (начиная с Linux 4.13)

Проверить, есть ли файловый дескриптор idx1 процесса pid1 в экземпляре epoll(7), описанном в idx2 у процесса pid2. Аргумент idx2 является указателем на структуру, которая описывает файл назначения. Формат структуры:

```
struct kcmp_epoll_slot {

    __u32 efd;

    __u32 tfd;

    __u64 toff;
};
```

В этой структуре поле efd содержит файловый дескриптор epoll, возвращаемый epoll_create(2), tfd содержит номер файлового дескриптора, а toff содержит смещение в файле назначения, начиная с нуля. Несколько разных назначений могут быть зарегистрированы с одним номером файлового дескриптора, а установка определённого смещения помогает выбрать нужный.

Заметим, что вызов kcmp() не защищён от ложных срабатываний (false positives), которые могут случаться, если процессы в этот момент выполняются. То есть для получения достоверных результатов перед выполнением данного системного вызова нужно послать процессам сигнал SIGSTOP (смотрите signal(7)).

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

Для простоты объяснения рассмотрим пример. Предположим, что v1 и v2 — адреса соответствующих ресурсов и возвращается значение:

0

v1 равен v2; другими словами, два процесса используют ресурс совместно.

1

v1 меньше v2.

2

v1 больше v2.

3

v1 не равен v2, но нужная информация недоступна.

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

Значения вызова kcmp() специально выбраны так, чтобы их легко можно было упорядочить. В частности, это удобно когда нужно сравнить большое количество файловых дескрипторов.

## ОШИБКИ
EBADF

Значение type равно KCMP_FILE и fd1 или fd2 не являются открытыми файловыми дескрипторами.

EFAULT

Слот epoll, указанный в idx2, находится за пределами пользовательского адресного пространства.

EINVAL

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

ENOENT

Файл назначения отсутствует в экземпляре epoll(7).

EPERM

Недостаточно прав для просмотра ресурсов процесса. Для проверки процессов требуется мандат CAP_SYS_PTRACE, которого у вас нет. Также могут действовать другие ограничения ptrace, например CONFIG_SECURITY_YAMA, которое при /proc/sys/kernel/yama/ptrace_scope равном 2, ограничивает kcmp() дочерними процессами; смотрите ptrace(2).

ESRCH

Процесс pid1 или pid2 не существует.

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

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

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

Данный системный вызов доступен только, если ядро собрано с параметром CONFIG_CHECKPOINT_RESTORE. Основное предназначение вызова — возможность засечки/восстановления в пользовательском пространстве (CRIU). Альтернативой этому системному вызову было бы выставление соответствующей информации о процессе в файловой системе proc(5); такой вариант не пригоден по причинам безопасности.

Дополнительную информацию об общих ресурсах смотрите в clone(2).

## ПРИМЕР
Данная программа использует kcmp() про проверки того, что пара файловых дескрипторов указывает на одно и тоже открытое файловое описание. Программа тестирует различные случаи для пар файловых дескрипторов, описанных в выводе программы. Пример работы программы:

```
$ ./a.out
PID родителя 1144
Открытый родителем файл на FD 3
PID потомка после fork() равен 1145
	Сравнение дубликатов FD из других процессов:
		kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> одинаков
Открытый потомком файл на FD 4
	Сравнение FD из различных open() одного процесса:
		kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> отличается
Дубликат FD 3 потомка для создания FD 5
	Сравнение дубликатов FD одного процесса:
		kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> одинаков
```

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

```
#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/kcmp.h>
#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \

                        } while (0)
static int
kcmp(pid_t pid1, pid_t pid2, int type,

     unsigned long idx1, unsigned long idx2)
{

    return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2);
}
static void
test_kcmp(char *msg, id_t pid1, pid_t pid2, int fd_a, int fd_b)
{

    printf("\t%s\n", msg);

    printf("\t\tkcmp(%ld, %ld, KCMP_FILE, %d, %d) ==> %s\n",

            (long) pid1, (long) pid2, fd_a, fd_b,

            (kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ?

                        "одинаков" : "отличается");
}
int
main(int argc, char *argv[])
{

    int fd1, fd2, fd3;

    char pathname[] = "/tmp/kcmp.test";

    fd1 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

    if (fd1 == -1)

        errExit("open");

    printf("PID родителя %ld\n", (long) getpid());

    printf("Открытый родителем файл на FD %d\n\n", fd1);

    switch (fork()) {

    case -1:

        errExit("fork");

    case 0:

        printf("PID потомка после fork() равен %ld\n", (long) getpid());

        test_kcmp("Сравнение дубликатов FD из других процессов:",

                getpid(), getppid(), fd1, fd1);

        fd2 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

        if (fd2 == -1)

            errExit("open");

        printf("Открытый потомком файл на FD %d\n", fd2);

        test_kcmp("Сравнение FD из различных open() одного процесса:",

                getpid(), getpid(), fd1, fd2);

        fd3 = dup(fd1);

        if (fd3 == -1)

            errExit("dup");

        printf("Дубликат FD %d потомка для создания FD %d\n", fd1, fd3);

        test_kcmp("Сравнение дубликатов FD одного процесса:",

                getpid(), getpid(), fd1, fd3);

        break;

    default:

        wait(NULL);

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
clone(2), unshare(2)


title: kexec_load(2)

text:
# kexec_load(2)

## ИМЯ
kexec_load, kexec_file_load - загружает новое ядро для выполнения в будущем

## ОБЗОР

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

```
long kexec_load(unsigned long entry, unsigned long nr_segments,
                struct kexec_segment *segments, unsigned long flags);
```

```
long kexec_file_load(int kernel_fd, int initrd_fd,
                    unsigned long cmdline_len, const char *cmdline,
                    unsigned long flags);
```

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

## ОПИСАНИЕ
Системный вызов kexec_load() загружает новое ядро, которое можно запустить позже с помощью reboot(2).

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

KEXEC_ON_CRASH (начиная с Linux 2.6.13)

Запускать новое ядро автоматически после аварии системы. Данное «аварийное ядро» загружено в область зарезервированной памяти, которая определена во время загрузки с помощью параметра командной строки ядра crashkernel. Область данной зарезервированной памяти экспортируется в пространство пользователя через файл /proc/iomem, в элемент с меткой «Crash kernel». Приложение в пользовательском пространстве может проанализировать этот файл и подготовить список сегментов (смотрите далее), которые определяют эту зарезервированную память в качестве приёмника. Если данный флаг установлен, то ядро проверяет входят ли сегменты назначения, указанные в segments, в зарезервированную область.

KEXEC_PRESERVE_CONTEXT (начиная с Linux 2.6.27)

Сохранять аппаратное и программное состояния перед выполнением нового ядра. Может использоваться для перевода системы в состояние ожидания (suspend). Этот флаг доступен только, если ядро было собрано с параметром CONFIG_KEXEC_JUMP, и работает только, если значение nr_segments больше 0.

В старших битах (соответствуют маске 0xffff0000) flags задаётся архитектура, на которой будет выполняться ядро. Константой (через OR) KEXEC_ARCH_DEFAULT задаётся использование текущей архитектуры; также есть другие константы, описывающие архитектуры: KEXEC_ARCH_386, KEXEC_ARCH_68K, KEXEC_ARCH_X86_64, KEXEC_ARCH_PPC, KEXEC_ARCH_PPC64, KEXEC_ARCH_IA_64, KEXEC_ARCH_ARM, KEXEC_ARCH_S390, KEXEC_ARCH_SH, KEXEC_ARCH_MIPS и KEXEC_ARCH_MIPS_LE.Архитектура должна быть работоспособна на ЦП системы.

В аргументе entry задаётся физический адрес точки входа в образе ядра. В аргументе nr_segments задаётся количество сегментов, на которые указывает указатель segments; ядро введено (произвольно) ограничение в 16 сегментов. В аргументе segments задаётся массив структур kexec_segment, который определяет разметку ядра:

```
struct kexec_segment {

    void   *buf;        /* буфер в пользовательском пространстве */

    size_t  bufsz;      /* размер буфера в пользовательском пространстве */

    void   *mem;        /* физический адрес ядра */

    size_t  memsz;      /* размер ядра */
};
```

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

- Значения buf и bufsz определяют область памяти в виртуальном адресном пространстве вызывающего, который является источником копирования. Значение bufsz может не превышать значение в поле memsz.

- Значения mem и memsz определяют физическое адресное пространство — приёмник копии. Значения, задаваемые в обоих полях, должны быть кратны размеру системной страницы.

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

При обычной работе kexec (т. е., флаг не установлен KEXEC_ON_CRASH) сегмент данных загружен в любую доступную память и перемещение выполняется в конечное назначение во время перезагрузки kexec (например, при выполнении команды kexec(8) с параметром -e).

При панике kexec (т. е., флаг KEXEC_ON_CRASH установлен)сегмент данных загружен в зарезервированную память на момент вызова, и, после падения (crash), механизм kexec просто передаёт управление ядру.

Системный вызов kexec_load() доступен только, если ядро было собрано с параметром CONFIG_KEXEC.

### kexec_file_load()
Системный вызов kexec_file_load() подобен kexec_load(), но имеет другой набор параметров. Он читает загружаемое ядро из файла, на который указывает файловый дескриптор kernel_fd, а initrd (начальный диск RAM) будет загружен из файла, на который указывает файловый дескриптор initrd_fd. Параметр cmdline является указателем на буфер, содержащий командную строку для нового ядра. В параметре cmdline_len указывает размер буфера. Последний байт буфера должен быть null ('\0').

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

KEXEC_FILE_UNLOAD

Выгрузить загруженное в данный момент ядро.

KEXEC_FILE_ON_CRASH

Загрузить новое ядро в область памяти зарезервированную под аварийное ядро (как для KEXEC_ON_CRASH). Ядро запускается, если отказывает работающее в данный момент ядро.

KEXEC_FILE_NO_INITRAMFS

Загрузка initrd/initramfs не обязательна. Установите данный флаг, если не нужно загружать initramfs. Если флаг установлен, то значение, передаваемое в initrd_fd игнорируется.

Системный вызов kexec_file_load() был добавлен для поддержки систем, где загрузка «kexec» должна быть ограничена только подписанными ядрами. Данный системный вызов доступен только, если ядро собрано с параметром CONFIG_KEXEC_FILE.

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

## ОШИБКИ
EADDRNOTAVAIL

Указаны флаги KEXEC_ON_CRASH, но область, заданная полями mem и memsz одного из элементов segments, находится за пределами диапазона памяти, зарезервированного для аварийного ядра.

EADDRNOTAVAIL

Значение в поле mem или memsz в одном из элементов segments не кратно размеру системной страницы.

EBADF

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

EBUSY

Уже загружено другое аварийное ядро или аварийное ядро уже используется.

EINVAL

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

EINVAL

Значение поля bufsz одного из элементов segments превышает значение в соответствующем поле memsz.

EINVAL

Значение nr_segments превышает KEXEC_SEGMENT_MAX (16).

EINVAL

Два или более буфера назначения ядра перекрываются.

EINVAL

Значение в cmdline[cmdline_len-1] не равно '\0'.

EINVAL

Файл, на который ссылается kernel_fd или initrd_fd, пуст (нулевой длины).

ENOEXEC

Значение kernel_fd не указывает на открытый файл, или ядро не может загрузить этот файл. В настоящее время, файл должен быть в формате и содержать ядро x86, которое можно загрузить в память выше 4 ГиБ (смотрите файл исходного кода ядра Documentation/x86/boot.txt).

ENOMEM

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

EPERM

Вызывающий не имеет мандата CAP_SYS_BOOT.

## ВЕРСИИ
Системный вызов kexec_load() впервые появился в Linux 2.6.13. Системный вызов kexec_file_load() впервые появился в Linux 3.17.

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

## ЗАМЕЧАНИЯ
В настоящее время в glibc нет поддержки данных системных вызовов. Вызывайте их через syscall(2).

## СМОТРИТЕ ТАКЖЕ
reboot(2), syscall(2), kexec(8)

Файлы исходного кода ядра Documentation/kdump/kdump.txt и Documentation/admin-guide/kernel-parameters.txt