setns

title: setns(2)

text:
# setns(2)

## ИМЯ
setns - повторно связывает нить с пространством имён

## ОБЗОР

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

```
int setns(int fd, int nstype);
```

## ОПИСАНИЕ
Указанный файловый дескриптор, ссылающийся на пространство имён, повторно связывается (reassociate) в вызвавшей нити с этим пространством имён.

Аргумент fd представляет собой файловый дескриптор, ссылающийся на одно из элементов пространств имён в каталоге /proc/[pid]/ns/; подробней о /proc/[pid]/ns/ смотрите в namespaces(7). Вызывающая нить будет повторно связана с соответствующим пространством имён с учётом всех ограничений, устанавливаемых аргументом nstype.

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

0

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

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

Значение fd должно указывать на пространство имён cgroup.

CLONE_NEWIPC (начиная с Linux 3.0)

Значение fd должно указывать на пространство имён IPC.

CLONE_NEWNET (начиная с Linux 3.0)

Значение fd должно указывать на пространство имён network.

CLONE_NEWNS (начиная с Linux 3.8)

Значение fd должно указывать на пространство имён mount.

CLONE_NEWPID (начиная с Linux 3.8)

Значение fd должно указывать на пространство имён PID потомков.

CLONE_NEWUSER (начиная с Linux 3.8)

Значение fd должно указывать на пространство имён user.

CLONE_NEWUTS (начиная с Linux 3.0)

Значение fd должно указывать на пространство имён UTS.

Установка nstype в 0 имеет смысл только, если вызывающий знает (или ему не важно) на какой тип пространства имён ссылается fd. Назначение ненулевого значения в nstype полезно, если вызывающий не знает на какой тип пространства имён ссылается fd. и хочет быть уверенным, что пространство имён именно нужного типа (вызывающий может не знать тип пространства имён на который указывает fd, если файловый дескриптор был открыт другим процессом и, например, передан вызывающему через доменный сокет UNIX).

### Информация по определённым типам пространств имён
Некоторые примечания и ограничения при пересопряжении с некоторыми типами пространств имён:

Пользовательские пространства имён

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

Многонитевой процесс не может изменить пространство имён пользователя с помощью setns().

Запрещается использовать setns() для повторного вхождения вызывающего в текущее пространство имён пользователя. Это не позволяет вызывающему, оставшемуся без мандатов, повторно получить их через вызов setns().

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

Дополнительную информацию о пользовательских пространствах имён смотрите в user_namespaces(7).

Пространства имён монтирования

Для смены пространства имён монтирования требуется, чтобы вызывающий процесс имел мандаты CAP_SYS_CHROOT и CAP_SYS_ADMIN в своём пространстве имён пользователя и мандат CAP_SYS_ADMIN в пользовательском пространстве имён, которое принадлежит целевому пространству имён монтирования.

Процесс не может войти в новое пространство имён монтирования, если он сообща владеет атрибутами файловых систем (атрибуты, чьё наследование управляется флагом CLONE_FS в clone(2)) с другим процессом.

Подробную информацию взаимодействии пользовательского пространствах имён и пространства имён монтирования смотрите в user_namespaces(7).

Пространства имён PID

Чтобы пересопрячь новое пространство имён PID c самим собой, вызывающий должен иметь мандат CAP_SYS_ADMIN в своём пространстве имён пользователя и пространстве имён пользователя целевого пространства имён PID.

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

Пересопряжение (reassociating) с пространством имён PID разрешено только, если пространство имён PID, указанное в fd, является потомком (дочерним, внучатым и т. д.) пространства имён PID вызывающего.

Дополнительную информацию о пространствах имён PID смотрите в pid_namespaces(7).

Пространства имён cgroup

Чтобы пересопрячь новое пространство имён cgroup c самим собой, вызывающий должен иметь мандат CAP_SYS_ADMIN в своём пространстве имён пользователя и пространстве имён пользователя целевого пространства имён cgroup.

Использование setns() для изменения пространства имён cgroup вызывающего не изменяет членство cgroup вызывающего.

Пространства имён IPC, UTS и сетевое

Чтобы пересопрячь новое пространство имён IPC, UTS или сетевое c самим собой, вызывающий должен иметь мандат CAP_SYS_ADMIN в своём пространстве имён пользователя и пространстве имён пользователя целевого пространства имён PID.

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

## ОШИБКИ
EBADF

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

EINVAL

Значение fd ссылается на пространство имён, чей тип не соответствует с указанным в nstype.

EINVAL

Эти проблемы возникают при повторном связывании нити с указанным пространством имён.

EINVAL

Вызывающий пытается объединиться с пространством имён PID предка (родителя, родителя родителя и т. д.).

EINVAL

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

EINVAL

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

EINVAL

Вызывающий состоит из нескольких нитей и пытается объединить новое пользовательское пространство имён.

ENOMEM

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

EPERM

Вызывающая нить не имеет требуемого мандата для этой операции.

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

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

## ЗАМЕЧАНИЯ
Не все атрибуты, которыми можно владеть сообща при создании новой нити с помощью using clone(2), можно изменить с помощью setns().

## ПРИМЕР
Программа, представленная ниже, ожидает два и более аргументов. В первом аргумент указывается путь к файлу пространства имён в существующем каталоге /proc/[pid]/ns/. В остальных аргументах указывается команда и её параметры. Программа открывает файл пространства имён, объединяет это пространство имён с помощью setns() и выполняет указанную команду внутри этого пространства имён.

В следующем сеансе оболочки показано использование этой программы (скомпилирована под именем ns_exec) вместе с примером для CLONE_NEWUTS из справочной страницы clone(2) (скомпилирована под именем newuts).

Сначала мы запускаем программу из clone(2) в фоновом режиме. Эта программа создаёт потомка в отдельном пространстве имён UTS. Потомок изменяет имя узла в своём пространстве имён, а затем оба процесса отображают имена узлов в своих пространствах имён UTS для того, чтобы мы увидели, что они разные.

```
$ su                   # Требуются права для выполнения

                          # операций с пространством имён
Password:
# ./newuts bizarro &
[1] 3549
clone() returned 3550
uts.nodename in child:  bizarro
uts.nodename in parent: antero
# uname -n             # проверяем имя узла в оболочке
antero
```

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

```
# ./ns_exec /proc/3550/ns/uts /bin/bash
# uname -n             # выполняется в оболочке, запущенной ns_exec
bizarro
```

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

```
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \

                        } while (0)
int
main(int argc, char *argv[])
{

    int fd;

    if (argc < 3) {

        fprintf(stderr, "%s /proc/PID/ns/FILE команда аргументы…\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    fd = open(argv[1], O_RDONLY);  /* получаем файловый дескриптор для пространства

                                      имён */

    if (fd == -1)

        errExit("open");

    if (setns(fd, 0) == -1)        /* объединяемся с этим пространством имён */

        errExit("setns");

    execvp(argv[2], &argv[2]);     /* выполняем команду в пространстве имён */

    errExit("execvp");
}
```

## СМОТРИТЕ ТАКЖЕ
nsenter(1), clone(2), fork(2), unshare(2), vfork(2), namespaces(7), unix(7)


setpgid

package: man-pages-ru

title: setpgid(2)

summary: устанавливает/получает группу процессов

text:
# setpgid(2)

## ИМЯ
setpgid, getpgid, setpgrp, getpgrp - устанавливает/получает группу процессов

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

\#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);

pid_t getpgid(pid_t pid);

pid_t getpgrp(void); /* по версии POSIX.1 */

pid_t getpgrp(pid_t pid); /* по версии BSD */

int setpgrp(void); /* по версии System V */

int setpgrp(pid_t pid, pid_t pgid); /* по версии BSD */

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

getpgid():

_XOPEN_SOURCE >= 500

|| /* начиная с glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

setpgrp() (POSIX.1):

```
    _XOPEN_SOURCE >= 500

        || /* начиная с glibc 2.19: */ _DEFAULT_SOURCE

        || /* в версии glibc <= 2.19: */ _SVID_SOURCE
```

setpgrp() (BSD), getpgrp() (BSD):

```
    [Доступно только в версиях glibc до 2.19]

    _BSD_SOURCE &&

        ! (_POSIX_SOURCE || _POSIX_C_SOURCE || _XOPEN_SOURCE ||

            _GNU_SOURCE || _SVID_SOURCE)
```

## ОПИСАНИЕ
Все перечисленные интерфейсы доступны в Linux и используются для получения и установки идентификатора группы процессов (PGID). Предпочтительней использовать версию POSIX.1: getpgrp(void) — для получения PGID вызывающего процесса; setpgid() — для установки PGID вызывающего процесса.

Вызов setpgid() устанавливает PGID у процесса с идентификатором pid равным pgid. Если значение pid равно 0, то используется идентификатор вызывающего процесса. Если значение pgid равно 0, то PGID процесса, указанного в pid, становится равным его идентификатору процесса. Если setpgid() используется для перевода процесса из одной группы в другую (это делают некоторые оболочки командной строки для объединения каналов процессов), то обе группы процессов должны быть частью одного сеанса (см. setsid(2) и credentials(7)). В этом случае в pgid указывается существующая группа процессов, в которую нужно выполнить перевод и идентификатор сеанса этой группы должен совпадать с идентификатором сеанса переводимого процесса.

В версии POSIX.1 вызов getpgrp() без аргументов возвращает PGID вызывающего процесса.

Вызов getpgid() возвращает PGID процесса с заданным pid. Если значение pid равно нулю, то используется идентификатор вызывающего процесса (получение PGID процесса, отличного от вызывающего, требуется редко, а для этой задачи хорошо подходит POSIX.1 getpgrp()).

В версии System V вызов setpgrp() без аргументов эквивалентен setpgid(0, 0).

В версии BSD вызов setpgrp() с аргументами pid и pgid является обёрточной функцией, которая вызывает

setpgid(pid, pgid)

Начиная с glibc 2.19, BSD-функция setpgrp() была удалена из <unistd.h>; вызовы должны быть заменены на вызов setpgid(), как показано выше.

В версии BSD вызов getpgrp() с аргументом pid является обёрточной функцией, которая вызывает

getpgid(pid)

Начиная с glibc 2.19, BSD-функция getpgrp() была удалена из <unistd.h>; вызовы должны быть заменены на вызов POSIX.1 getpgrp(), который не имеет аргументов (если нужно получить PGID вызывающего), или на вызов getpgid(), как показано выше.

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

Вызов getpgrp() (POSIX.1) всегда возвращает PGID вызывающего процесса.

Вызовы getpgid() и getpgrp() (BSD) при успешном выполнении возвращают группу процессов. При ошибке возвращается -1, а значение errno устанавливается соответствующим образом.

## ОШИБКИ
EACCES

Попытка изменить идентификатор группы процессов у одного из потомков вызывающего процесса, но потомок уже вызвал execve(2) (setpgid(), setpgrp()).

EINVAL

Значение pgid меньше 0 (setpgid(), setpgrp()).

EPERM

Попытка переместить процесс в группу процессов из другого сеанса или изменить идентификатор группы процессов у одного из потомков вызывающего процесса, но потомок находится в другом сеансе или изменить идентификатор группы процессов лидера сеанса (setpgid(), setpgrp()).

ESRCH

Для getpgid(): нет процесса с указанным pid. Для setpgid(): значение pid не равно идентификатору вызывающего процесса или идентификатору потомка вызывающего процесса.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов setpgid() и версия getpgrp() без аргументов соответствуют POSIX.1-2001.

В POSIX.1-2001 также определён вызов getpgid() и его версия setpgrp(), у которых нет аргументов (в POSIX.1-2008 определение setpgrp() помечено как устаревшее).

Версия getpgrp() с одним аргументом и версия setpgrp() с двумя аргументами появились из 4.2BSD и отсутствуют в POSIX.1.

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

Каждая группа процессов является членом сеанса и каждый процесс является членом сеанса, в который входит его группа процессов (смотрите credentials(7)).

Сеанс может иметь управляющий терминал. В любой момент одна (и только одна) группа процессов в сеансе может являться приоритетной группой процессов (foreground process group) терминала; оставшиеся группы процессов выполняются в фоновом режиме. Если от терминала приходит сигнал (например, нажата клавиша прерывания и сгенерирован SIGINT), то сигнал посылается в приоритетную группу процессов (смотрите в termios(3) описание символов, для которых генерируются сигналы). Только приоритетная группа процессов может выполнять вызов read(2) для терминала; если группа процессов в фоновом режиме пытается выполнить read(2) для терминала, то группе посылается сигнал SIGTTIN, который приостанавливает её выполнение. Функции tcgetpgrp(3) и tcsetpgrp(3) используются для получения/установки приоритетной группы процессов у управляющего терминала.

Вызовы setpgid() и getpgrp() используются программами, например bash(1), для создания группы процессов с целью реализации управления заданиями оболочки командной строки.

Если завершение процесса лишает группу процессов главы и если любой из такой группы процессов остановлен, то каждому процессу в группе посылается сигнал SIGHUP с последующим SIGCONT. Осиротевшей считается группа процессов, у которой родитель каждого члена группы процессов сам является членом группы процессов или членом группы процессов другого сеанса (см. также credentials(7)).

## СМОТРИТЕ ТАКЖЕ
getuid(2), setsid(2), tcgetpgrp(3), tcsetpgrp(3), termios(3), credentials(7)


setresuid

title: setresuid(2)

text:
# setresuid(2)

## ИМЯ
setresuid, setresgid - устанавливает реальный, эффективный и сохранённый пользовательский идентификатор или идентификатор группы

## ОБЗОР
\#define _GNU_SOURCE /* смотрите feature_test_macros(7) */

\#include <unistd.h>

int setresuid(uid_t ruid, uid_t euid, uid_t suid);

int setresgid(gid_t rgid, gid_t egid, gid_t sgid);

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

Непривилегированный процесс может изменять реальный UID, эффективный UID и сохранённый set-user-ID на соответственно текущий реальный UID, текущий UID и текущий сохранённый set-user-ID.

Привилегированный процесс (в Linux: имеющие мандат CAP_SETUID) могут устанавливать произвольные значения для реального, эффективного UID и сохранённого set-user-UID .

Если один из параметров равен -1, то соответствующее ему значение не изменяется.

Независимо от того, как изменились реальный UID, эффективный UID и сохранённый UID идентификатор в файловой системе всегда устанавливается равным значению (возможно новому) эффективного UID.

Аналогично, setresgid() устанавливает реальный GID, эффективный GID, и сохранённый GID вызывающего процесса (и всегда изменяет GID в файловой системе на значение эффективного GID) с теми же ограничениями для непривилегированных процессов.

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

Замечание: есть случаи, когда setresuid() может завершиться с ошибкой даже когда UID вызывающего равен 0; это серьёзная ошибка безопасности — не проверять возвращаемое значение setresuid().

## ОШИБКИ
EAGAIN

Вызов изменил бы настоящего реальный UID вызывающего (т. е. ruid не совпадает с реальным UID вызывающего), но возникла временная ошибка при выделении памяти под необходимые структуры ядра.

EAGAIN

Значение ruid не совпадает с реальным UID вызывающего и этот вызов создал был превышение количества процессов, принадлежащих пользователю с реальным ID ruid сверх ограничителя ресурсы RLIMIT_NPROC вызывающего. Начиная с Linux 3.1 эта ошибка больше не возникает (но корректное приложение должно проверять эту ошибку); смотрите описание EAGAIN в execve(2).

EINVAL

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

EPERM

Вызывающий процесс не является привилегированным (не имеет необходимого мандата в своём пространстве имён пользователя) и пытается изменить значения идентификаторов, что запрещено. Для setresuid() необходим мандат CAP_SETUID; для setresgid() — CAP_SETGID.

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

## СООТВЕТСТВИЕ СТАНДАРТАМ
Это нестандартные вызовы; также они есть в HP-UX и некоторых BSD.

## ЗАМЕЧАНИЯ
В HP-UX и FreeBSD прототип находится в <unistd.h>. В Linux прототип задан в glibc, начиная с версии 2.3.2.

Первоначальные версии системных вызовов setresuid() и setresgid() в Linux поддерживали только 16-битные идентификаторы пользователей и групп. Позднее в Linux 2.4 были добавлены вызовы setresuid32() и setresgid32(), поддерживающие 32-битные идентификаторы. В glibc обёрточные функции setresuid() и setresgid() работают одинаково вне зависимости от версий ядра.

### Отличия между библиотекой C и ядром
На уровне ядра ID пользователя и группы являются атрибутами нити. Однако в POSIX требуется, чтобы все нити в процессе имели одинаковые права. В реализации нитей NPTL требования POSIX реализованы через обёрточные функции для различных системных вызовов, которые изменяют UID и GID процесса. В этих функциях (включая и setresuid() and setresgid()) используется алгоритмы на основе сигналов, которые следят за тем, что когда у одной нити изменяются права, эти изменения выполняются и для остальных нитей процесса. Подробное описание смотрите в nptl(7).

## СМОТРИТЕ ТАКЖЕ
getresuid(2), getuid(2), setfsgid(2), setfsuid(2), setreuid(2), setuid(2), capabilities(7), credentials(7), user_namespaces(7)


setreuid

title: setreuid(2)

text:
# setreuid(2)

## ИМЯ
setreuid, setregid - устанавливает действительный и/или эффективный идентификатор пользователя или группы

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

\#include <unistd.h>

int setreuid(uid_t ruid, uid_t euid);

int setregid(gid_t rgid, gid_t egid);

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

setreuid(), setregid():

_XOPEN_SOURCE >= 500

|| /* начиная с glibc 2.19: */ _DEFAULT_SOURCE

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

## ОПИСАНИЕ
Вызов setreuid() устанавливает действительный и эффективный идентификатор пользователя вызывающего процесса.

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

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

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

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

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

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

Замечание: есть случаи, когда setreuid() может завершиться с ошибкой даже когда UID вызывающего равен 0; это серьёзная ошибка безопасности — не проверять возвращаемое значение setreuid().

## ОШИБКИ
EAGAIN

Вызов изменил бы настоящего реальный UID вызывающего (т. е. ruid не совпадает с реальным UID вызывающего), но возникла временная ошибка при выделении памяти под необходимые структуры ядра.

EAGAIN

Значение ruid не совпадает с реальным UID вызывающего и этот вызов создал был превышение количества процессов, принадлежащих пользователю с реальным ID ruid сверх ограничителя ресурсы RLIMIT_NPROC вызывающего. Начиная с Linux 3.1 эта ошибка больше не возникает (но корректное приложение должно проверять эту ошибку); смотрите описание EAGAIN в execve(2).

EINVAL

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

EPERM

Вызывающий процесс не имеет прав (Linux: не имеет необходимого мандата в своём пространстве имён пользователя: CAP_SETUID при вызове setreuid() или мандата CAP_SETGID при вызове setregid()), а требуемые изменения не относятся к следующим: 1) взаимозамене эффективного идентификатора на действительный идентификатор пользователя (группы); 2) установке значения одного идентификатора в значение другого; 3) замене эффективного идентификатора пользователя (группы) на сохранённый идентификатор пользователя (группы).

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, 4.3BSD (setreuid() и setregid() впервые появились в 4.2BSD).

## ЗАМЕЧАНИЯ
Установка эффективного идентификатора пользователя (группы) в значение сохранённого идентификатора возможна с версии Linux 1.1.37 (1.1.38).

В POSIX.1 не определены все варианты изменения идентификаторов, разрешённые в Linux непривилегированным процессам. Вызов setreuid() может изменить значение эффективного пользовательского идентификатора на действительный или сохранённый пользовательский идентификатор и не определено, может ли непривилегированный процесс установить действительный пользовательский идентификатор равным действительному, эффективному или сохранённому пользовательскому идентификатору. Вызов setregid() может изменить действительный идентификатор группы на значение сохранённого идентификатора группы, а эффективный идентификатор группы — на значение действительного или сохранённого идентификатора группы. Действующие правила о разрешённых изменениях идентификаторов отличаются в разных реализациях.

В POSIX.1 ничего не сказано о работе этих вызовов над сохранённым идентификатором пользователя и группы.

Первоначальные версии системных вызовов setreuid() и setregid() в Linux поддерживали только 16-битные идентификаторы пользователей и групп. Позднее в Linux 2.4 были добавлены вызовы setreuid32() и setregid32(), поддерживающие 32-битные идентификаторы. В glibc обёрточные функции setreuid() и setregid() работают одинаково вне зависимости от версий ядра.

### Отличия между библиотекой C и ядром
На уровне ядра ID пользователя и группы являются атрибутами нити. Однако в POSIX требуется, чтобы все нити в процессе имели одинаковые права. В реализации нитей NPTL требования POSIX реализованы через обёрточные функции для различных системных вызовов, которые изменяют UID и GID процесса. В этих функциях (включая setreuid() и setregid()) используется алгоритмы на основе сигналов, которые следят за тем, что когда у одной нити изменяются права, эти изменения выполняются и для остальных нитей процесса. Подробное описание смотрите в nptl(7).

## СМОТРИТЕ ТАКЖЕ
getgid(2), getuid(2), seteuid(2), setgid(2), setresuid(2), setuid(2), capabilities(7), credentials(7), user_namespaces(7)


setsid

title: setsid(2)

text:
# setsid(2)

## ИМЯ
setsid - создает сеанс и устанавливает идентификатор группы процесса

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

\#include <unistd.h>

pid_t setsid(void);

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

Вызывающий процесс будет единственным в новой группе процессов и новом сеансе.

Изначально, новый сеанс не имеет управляющего терминала. О том, как сеанс получает управляющий терминал, смотрите в credentials(7).

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

## ОШИБКИ
EPERM

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

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

## ЗАМЕЧАНИЯ
Потомок, создаваемый с помощью fork(2), наследует ID сеанса своего родителя. Идентификатор сеанса сохраняется при вызове execve(2).

Лидер группы процессов — это процесс, идентификатор группы процессов которого равен идентификатору самого процесса (PID). Отказ лидера группы процессов выполнять setsid() предотвращает возможность того, что сам лидер группы процессов переместится в новый сеанс, в то время как другие процессы в группе останутся в первоначальном сеансе; это поломало бы жёсткую двухуровневую иерархию сценариев и групп процессов. Для того, чтобы setsid() выполнился успешно, вызовите fork(2) и в родителе _exit(2), а затем в дочернем процессе (который по определению не может быть лидером группы процессов) вызовите setsid().

Если сеанс имеет управляющий терминал, у которого не установлен флаг CLOCAL и возникает зависание (hangup) терминала, то лидеру сеанса посылается SIGHUP.

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

## СМОТРИТЕ ТАКЖЕ
setsid(1), getsid(2), setpgid(2), setpgrp(2), tcgetsid(3), credentials(7), sched(7)


setuid

title: setuid(2)

text:
# setuid(2)

## ИМЯ
setuid - устанавливает идентификатор пользователя

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

\#include <unistd.h>

int setuid(uid_t uid);

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

В Linux setuid() реализован как и в стандарте POSIX с возможностью _POSIX_SAVED_IDS. Это позволяет setuid-программам (не setuid-root) сбрасывать все привилегии, делать непривилегированную работу, а затем безопасным путём возвращать себе исходный эффективный идентификатор пользователя.

Если пользователь root или программа установлена как setuid root, при работе требуется особая осторожность: функция setuid() проверяет эффективный идентификатор вызвавшего пользователя и, если это суперпользователь, то все устанавливаемые значения идентификаторов равны uid. После этого программа уже никаким образом не сможет вернуть права пользователя root.

Таким образом, программа, принадлежащая root и с установленным битом setuid, собирающаяся временно сбросить права root и поработать с правами непривилегированного пользователя, а затем восстановить права root, не сможет использовать setuid(). Требуемого результата можно достичь с помощью вызова seteuid(2).

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

Замечание: есть случаи, когда setuid() может завершиться с ошибкой даже когда UID вызывающего равен 0; это серьёзная ошибка безопасности — не проверять возвращаемое значение setuid().

## ОШИБКИ
EAGAIN

Вызов изменил бы настоящего реальный UID вызывающего (т. е. uid не совпадает с реальным UID вызывающего), но возникла временная ошибка при выделении памяти под необходимые структуры ядра.

EAGAIN

Значение uid не совпадает с реальным UID вызывающего и этот вызов создал был превышение количества процессов, принадлежащих пользователю с реальным ID ruid сверх ограничителя ресурсы RLIMIT_NPROC вызывающего. Начиная с Linux 3.1 эта ошибка больше не возникает (но корректное приложение должно проверять эту ошибку); смотрите описание EAGAIN в execve(2).

EINVAL

Идентификатор пользователя, заданный в uid, некорректен в этом пользовательском пространстве имён.

EPERM

Пользователь не является суперпользователем (Linux: нет мандата CAP_SETUID в пользовательском пространстве имён), а uid не совпадает с действительным или сохранённым идентификатором пользователя вызывающего процесса.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4. Этот системный вызов не полностью совместим с 4.4BSD, который устанавливает действительный, эффективный и сохранённый идентификаторы пользователя.

## ЗАМЕЧАНИЯ
Linux поддерживает идентификатор пользователя файловой системы, обычно совпадающий с эффективным идентификатором. Системный вызов setuid() также устанавливает идентификатор пользователя файловой системы вызывающего процесса. См. setfsuid(2).

Если uid отличается от старого эффективного идентификатора, то процессу нельзя будет создавать core-файлы.

Первоначальная версия системного вызова setuid() в Linux поддерживала только 16-битные идентификаторы пользователя. Позднее в Linux 2.4 был добавлен вызов setuid32(), поддерживающий 32-битные идентификаторы. В glibc обёрточная функция setuid() работает одинаково вне зависимости от версий ядра.

### Отличия между библиотекой C и ядром
На уровне ядра ID пользователя и группы являются атрибутами нити. Однако в POSIX требуется, чтобы все нити в процессе имели одинаковые права. В реализации нитей NPTL требования POSIX реализованы через обёрточные функции для различных системных вызовов, которые изменяют UID и GID процесса. В этих функциях (включая и setuid()) используется алгоритмы на основе сигналов, которые следят за тем, что когда у одной нити изменяются права, эти изменения выполняются и для остальных нитей процесса. Подробное описание смотрите в nptl(7).

## СМОТРИТЕ ТАКЖЕ
getuid(2), seteuid(2), setfsuid(2), setreuid(2), capabilities(7), credentials(7), user_namespaces(7)


setup

title: setup(2)

text:
# setup(2)

## ИМЯ
setup - настраивает устройства и файловые системы, монтирует корневую файловую систему

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

int setup(void);

## ОПИСАНИЕ
setup() вызывается один раз из linux/init/main.c. Она вызывает функции инициализации устройств и файловых систем, встроенных в ядро, и затем монтирует корневую файловую систему.

Ни один из пользовательских процессов не может вызвать setup(). Любой пользовательский процесс даже с правами суперпользователя будет получать сообщение об ошибке с кодом EPERM.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Вызов setup() всегда возвращает пользовательскому процессу значение -1.

## ОШИБКИ
EPERM

Всегда для пользовательского процесса.

## ВЕРСИИ
Начиная с Linux 2.1.121, эта функция не существует.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция применяется только в Linux и поэтому не должна использоваться в программах, предназначенных для переноса на другую платформу, и вообще не должна вызываться из пользовательских программ.

## ЗАМЕЧАНИЯ
Вызывающая последовательность менялась: в некоторых версиях у setup() был один аргумент void *BIOS, а в некоторых — int magic.


setxattr

title: setxattr(2)

summary: устанавливает расширенное значение

text:
# setxattr(2)

## ИМЯ
setxattr, lsetxattr, fsetxattr - устанавливает расширенное значение атрибутов

## ОБЗОР

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

```
int setxattr(const char *path, const char *name,
              const void *value, size_t size, int flags);
int lsetxattr(const char *path, const char *name,
              const void *value, size_t size, int flags);
int fsetxattr(int fd, const char *name,
              const void *value, size_t size, int flags);
```

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

Вызов setxattr() устанавливает значение value расширенного атрибута с именем, заданным в name и связанного с заданным path в файловой системе. В аргументе size задаётся размер (в байтах) value; допускается нулевой размер.

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

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

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

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

XATTR_CREATE

Выполнять только создание, если атрибут с таким именем существует — возвращать ошибку.

XATTR_REPLACE

Выполнять только замену, если атрибут с таким именем не существует — возвращать ошибку.

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

## ОШИБКИ
EDQUOT

Предел по дисковой квоте; не хватает пространства для сохранения расширенного атрибута.

EEXIST

Указан XATTR_CREATE, но атрибут уже существует.

ENODATA

Указан XATTR_REPLACE, но атрибут не существует.

ENOSPC

Не хватает пространства для сохранения расширенного атрибута.

ENOTSUP

Неверный префикс пространства имён name.

ENOTSUP

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

EPERM

Файл помечен как неизменяемый (immutable) или только для добавления (смотрите ioctl_iflags(2)).

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

ERANGE

Размер name или value превышает ограничение, задаваемое файловой системой.

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

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

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


sgetmask

title: sgetmask(2)

summary: работа с маской сигналов (устарел)

text:
# sgetmask(2)

## ИМЯ
sgetmask, ssetmask - работа с маской сигналов (устарел)

## ОБЗОР
long sgetmask(void);

long ssetmask(long newmask);

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

## ОПИСАНИЕ
Данные системные вызовы устарели. Используйте вместо них sigprocmask(2).

Вызов sgetmask() возвращает маску сигналов вызывающего процесса.

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

Маски сигналов обрабатываются этими системными вызовами как простые битовые маски (в отличие от sigset_t, который используется в sigprocmask(2)); для создания и проверки масок используйте sigmask(3).

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

## ОШИБКИ
Данные системные вызовы всегда выполняются без ошибок.

## ВЕРСИИ
Начиная с Linux 3.16 поддержка данных системных вызовов необязательна, она зависит от того, собрано ли ядро с параметром CONFIG_SGETMASK_SYSCALL.

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

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

Данные системные вызовы ничего не знают о номерах сигналов больше 31 (т.е. сигналах реального времени).

Данные системные вызовы не существуют на x86-64.

Они не могут заблокировать SIGSTOP или SIGKILL.

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


shmctl

title: shmctl(2)

summary: управление общей памятью System V

text:
# shmctl(2)

## ИМЯ
shmctl - управление общей памятью System V

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

\#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

## ОПИСАНИЕ
Вызов shmctl() выполняет управляющую операцию, указанную в cmd, над общим сегментом памяти System V, чей идентификатор задан в shmid.

В аргументе buf содержится указатель на структуру shmid_ds, определённую в <sys/shm.h> следующим образом:

```
struct shmid_ds {

    struct ipc_perm shm_perm;    /* владелец и права */

    size_t          shm_segsz;   /* размер сегмента (байты) */

    time_t          shm_atime;   /* время последнего подключения */

    time_t          shm_dtime;   /* время последнего отключения */

    time_t          shm_ctime;   /* время последнего изменения */

    pid_t           shm_cpid;    /* PID создателя */

    pid_t           shm_lpid;    /* PID последнего выполнявшего

                                    shmat(2)/shmdt(2) */

    shmatt_t        shm_nattch;  /* текущее количество подключений */

    ...
};
```

Структура ipc_perm определена следующим образом (значения полей устанавливаются с помощью IPC_SET):

```
struct ipc_perm {

    key_t          __key;    /* ключ, передаваемый в shmget(2) */

    uid_t          uid;      /* эффективный UID владельца */

    gid_t          gid;      /* эффективный GID владельца */

    uid_t          cuid;     /* эффективный UID создателя */

    gid_t          cgid;     /* эффективный GID создателя */

    unsigned short mode;     /* права + флаги SHM_DEST и

                                SHM_LOCKED */

    unsigned short __seq;    /* порядковый номер */
};
```

Возможные значения cmd:

IPC_STAT

Копирует информацию из структуры данных ядра, связанной с shmid, в структуру shsid_ds, расположенную по адресу buf. Вызывающий должен иметь права на чтение общего сегмента памяти.

IPC_SET

Записывает значения некоторых полей структуры shmid_ds, указанной в buf, в структуру данных ядра, связанную с общим сегментом памяти, обновляя при этом поле shm_ctime. Могут измениться следующие поля: shm_perm.uid, shm_perm.gid и shm_perm.mode (младшие 9 битов). Эффективный UID вызывающего процесса должен совпадать с UID владельца (shm_perm.uid) или создателя (shm_perm.cuid) общего сегмента памяти, или вызывающий должен иметь привилегии.

IPC_RMID

Помечает сегмент как удалённый. Сегмент будет удалён только после того как от него отключится последний процесс (т.е. когда поле shm_nattch из связанной структуры shmid_ds станет равно нулю). Вызывающий должен быть владельцем, создателем или иметь соответствующие привилегии. Аргумент buf игнорируется.

Если сегмент помечен на удаление, то в поле shm_perm.mode устанавливается (нестандартный) флаг SHM_DEST в связанной структуре данных, которая возвращается при операции IPC_STAT.

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

Смотрите также описание /proc/sys/kernel/shm_rmid_forced в proc(5).

IPC_INFO (есть только в Linux)

Возвращает параметры и информацию о системных максимальных значениях общей памяти в структуре, указанной в buf. Данная структура имеет тип shminfo (то есть, требуется приведение типов) и определена в <sys/shm.h>, если определён макрос тестирования свойств _GNU_SOURCE:

```
struct shminfo {

    unsigned long shmmax; /* максимальный размер

                             сегмента */

    unsigned long shmmin; /* минимальный размер сегмента;

                             всегда 1 */

    unsigned long shmmni; /* максимальное количество

                             сегментов */

    unsigned long shmseg; /* максимальное количество

                             сегментов, к которому может

                             подключиться; процесс

                             не используется в ядре */

    unsigned long shmall; /* макс. количество страниц

                             общей памяти в системе */
};

```

Значения shmmni, shmmax и shmall можно изменить с помощью файлов в /proc с теми же именами; подробней см. proc(5).

SHM_INFO (есть только в Linux)

Возвращает структуру shm_info, чьи поля содержат информацию о системных ресурсах, использованных общей памятью. Эта структура определена в <sys/shm.h>, если определён макрос тестирования свойств _GNU_SOURCE:

```
struct shm_info {

    int           used_ids; /* количество используемых в

                               данный момент сегментов */

    unsigned long shm_tot;  /* общее количество общих

                               страниц памяти */

    unsigned long shm_rss;  /* количество общих страниц,

                               находящихся в памяти */

    unsigned long shm_swp;  /* количество страниц памяти в

                               пространстве подкачки */

    unsigned long swap_attempts; /* не используется,

                                    начиная с Linux 2.4 */

    unsigned long swap_successes; /* не используется,

                                     начиная с Linux 2.4 */
};

```

SHM_STAT (есть только в Linux)

Возвращает структуру shmid_ds как в операции IPC_STAT. Однако аргумент shmid является не идентификатором сегмента, а индексом во внутреннем массиве ядра, в котором содержится информации о всех общих сегментов памяти в системе.

SHM_STAT_ANY (есть только в Linux, начиная с Linux 4.17)

Возвращает структуру shmid_ds как для SHM_STAT. Однако shm_perm.mode не проверяется на доступность чтения для shmid, что означает, что эту операцию может выполнять пользователь (как и любой пользователь, который может прочитать эту же информацию из /proc/sysvipc/shm).

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

SHM_LOCK (есть только в Linux)

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

SHM_UNLOCK (есть только в Linux)

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

В ядрах до версии 2.6.10 только привилегированный процесс мог использовать SHM_LOCK и SHM_UNLOCK. Начиная с ядра версии 2.6.10 непривилегированный процесс может использовать эти операции, если его эффективный UID совпадает с UID владельца или создателя сегмента и (для SHM_LOCK) количество блокируемой памяти находится в пределах ресурса RLIMIT_MEMLOCK (см. setrlimit(2)).

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

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

## ОШИБКИ
EACCES

Указана операция IPC_STAT или SHM_STAT, но в shm_perm.mode не установлено право на чтение shmid, и вызывающий процесс не имеет мандата CAP_IPC_OWNER в пространстве имён пользователя, который управляет его пространством имён IPC.

EFAULT

Значение аргумента cmd равно IPC_SET или IPC_STAT, но адрес, указанный в buf, недоступен.

EIDRM

Значение shmid указывает на удалённый идентификатор.

EINVAL

Значение shmid содержит недопустимый идентификатор, или cmd содержит недопустимую команду. Или (для SHM_STAT или SHM_STAT_ANY) индекс shmid ссылается на элемент массива, который в данный момент не используется.

ENOMEM

(в ядрах, начиная с 2.6.9) Указана операция SHM_LOCK и размер блокируемого сегмента таков, что общее количество байт, блокируемое общими сегментами памяти, превысило бы ограничение, установленное для действительного идентификатора пользователя вызывающего процесса. Этот лимит определён мягким ограничителем ресурса RLIMIT_MEMLOCK (см. setrlimit(2)).

EOVERFLOW

Попытка выполнить IPC_STAT, но значения GID или UID слишком велики для помещения в структуру, на которую указывает buf.

EPERM

Попытка выполнить IPC_SET или IPC_RMID, но эффективный пользовательский идентификатор вызывающего процесса не равен идентификатору создателя (shm_perm.cuid) или владельца (shm_perm.uid) и процесс не привилегированный (Linux: не имеет мандата CAP_SYS_ADMIN).

Или (в ядрах до 2.6.9) процесс не имеет привилегий (Linux: не имеет мандата CAP_IPC_LOCK) для выполнения SHM_LOCK или SHM_UNLOCK. Начиная с Linux 2.6.9 эта ошибка также возникает, если значение RLIMIT_MEMLOCK равно 0 и вызывающий не имеет привилегий.

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

## ЗАМЕЧАНИЯ
Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.

Операции IPC_INFO, SHM_STAT и SHM_INFO используются программой ipcs(1) для получения информации о выделенных ресурсах. В будущем для этого может быть задействован интерфейс файловой системы /proc.

Linux разрешает процессу подключаться (shmat(2)) к общему сегменту память, который уже помечен как удалённый с помощью shmctl(IPC_RMID). Это свойство недоступно в других реализациях UNIX; в переносимых приложениях лучше не использовать это свойство.

В Linux 2.2 различные поля struct shmid_ds имели тип short. В Linux 2.4 тип был изменён на long. Для задействования преимуществ этого изменения необходима перекомпиляция программы с glibc-2.1.91 или более поздней версией (ядро различает старые и новые вызовы по флагу IPC_64 в аргументе cmd).

## СМОТРИТЕ ТАКЖЕ
mlock(2), setrlimit(2), shmget(2), shmop(2), capabilities(7), sysvipc(7)


shmget

title: shmget(2)

summary: выделяет общий сегмент памяти System V

text:
# shmget(2)

## ИМЯ
shmget - выделяет общий сегмент памяти System V

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

\#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

## ОПИСАНИЕ
Вызов shmget() возвращает идентификатор общего сегмента памяти System V, соответствующего значению аргумента key. Его можно использовать для получения идентификатора ранее созданного общего сегмента памяти (когда shmflg равно нулю и key не содержит значения IPC_PRIVATE) или для создания нового.

Новый общий сегмент памяти размером size, округлённым до значения, кратного PAGE_SIZE создаётся, если значение key равно IPC_PRIVATE или, если key не равно IPC_PRIVATE, но не существует общего сегмента памяти, который бы соответствовал значению key и в shmflg есть флаг IPC_CREAT.

Если в shmflg одновременно указаны IPC_CREAT и IPC_EXCL и для значения key уже существует общий сегмент памяти, то вызов shmget() завершается с ошибкой и errno присваивается EEXIST (такой же результат как с O_CREAT | O_EXCL у open(2)).

Значение shmflg составляется из следующих флагов:

IPC_CREAT

Служит для создания нового сегмента. Если этого флага нет, то вызов shmget() будет искать сегмент, соответствующий key, и затем проверит, имеет ли пользователь права на доступ к сегменту.

IPC_EXCL

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

SHM_HUGETLB (начиная с Linux 2.6)

Выделять сегмент используя «огромные страницы». Дополнительную информацию смотрите в файле исходного кода ядра Linux Documentation/admin-guide/mm/hugetlbpage.rst.

SHM_HUGE_2MB, SHM_HUGE_1GB (начиная с Linux 3.8)

Используется вместе с SHM_HUGETLB для выбора других размеров страниц hugetlb (2 МБ и 1 МБ, соответственно) в системах, которые поддерживают несколько размеров страниц hugetlb.

Вообще, желаемые размер огромной страницы можно настроить закодировав логарифмом по основанию 2 желаемый размер страницы в шести битах смещения SHM_HUGE_SHIFT. Таким образом, приведённые выше константы определяются так:

```
#define SHM_HUGE_2MB    (21 << SHM_HUGE_SHIFT)
#define SHM_HUGE_1GB    (30 << SHM_HUGE_SHIFT)

```

Дополнительную информацию о схожих по имени константах смотрите в mmap(2).

SHM_NORESERVE (начиная с Linux 2.6.15)

Этот флаг нужен для того же, что и флаг MAP_NORESERVE у mmap(2). Он указывает не резервировать место в пространстве подкачки для этого сегмента. Операцией резервирования места в пространстве подкачки гарантируется, что сегмент можно изменить. Если место не резервировать, то при записи можно получить сигнал SIGSEGV, если кончится физическая память. Смотрите также обсуждение файла /proc/sys/vm/overcommit_memory в proc(5).

В дополнении к перечисленным выше флагам в младших 9 битах shmflg задаются права для владельца, группы и всех остальных. Формат значения битов совпадает с аргументом mode вызова open(2). В данный момент бит выполнения системой не используются.

Если создаётся новый общий сегмент памяти, то его содержимое инициализируется нулями, а соответствующая ему структура данных shmid_ds (см. shmctl(2)) следующим образом:

Полям shm_perm.cuid и shm_perm.uid присваиваются значения эффективного идентификатора пользователя вызывающего процесса.

Полям shm_perm.cgid и shm_perm.gid присваиваются значения эффективного идентификатора группы вызывающего процесса.

Младшим 9 битам shm_perm.mode присваивается значение младших 9 бит shmflg.

Полю shm_segsz присваивается значение size.

Полям shm_lpid, shm_nattch, shm_atime и shm_dtime присваивается значение 0.

Полю shm_ctime присваивается значение текущего времени.

Если общий сегмент памяти уже существует, то проверяются права доступа к нему и не помечен ли он для удаления.

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

## ОШИБКИ
В случае возникновения ошибки errno может принимать следующие значения:

EACCES

Пользователь не имеет прав доступа к общему сегменту памяти и не имеет мандата CAP_IPC_OWNER в пространстве имён пользователя, который управляет его пространством имён IPC.

EEXIST

В shmflg указаны IPC_CREAT и IPC_EXCL, но общий сегмент памяти уже существует для key.

EINVAL

Был создан новый сегмент и size меньше SHMMIN или больше SHMMAX.

EINVAL

Сегмент для заданного key существует, но size больше размера этого сегмента.

ENFILE

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

ENOENT

Не существует сегмента для ключа key и флаг IPC_CREAT не указан.

ENOMEM

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

ENOSPC

Все возможные идентификаторы сегментов уже распределены (SHMMNI) или размер выделяемого сегмента превысит системные лимиты по общей памяти (SHMALL).

EPERM

Указан флаг SHM_HUGETLB, но у вызывающего нет прав (нет мандата CAP_IPC_LOCK).

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

SHM_HUGETLB и SHM_NORESERVE являются расширениями Linux.

## ЗАМЕЧАНИЯ
Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.

IPC_PRIVATE — не поле флага, а тип key_t. Если key равно этому специальному значению, то системный вызов игнорирует всё кроме 9-ти младших битов shmflg и создаёт новый общий сегмент памяти.

### Ограничения общей памяти
Ниже приведены ограничения ресурсов на общий сегмент памяти, влияющие на вызов shmget():

SHMALL

Системный лимит на полный объём общей памяти, измеряется в единицах, равных размеру системной страницы.

В Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/shmmni. Начиная с 3.16, значение по умолчанию равно:

ULONG_MAX - 2^24

Эффект этого значения (которое подходит и для 32-разрядной, и для 64-разрядной системы) — не задать ограничение на выделения. Это значение, в отличии от ULONG_MAX, было выбрано в качестве значения по умолчанию, чтобы предотвратить некоторые случаи, когда старые приложения просто увеличивают существующий предел без начальной проверки его текущего значения. Такие приложения переполнили бы значение, если предел был равен ULONG_MAX.

В Linux 2.4 по Linux 3.15 значение по умолчанию этого ограничения было:

SHMMAX / PAGE_SIZE * (SHMMNI / 16)

Если SHMMAX и SHMMNI не изменены, то умножение результата этой формулы на размер страницы (для получения значения в байтах) даёт значение 8 ГБ — ограничение на общее количество памяти, используемой во всех общих сегментах памяти.

SHMMAX

Максимальный размер общего сегмента памяти в байтах.

В Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/shmmax. Начиная с 3.16, значение по умолчанию равно:

ULONG_MAX - 2^24

Эффект этого значения (которое подходит и для 32-разрядной, и для 64-разрядной системы) — не задать ограничение на выделения. Смотрите описание SHMALL о том, почему используется именно такое значение по умолчанию (а не ULONG_MAX).

В Linux 2.2 по Linux 3.15 значение по умолчанию этого ограничения равно 0x2000000 (32 МБ).

Так как невозможно отобразить только часть общего сегмента памяти, размер виртуальной памяти отличается от ограничения на максимальный размер подходящего сегмента: например, на i386 самые большие сегменты, которые можно отображать, имеют размер около 2.8 ГБ, а на x86-64 — около 127 ТБ.

SHMMIN

Минимальный размер общего сегмента памяти в байтах в системе: зависит от реализации (в настоящий момент равно 1 байту, хотя на самом деле минимальный выделяемый размер равен PAGE_SIZE).

SHMMNI

Системный лимит на общее количество общих сегментов памяти. Начиная с Linux 2.2, значение по умолчанию равно 128; начиная с Linux 2.4, значение по умолчанию равно 4096.

В Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/shmmni.

Реализацией не ограничивается максимальное количество общих сегментов памяти на процесс (SHMSEG).

### Замечания, касающиеся Linux
В Linux до версии 2.3.30 вызов shmget() возвращал значение EIDRM, если общий сегмент памяти был запланирован к удалению.

## ДЕФЕКТЫ
Имя IPC_PRIVATE, возможно, было выбрано неудачно, IPC_NEW отражает смысл действия более ясно.

## СМОТРИТЕ ТАКЖЕ
memfd_create(2), shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), shm_overview(7), sysvipc(7)


shmop

title: shmop(2)

summary: операции с общей памятью System V

text:
# shmop(2)

## ИМЯ
shmat, shmdt - операции с общей памятью System V

## ОБЗОР

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

```
void *shmat(int shmid, const void *shmaddr, int shmflg);
```

```
int shmdt(const void *shmaddr);
```

## ОПИСАНИЕ

### shmat()
Вызов shmat() подключает сегмент общей памяти System V с идентификатором shmid к адресному пространству вызывающего процесса. Адрес подключения, указанный в shmaddr, учитывается следующим образом:

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

- Если значение shmaddr не равно NULL, а в shmflg указан флаг SHM_RND, то подключение производится по адресу shmaddr, округлённому до ближайшего значения кратного SHMLBA.

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

В дополнении к SHM_RND, в аргументе битовой маски shmflg могут быть указаны следующие флаги:

SHM_EXEC (есть только в Linux; начиная с Linux 2.6.9)

Разрешить выполнение содержимого сегмента. Вызывающий должен иметь права на выполнение сегмента.

SHM_RDONLY

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

SHM_REMAP (есть только в Linux)

Этот флаг указывает, что отображение сегмента должно замещать любые существующие отображения в диапазоне, начиная с shmaddr и до размера сегмента (обычно выдается ошибка EINVAL, если в этом диапазоне адресов уже есть отображение). В этом случае значение shmaddr не должно быть равно NULL.

Значение brk(2) вызывающего процесса от подключения не изменяется. При завершении работы процесса сегмент будет автоматически отсоединён. Один и тот же сегмент может быть подключён в адресное пространство процесса несколько раз, как только для чтения, так и для чтения-записи.

При успешном выполнении системный вызов shmat() обновляет поля структуры shmid_ds (см. shmctl(2)), связанной с общим сегментом памяти, следующим образом:

Полю shm_atime присваивается значение текущего времени.

Значение shm_lpid устанавливается равным идентификатору вызывающего процесса.

Значение shm_nattch увеличивается на 1.

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

При успешном выполнении вызов shmdt() обновляет поля структуры shmid_ds, связанной с общим сегментом памяти, следующим образом:

Полю shm_dtime присваивается значение текущего времени.

Значение shm_lpid устанавливается равным идентификатору вызывающего процесса.

Значение shm_nattch уменьшается на 1. Если оно становится равным 0 и сегмент помечен для удаления, то сегмент удаляется.

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

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

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

EACCES

Вызывающий процесс не имеет прав для подключения заданного типа и не имеет мандата CAP_IPC_OWNER в пространстве имён пользователя, который управляет его пространством имён IPC.

EIDRM

Значение shmid указывает на удалённый идентификатор.

EINVAL

Неправильное значение shmid, не выровненное (по границе страницы и не указан SHM_RND) или неправильное значение shmaddr, или невозможно подключить сегмент по адресу shmaddr, или был указан SHM_REMAP, но shmaddr равно NULL.

ENOMEM

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

Значения errno, устанавливаемые при возникновении ошибок в shmdt():

EINVAL

По адресу shmaddr подключённый общий сегмент памяти отсутствует; или значение shmaddr не выровнено по границе страницы.

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

В SVID 3 (возможно, чуть раньше) тип аргумента shmaddr изменён с char * на const void *, а тип возвращаемого значения shmat() с char * на void *.

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

При вызове execve(2) все подключённые общие сегменты памяти отключаются.

При вызове _exit(2) все подключённые общие сегменты памяти отключаются.

Для улучшения переносимости программ при подключении общего сегмента памяти рекомендуется использовать shmat() с аргументом shmaddr, установленным в NULL. Необходимо учитывать, что сегмент памяти, подключаемый таким способом, в разных процессах может подключаться по разным адресам. Поэтому все указатели в области общей памяти должны быть не абсолютными, а относительными (как правило относительно адреса начала сегмента).

В Linux сегмент общей памяти можно подключить даже, если он помечен для удаление. Однако в POSIX.1 об этом ничего не сказано, и многие другие реализации это не поддерживают.

На работу shmat() влияют следующие системные параметры:

SHMLBA

Кратность адреса нижней границы сегмента. При явном указании в вызове shmat() подключаемого адреса вызывающий должен убедиться, что адрес кратен этому значению. Это необходимо у некоторых архитектур, чтобы точно получить хорошую производительность от кэша ЦП или чтобы различные подключения одного сегмента имели целостный вид внутри кэша ЦП. Параметр SHMLBA, обычно, кратен нескольким размерам системной страницы (у многих архитектур Linux SHMLBA совпадает с размером системной страницы).

Реализацией не ограничивается количество общих сегментов общей памяти на процесс (SHMSEG).

## СМОТРИТЕ ТАКЖЕ
brk(2), mmap(2), shmctl(2), shmget(2), capabilities(7), shm_overview(7), sysvipc(7)


shutdown

title: shutdown(2)

text:
# shutdown(2)

## ИМЯ
shutdown - закрывает часть полнодуплексного соединения

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

int shutdown(int sockfd, int how);

## ОПИСАНИЕ
Вызов shutdown() приводит к закрытию всего полнодуплексного соединения или его части в сокете, связанном с sockfd. Если значение how равно SHUT_RD, то дальнейший приём данных будет запрещён. Если значение how равно SHUT_WR, то дальнейшая передача данных будет запрещена. Если значение how равно SHUT_RDWR, то дальнейший приём и передача данных будут запрещены.

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

## ОШИБКИ
EBADF

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

EINVAL

Указано неверное значение в how (но смотрите ДЕФЕКТЫ).

ENOTCONN

Указанный сокет не подключён.

ENOTSOCK

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

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

## ЗАМЕЧАНИЯ
Константы SHUT_RD, SHUT_WR, SHUT_RDWR имеют значения 0, 1, 2, соответственно, и определены в <sys/socket.h> начиная с glibc-2.1.91.

## ДЕФЕКТЫ
Проверки применимости how выполняются в коде, относящемся к домену, и до Linux 3.7 проверки были не во всех доменах. В первую очередь, это были доменные сокеты UNIX, которые просто игнорировали некорректные значения. Данная проблема была устранена для доменных сокетов UNIX в Linux 3.7.

## СМОТРИТЕ ТАКЖЕ
close(2), connect(2), socket(2), socket(7)


sigaction

title: sigaction(2)

summary: получает и изменяет обработчик сигнала

text:
# sigaction(2)

## ИМЯ
sigaction, rt_sigaction - получает и изменяет обработчик сигнала

## ОБЗОР

```
#include <signal.h>
```

```
int sigaction(int signum, const struct sigaction *act,
              struct sigaction *oldact);
```

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

sigaction(): _POSIX_C_SOURCE

siginfo_t: _POSIX_C_SOURCE >= 199309L

## ОПИСАНИЕ
Системный вызов sigaction() используется для изменения выполняемого процессом действия при получении определённого сигнала (список сигналов смотрите в signal(7)).

В signum указывается сигнал; может принимать значение любого корректного сигнала за исключением SIGKILL и SIGSTOP.

Если значение act не равно NULL, то устанавливается новое действие для сигнала signum из act. Если значение oldact не равно NULL, то предыдущее действие записывается в oldact.

Структура sigaction определена следующим образом:

```
struct sigaction {

    void     (*sa_handler)(int);

    void     (*sa_sigaction)(int, siginfo_t *, void *);

    sigset_t sa_mask;

    int      sa_flags;

    void     (*sa_restorer)(void);
};
```

Для некоторых архитектур используется union: не выполняйте назначение одновременно sa_handler и sa_sigaction.

Поле sa_restorer не предназначено для использования в приложении (в POSIX sa_restorer не определёно). Предназначение этого поля немного описано в sigreturn(2).

sa_handler указывает действие, которое должно быть связано с signum; может принимать значение SIG_DFL в качестве действия по умолчанию, SIG_IGN, чтобы игнорировать этот сигнал, или принимать указатель на функцию управления сигналом. Данная функция получает номер сигнала в качестве своего единственного аргумента.

Если в sa_flags указан SA_SIGINFO, то sa_sigaction (вместо sa_handler) задаёт функцию обработки сигнала signum. Эта функция имеет три параметра, которые описаны ниже.

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

В flag указывается набор флагов, которые изменяют поведение сигнала. Он формируется побитовым ИЛИ из следующих флагов:

SA_NOCLDSTOP

Если значение signum равно SIGCHLD, то уведомление об остановке дочернего процесса (т.е., в тех случаях, когда дочерний процесс получает сигнал SIGSTOP, SIGTSTP, SIGTTIN или SIGTTOU) или возобновлении работы (т.е., когда дочерний процесс получает SIGCONT) не будет получено (см. wait(2)). Этот флаг имеет значение только когда установлен обработчик SIGCHLD.

SA_NOCLDWAIT (начиная с Linux 2.6)

Если значение signum равно SIGCHLD, то дочерние процессы не будут переводиться в состояние зомби при завершении. Смотрите также waitpid(2). Этот флаг имеет значение только когда установлен обработчик SIGCHLD или когда обработчик сигнала установлен в SIG_DFL.

Если флаг SA_NOCLDWAIT не задан при установке обработчика SIGCHLD, то по POSIX.1 остаётся неопределённым, будет ли генерироваться сигнал SIGCHLD при завершении дочернего процесса. В Linux сигнал SIGCHLD в этом случае генерируется; в некоторых других реализациях это не делается.

SA_NODEFER

Не препятствовать получению сигнала при его обработке обработчиком сигнала. Этот флаг имеет значение только когда установлен обработчик. Флаг SA_NOMASK является устаревшим синонимом данного флага.

SA_ONSTACK

Вызывать обработчик сигнала в дополнительном стеке сигналов, предоставленном sigaltstack(2). Если дополнительный стек недоступен, то будет использован стек по умолчанию. Этот флаг имеет значение только когда установлен обработчик.

SA_RESETHAND

Восстановить поведение сигнала в значение по умолчанию после входа в обработчик сигнала. Этот флаг имеет значение только когда установлен обработчик. Флаг SA_ONESHOT является устаревшим синонимом данного флага.

SA_RESTART

Обеспечивать поведение совместимое с семантикой сигналов BSD, позволяя некоторым системным вызовам перезапускаться в то время, как идет обработка сигналов. Этот флаг имеет значение только когда установлен обработчик. О перезапуске системных вызовов смотрите в signal(7).

SA_RESTORER

Не предназначен для приложений. Данный флаг используется в библиотеках C для указания на то, что поле sa_restorer содержит адрес «прыжковым мостиком в сигнал" (signal trampoline). Подробней смотрите в sigreturn(2).

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

Обработчик сигнала требует трёх аргументов, а не одного. В этом случае надо использовать параметр sa_sigaction вместо sa_handler. Этот флаг имеет значение только когда установлен обработчик.

### Аргумент siginfo_t обработчика SA_SIGINFO.
Если в act.sa_flags указан флаг SA_SIGINFO, то адрес обработчика сигнала передаётся в поле act.sa_sigaction. Этот обработчик имеет три аргумента:

```
void
handler(int sig, siginfo_t *info, void *ucontext)
{

    ...
}
```

Три параметра:

sig

Номер сигнала, который привёл к вызову обработчика.

info

Указатель на siginfo_t — структуру, содержащую дополнительную информацию о сигнале, описана далее.

ucontext

Указатель на структуру ucontext_t, приведённую к void " *. Эта структура содержит информацию о контексте сигнала, которая была сохранена ядром в стеке пользовательского пространства; подробности описаны в sigreturn(2). Подробней о структуре ucontext_t смотрите в getcontext(3). Вообще, функция-обработчик не использует третий аргумент.

Тип данных siginfo_t представляется структурой со следующими полями:

```
siginfo_t {

    int      si_signo;     /* Номер сигнала */

    int      si_errno;     /* Значение errno */

    int      si_code;      /* Код сигнала */

    int      si_trapno;    /* Номер ловушки, которую вызвал

                              аппаратный сигнал

                              (не используется на большинстве

                              архитектур) */

    pid_t    si_pid;       /* ID процесса, пославшего сигнал */

    uid_t    si_uid;       /* ID реального пользователя процесса,

                              пославшего сигнал */

    int      si_status;    /* Выходное значение или номер сигнала */

    clock_t  si_utime;     /* Использованное пользовательское время */

    clock_t  si_stime;     /* Использованное системное время */

    sigval_t si_value;     /* Значение сигнала */

    int      si_int;       /* Сигнал POSIX.1b */

    void    *si_ptr;       /* Сигнал POSIX.1b */

    int      si_overrun;   /* Счётчик переполнения таймера;

                              таймеры POSIX.1b */

    int      si_timerid;   /* ID таймера; таймеры POSIX.1b */

    void    *si_addr;      /* Адрес памяти, приводящий к ошибке */

    long     si_band;      /* Внутреннее событие (был int в

                              glibc 2.3.2 и более ранних) */

    int      si_fd;        /* Файловый дескриптор */

    short    si_addr_lsb;  /* Наименее значимый бит адреса

                              (начиная с Linux 2.6.32) */

    void    *si_lower;     /* Нижняя граница при нарушении адреса

                              (начиная с Linux 3.19) */

    void    *si_upper;     /* Верхняя граница при нарушении адреса

                              (начиная с Linux 3.19) */

    int      si_pkey;      /* Ключа защиты в PTE, который привёл

                              к ошибке (начиная с Linux 4.6) */

    void    *si_call_addr; /* Адрес инструкции системного вызова

                              (начиная с Linux 3.5) */

    int      si_syscall;   /* Количество попыток системного вызова

                              (начиная с Linux 3.5) */

    unsigned int si_arch;  /* Архитектура пытавшегося системного вызова

                              (начиная с Linux 3.5) */
}
```

Поля si_signo, si_errno и si_code определены для всех сигналов. (si_errno обычно не используется в Linux.) Оставшаяся часть структуры может представлять собой объединение, поэтому нужно читать только те поля, которые имеют смысл для заданного сигнала:

- Для сигналов, посылаемых kill(3) и sigqueue(3), заполняются si_pid и si_uid. Также для сигналов, посылаемых sigqueue(3), заполняются si_int и si_ptr значениями, задаваемыми отправителем сигнала; подробней смотрите sigqueue(3).

- Для сигналов, посылаемых таймерами POSIX.1b (начиная с Linux 2.6), заполняются si_overrun и si_timerid. Поле si_timerid является внутренним идентификатором, который используется ядром для различения таймеров; это не идентификатор таймера, возвращаемого timer_create(2). Поле si_overrun отражает счётчик превышения таймера; эту же информацию можно получить с помощью вызова timer_getoverrun(2). Эти поля являются нестандартным расширением Linux.

- Для сигналов, посылаемых уведомлением очереди сообщений (см. описание SIGEV_SIGNAL в mq_notify(3)), заполняются si_int/si_ptr значением sigev_value, предоставляемым mq_notify(3); si_pid — значением идентификатора процесса, отправившего сообщение; si_uid — значением реального идентификатора пользователя, отправившего сообщение.

- Для SIGCHLD заполняются si_pid, si_uid, si_status, si_utime и si_stime, предоставляющие информацию о потомке. В поле si_pid указывается идентификатор процесса потомка; в si_uid — реальный пользовательский идентификатор потомка. В поле si_status содержится код завершения потомка (если si_code равно CLD_EXITED) или номер сигнала, который вызвал изменение состояния процесса. Поля si_utime и si_stime содержат системное и пользовательское время ЦП, затраченное процессом-потомком; эти поля не содержат время, использованное на ожидание потомков (в отличие от getrusage(2) и times(2)). В ядрах до версии 2.6 и начиная с 2.6.27 эти поля содержат время ЦП в единицах sysconf(_SC_CLK_TCK). В ядрах 2.6 до 2.6.27 ошибочно считалось, что эти поля содержат время в единицах (настраиваемых) системных мигов (jiffy) (смотрите time(7)).

- При SIGILL, SIGFPE, SIGSEGV, SIGBUS и SIGTRAP заполняется si_addr адресом ошибки. На некоторых архитектурах для эти сигналов также заполняется поле si_trapno.

Некоторые отдельные варианты SIGBUS, в частности BUS_MCEERR_AO и BUS_MCEERR_AR, также заполняют si_addr_lsb. Это поле указывает на наименее значимый бит сообщаемого адреса и поэтому показывает размер повреждения. Например, если была повреждена страница целиком, то si_addr_lsb содержит log2(sysconf(_SC_PAGESIZE)). Когда доставляется SIGTRAP в ответ на событие ptrace(2) (PTRACE_EVENT_foo), то si_addr не заполняется, но заполняются si_pid и si_uid соответствующими ID процесса и пользователя, ответственного за получение трапа. В случае seccomp(2), трассируемый будет показан как получающий событие. BUS_MCERR_* и si_addr_lsb являются расширениями Linux.

Для отдельного варианта SEGV_BNDERR из SIGSEGV заполняются si_lower и si_upper.

Для отдельного варианта SEGV_PKUERR из SIGSEGV заполняется si_pkey.

- Для SIGIO/SIGPOLL (синонимы в Linux) заполняются si_band и si_fd. Событие si_band представляет собой битовую маску, содержащую те же значения, которые заполняются в поле revents вызовом poll(2). Поле si_fd содержит файловый дескриптор, для которого произошло событие ввода-вывода; дополнительную информацию смотрите в описании F_SETSIG на странице fcntl(2).

- Для SIGSYS, генерируемого (начиная с Linux 3.5), когда фильтр seccomp возвращает SECCOMP_RET_TRAP, заполняются si_call_addr, si_syscall, si_arch, si_errno и другие поля, как описывается в seccomp(2).

### Поле si_code
В поле si_code аргумента siginfo_t, передаваемого обработчику сигналов SA_SIGINFO содержится значение (не маска битов), определяющее причину отправки сигнала. При событии ptrace(2) в si_code будет содержаться SIGTRAP и событие ptrace в старшем байте:

```
(SIGTRAP | PTRACE_EVENT_foo << 8).
```

Не события не ptrace(2) значения, которые могут появиться в si_code, описаны в конце этого раздела. Начиная с glibc 2.20, определения большинства этих символов доступны из <signal.h> при определении макросов тестирования свойств (до включения какого-либо заголовочного файла) следующим образом:

- _XOPEN_SOURCE со значением 500 или больше;

- _XOPEN_SOURCE и _XOPEN_SOURCE_EXTENDED; или

- _POSIX_C_SOURCE со значением 200809L или больше.

Определения символов констант TRAP_* предоставляются только в первых двух случаях. До glibc 2.20 для получения этих символов макросы тестирования свойств были не нужны.

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

SI_USER

kill(2).

SI_KERNEL

посылается ядром

SI_QUEUE

sigqueue(3).

SI_TIMER

таймер POSIX истёк.

SI_MESGQ (начиная с Linux 2.6.6)

изменилось состояние очереди сообщений POSIX; см. mq_notify(3).

SI_ASYNCIO

AIO завершён.

SI_SIGIO

Queued SIGIO (только в ядрах до Linux 2.2; начиная с Linux 2.4 SIGIO/SIGPOLL заполняют si_code как описано выше).

SI_TKILL (начиная с Linux 2.4.19)

tkill(2) или tgkill(2).

Следующие значения могут присутствовать в si_code для сигнала SIGILL:

ILL_ILLOPC

Некорректный код инструкции.

ILL_ILLOPN

Некорректный операнд.

ILL_ILLADR

Некорректный режим адресации.

ILL_ILLTRP

Некорректная ловушка.

ILL_PRVOPC

Привилегированный код инструкции.

ILL_PRVREG

Привилегированный регистр.

ILL_COPROC

Ошибка сопроцессора.

ILL_BADSTK

Внутренняя ошибка стека.

Следующие значения могут присутствовать в si_code для сигнала SIGFPE:

FPE_INTDIV

Деление на ноль при работе с целыми числами.

FPE_INTOVF

Переполнение при работе с целыми числами.

FPE_FLTDIV

Деление на ноль при работе с числами с плавающей запятой.

FPE_FLTOVF

Переполнение при работе с числами с плавающей запятой.

FPE_FLTUND

Нехватка значения при работе с числами с плавающей запятой.

FPE_FLTRES

Неточный результат при работе с числами с плавающей запятой.

FPE_FLTINV

Неправильная операция при работе с числами с плавающей запятой.

FPE_FLTSUB

Индекс вне разрешенных пределов при работе с числами с плавающей запятой.

Следующие значения могут присутствовать в si_code для сигнала SIGSEGV:

SEGV_MAPERR

Адрес не соответствует объекту.

SEGV_ACCERR

Некорректные права на отображённый объект.

SEGV_BNDERR (начиная с Linux 3.19)

Ошибка проверки границ адреса.

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

Доступ запрещён битами защиты памяти. Смотрите pkeys(7). Ключ защиты, применяемый при таком доступе, доступен в si_pkey.

Следующие значения могут присутствовать в si_code для сигнала SIGBUS:

BUS_ADRALN

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

BUS_ADRERR

Несуществующий физический адрес.

BUS_OBJERR

Аппаратная ошибка, специфичная для объекта.

BUS_MCEERR_AR (начиная с Linux 2.6.32)

машинной проверкой устранена аппаратная ошибка памяти; требуется действие

BUS_MCEERR_AO (начиная с Linux 2.6.32)

в процессе обнаружена аппаратная ошибка памяти, но не устранена; действие не обязательно

Следующие значения могут присутствовать в si_code для сигнала SIGTRAP:

TRAP_BRKPT

Точка останова процесса.

TRAP_TRACE

Ловушка отладки процесса.

TRAP_BRANCH (начиная с Linux 2.4, только для IA64))

Процесс пойман в ветвь ловушки.

TRAP_HWBKPT (начиная с Linux 2.4, только для IA64))

Аппаратная точка прерывания/слежения.

Следующие значения могут присутствовать в si_code для сигнала SIGCHLD:

CLD_EXITED

Дочерний процесс завершил работу.

CLD_KILLED

Работа дочернего процесса была прервана.

CLD_DUMPED

Дочерний процесс завершился некорректно.

CLD_TRAPPED

Сработала ловушка в отлаживаемом дочернем процессе.

CLD_STOPPED

Дочерний процесс остановлен.

CLD_CONTINUED (начиная с Linux 2.6.9)

Остановленный дочерний процесс продолжил работу.

Следующие значения могут присутствовать в si_code для сигнала SIGIO/SIGPOLL:

POLL_IN

Есть входные данные.

POLL_OUT

Освободились выходные буферы.

POLL_MSG

Есть входное сообщение.

POLL_ERR

Ошибка ввода-вывода.

POLL_PRI

Есть входные данные высокого приоритета.

POLL_HUP

Устройство отключено.

Следующее значение может присутствовать в si_code для сигнала SIGSYS:

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

Возникает по правилу фильтрации seccomp(2).

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

## ОШИБКИ
EFAULT

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

EINVAL

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

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

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

В соответствии с POSIX поведение процесса после игнорирования сигнала SIGFPE, SIGILL или SIGSEGV не определено, если эти сигналы не были посланы при помощи функций kill(2) или raise(3). Деление целого числа на ноль имеет непредсказуемый результат. В некоторых архитектурах это приводит к появлению сигнала SIGFPE. (Также, деление самого большого по модулю отрицательного числа на -1 тоже может приводить к SIGFPE.) Игнорирование этого сигнала может привести к появлению бесконечного цикла.

POSIX.1-1990 запрещает установку действия для сигнала SIGCHLD в SIG_IGN. В POSIX.1-2001 и новых версиях стандарта допускается такая возможность, поэтому игнорирование SIGCHLD можно использовать для недопущения создания зомби (смотрите wait(2)). Тем не менее, поведение BSD и System V по игнорированию SIGCHLD различается, поэтому есть только один переносимый способ убедиться, что завершившийся потомок не стал зомби — поймать сигнал SIGCHLD и выполнить wait(2) или подобный вызов.

В POSIX.1-1990 указан только SA_NOCLDSTOP. В POSIX.1-2001 добавлены SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART и SA_SIGINFO. Использование в приложениях последних значений в sa_flags может оказаться сложнее перенести на старые реализации UNIX.

Флаг SA_RESETHAND совместим с одноимённым флагом из SVr4.

Флаг SA_NODEFER совместим с одноименным флагом SVr4 в ядре версии 1.3.9 и более поздних. В старых выпусках ядра Linux позволяли принимать и обрабатывать любые сигналы, а не только те, обработка которых уже задана (на деле это приводит к игнорированию установок sa_mask).

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

Невозможно заблокировать сигналы SIGKILL или SIGSTOP (указав их в sa_mask). Попытки это сделать будут просто игнорироваться.

Подробная информация о работе с наборами сигналов есть на странице sigsetops(3).

Список функций безопасных асинхронных сигналов, которые можно не опасаясь вызывать из обработчика сигналов, смотрите в signal-safety(7).

### Отличия между библиотекой C и ядром
Обёрточная функция glibc для sigaction() выдаёт ошибку (EINVAL) при попытках изменить обработчики двух сигналов реального времени, которые используются внутри реализации NPTL. Подробности смотрите в nptl(7).

На архитектурах, где переход от сигнала (signal trampoline) располагается в библиотеке C, обёрточная функция glibc для sigaction() помещает адрес кода перехода в поле act.sa_restorer и изменяет флаг SA_RESTORER в поле act.sa_flags. Смотрите sigreturn(2).

Первоначально, системный вызов Linux назывался sigaction(). Однако, с добавлением сигналов реального времени в Linux 2.2, 32-битный аргумент sigset_t неизменяемого размера, поддерживаемый этим системным вызовом, не мог больше использоваться. В результате был добавлен новый системный вызов rt_sigaction() с увеличенным типом sigset_t. У нового системного вызова появился четвёртый аргумент, size_t sigsetsize, в котором указывается размер (в байтах) наборов сигналов act.sa_mask и oldact.sa_mask. В настоящее время значение этого аргумента должно быть равно sizeof(sigset_t) (иначе возникает ошибка EINVAL). Обёрточная функция glibc sigaction() скрывает это и вызывает rt_sigaction(), если он есть в ядре.

### Недокументированное
До появления SA_SIGINFO также было возможно получить дополнительную информацию о сигнале. Для этого в обработчике сигнала sa_handler заполняется второй параметр типа struct sigcontext, который повторяет структуру, передаваемую в поле uc_mcontext структуры ucontext, которая передаётся (через указатель) в третьем аргументе обработчика sa_sigaction. Смотрите соответствующий исходный код ядра Linux. В настоящее время этот механизм устарел.

## ДЕФЕКТЫ
В ядрах по версию 2.6.13 включительно, указание SA_NODEFER в sa_flags предотвращает доставку сигнала не только из маскируемого при выполнении обработчика, но также сигналов, указанных в sa_mask. Этот дефект исправлен в ядре 2.6.14.

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

## СМОТРИТЕ ТАКЖЕ
kill(1), kill(2), pause(2), restart_syscall(2), seccomp(2) sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigreturn(2), sigsuspend(2), wait(2), killpg(3), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), core(5), signal(7)


sigaltstack

title: sigaltstack(2)

text:
# sigaltstack(2)

## ИМЯ
sigaltstack - считывает или устанавливает расположение стека сигналов

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

int sigaltstack(const stack_t *ss, stack_t *old_ss);

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

sigaltstack():

_XOPEN_SOURCE >= 500

|| /* начиная с glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

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

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

Обычный порядок действий для использования альтернативного стека сигналов:

1.

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

2.

Вызвать sigaltstack() для информирования системы о существовании и расположении альтернативного стека сигналов.

3.

При установке обработчика сигналов с помощью sigaction(2) (флагом SA_ONSTACK) сообщить системе, что обработчик сигналов должен выполняться с альтернативным стеком сигналов.

Аргумент ss используется для указания нового альтернативного стека сигналов, а аргумент old_ss используется для получения информации об установленном в данный момент стеке сигналов. Если интересует какая-то одна из этих задач, то другой аргумент указывается как NULL.

Тип stack_t, используемый для аргументов этой функции, определён следующим образом:

```
typedef struct {

    void  *ss_sp;     /* базовый адрес стека */

    int    ss_flags;  /* флаги */

    size_t ss_size;   /* количество байт в стеке */
} stack_t;
```

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

ss.ss_flags

В этом поле содержится 0 или следующий флаг:

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

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

Этот флаг был добавлен для безопасного переключения из обработчика сигналов с помощью swapcontext(3). Без этого флага следующий обрабатываемый сигнал повредит состояние обработчика сигналов, в который выполняется переключение (switched-away). В ядрах без поддержки этого флага вызов sigaltstack() завершается ошибкой EINVAL, если этот флаг указан.

ss.ss_sp

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

ss.ss_size

В этом поле задаётся размер стека. Для определения альтернативного стека сигналов достаточного размера можно использовать константу SIGSTKSZ, а для выделения стека минимального размера можно указать константу MINSIGSTKSZ.

Для отключения существующего стека, укажите в ss.ss_flags значение SS_DISABLE. В этом случае ядро игнорирует все флаги в ss.ss_flags и остальные поля в ss.

Если old_ss не равно NULL, то в нём возвращается информация об альтернативном стеке сигналов, который использовался до этого вызова sigaltstack(). В полях old_ss.ss_sp и old_ss.ss_size возвращаются начальный адрес и размер стека. В old_ss.ss_flags может быть возвращено одно из следующих значений:

SS_ONSTACK

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

SS_DISABLE

В данный момент альтернативный стек сигналов выключен.

Также это значение возвращается, если процесс уже выполняется с альтернативным стеком сигналов, установленным с помощью флага SS_AUTODISARM. В этом случае с помощью swapcontext(3) можно безопасно переключаться в другой обработчик сигналов. Также возможно установить другой альтернативный стек сигналов с помощью последующего вызова sigaltstack().

SS_AUTODISARM

Альтернативный стек сигналов был помечен к автоматической очистке (autodisarmed), как описывалось ранее.

Если присвоить ss значение NULL,а old_ss — не NULL, то можно получить текущие настройки альтернативного стека сигналов без его изменения.

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

## ОШИБКИ
EFAULT

Значение ss или old_ss не равно NULL и указывает за пределы адресного пространства процесса.

EINVAL

Значение ss не равно NULL и в поле ss_flags содержится некорректный флаг.

ENOMEM

Указанный размер нового альтернативного стека сигналов ss.ss_size меньше MINSIGSTKSZ.

EPERM

Была попытка изменить альтернативный стек сигналов при его активности (т. е. текущий альтернативный стек сигналов уже задействован при выполнении процесса).

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

sigaltstack()

Безвредность в нитях

MT-Safe

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

Флаг SS_AUTODISARM является расширением Linux.

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

Назначение альтернативного стека сигналов полезно, если ожидается, что процесс может задействовать весь свой обычный стек. Это может случиться, например, когда стек становится настолько большим, что он встречается с растущей в вверх «кучей», или достигает ограничения, заданного вызовом setrlimit(RLIMIT_STACK, &rlim). Если стандартный стек закончился, то ядро посылает процессу сигнал SIGSEGV. В этих условиях единственным способом поймать сигнал будет задействование альтернативного стека сигналов.

На большинстве аппаратных архитектур, поддерживаемых Linux, стеки растут сверху вниз. Вызов sigaltstack() автоматически учтёт направление роста стека.

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

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

Вызов sigaltstack() заменяет устаревший вызов sigstack(). Для обратной совместимости в glibc также есть функция sigstack(). Во всех новых приложениях нужно использовать sigaltstack().

### История
Системный вызов sigstack() появился в 4.2BSD. В нём использовалась слегка другая структура, и его главным недостатком было то, что вызывающий должен был учитывать направления роста стека.

## ПРИМЕР
В следующем сегменте кода показано использование sigaltstack() (и sigaction(2)) для установки альтернативного стека сигналов, который используется обработчиком для сигнала SIGSEGV:

```
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);
if (ss.ss_sp == NULL) {

    perror("malloc");

    exit(EXIT_FAILURE);
}
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) {

    perror("sigaltstack");

    exit(EXIT_FAILURE);
}
sa.sa_flags = SA_ONSTACK;
sa.sa_handler = handler();      /* адрес обработчика сигналов */
sigemptyset(&sa.sa_mask);
if (sigaction(SIGSEGV, &sa, NULL) == -1) {

    perror("sigaction");

    exit(EXIT_FAILURE);
}
```

## ДЕФЕКТЫ
В Linux 2.2 и старее в ss.sa_flags можно указывать только флаг SS_DISABLE. В версиях до ядра Linux 2.4 разрешалось sigaltstack() допускать ss.ss_flags==SS_ONSTACK с тем же смыслом как ss.ss_flags==0 (т. е., при включении SS_ONSTACK в ss.ss_flags ни к чему не приводило). В других реализациях и согласно POSIX.1 флаг SS_ONSTACK появляется в old_ss.ss_flags только как флаг результата. В Linux его не нужно даже указывать в ss.ss_flags, иначе это снизит переносимость, так как некоторые системы выдают ошибку, если в ss.ss_flags указан SS_ONSTACK.

## СМОТРИТЕ ТАКЖЕ
execve(2), setrlimit(2), sigaction(2), siglongjmp(3), sigsetjmp(3), signal(7)


signal

title: signal(2)

summary: работа с сигналами ANSI C

text:
# signal(2)

## ИМЯ
signal - работа с сигналами ANSI C

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

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

## ОПИСАНИЕ
Работа вызова signal() различается в различных версиях UNIX, и такая же ситуация исторически сложилась и в различных версиях Linux. Не используйте его: используйте вместо него sigaction(2). Смотрите абзац Переносимость далее.

Вызов signal() устанавливает обработчик сигнала с номером signum в соответствии с параметром handler, который может быть равен SIG_IGN, SIG_DFL или адресу функции пользователя ("обработчик сигнала").

Если сигнал signum доставляется процессу, то происходит следующее:

*

Если значение обработчика равно SIG_IGN, то сигнал игнорируется.

*

Если значение обработчика равно SIG_DFL, то выполняется стандартное действие, связанное с сигналом (см. signal(7)).

*

Если значение обработчика равно адресу функции, то сначала значение обработчика сбрасывается в SIG_DFL или сигнал блокируется (см. Переносимость далее), а затем вызывается функция handler с аргументом signum. Если вызов обработчика приводит к блокировке сигнала, то сигнал разблокируется после возврата из обработчика.

Сигналы SIGKILL и SIGSTOP не могут быть перехвачены или игнорированы.

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

## ОШИБКИ
EINVAL

Неверное значение signum.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, C89, C99.

## ЗАМЕЧАНИЯ
Результат работы signal() в многонитевом процессе не регламентирован.

В соответствии с POSIX поведение процесса после игнорирования сигнала SIGFPE, SIGILL или SIGSEGV не определено, если эти сигналы не были посланы при помощи функций kill(2) или raise(3). Деление целого числа на ноль имеет непредсказуемый результат. В некоторых архитектурах это приводит к появлению сигнала SIGFPE. (Также, деление самого большого по модулю отрицательного числа на -1 тоже может приводить к SIGFPE.) Игнорирование этого сигнала может привести к появлению бесконечного цикла.

О том, что происходит когда обработчик SIGCHLD приравнивается к SIG_IGN, смотрите на странице sigaction(2).

Список асинхронных функций работы с сигналами, которые можно безопасно вызывать из обработчика сигналов, смотрите на странице signal-safety(7).

Используемый sighandler_t является расширением GNU, который определён, если существует макрос _GNU_SOURCE; в glibc также есть sig_t, если определён _BSD_SOURCE (glibc 2.19 и старее) или _DEFAULT_SOURCE (glibc 2.19 и новее). Без использования этого типа объявление signal() сложнее читать:

```
void ( *signal(int signum, void (*handler)(int)) ) (int);
```

### Переносимость
Вызов signal() считается переносимым, если обработчик сигнала равен SIG_DFL или SIG_IGN. Семантика при использовании signal() для установки обработчика сигнала отличается в различных системах (и в POSIX.1 явно разрешена такая перемена); не используйте данный вызов для этой цели.

В POSIX.1 проблема переносимости решена введением sigaction(2), который предоставляет явное управление семантикой при вызове обработчика сигнала; используйте этот интерфейс вместо signal().

В первых системах UNIX, когда обработчик, установленный с помощью signal(), вызывался по получению сигнала, обработчик сигнала был бы сброшен в SIG_DFL, и система не заблокировала бы доставку этого сигнала в последующие экземпляры.

```
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
```

System V также предоставляет эту семантику signal(). Это плохо, так как сигнал может быть доставлен снова, до того как обработчик сможет получить шанс его переустановить. Кроме того, скоростные доставки одного сигнала приводили к рекурсивным вызовам обработчика.

В BSD улучшили эту ситуацию, но, к сожалению, изменили существующую семантику для установки обработчика с помощью signal(). В BSD при вызове обработчика сигнала обработчик сигнала не сбрасывается, и дальнейшие экземпляры сигнала блокируются и не доставляются пока выполняется обработчик. Кроме этого, некоторые блокирующие системные вызовы автоматически перезапускаются при прерывании обработчиком сигнала (смотрите signal(7)). Семантика BSD эквивалентна вызову sigaction(2) со следующими флагами:

```
    sa.sa_flags = SA_RESTART;
```

Ситуация в Linux:

- Системный вызов ядра signal() предоставляет семантику System V.

- По умолчанию в glibc 2 и новее обёрточная функция signal() не вызывает системный вызов ядра. Вместо этого она вызывает sigaction(2) с флагами, которые активируют семантику BSD. Такое поведение по умолчанию устанавливается, если определён макрос тестирования свойств _BSD_SOURCE в glibc 2.19 и старее или _DEFAULT_SOURCE в glibc 2.19 и новее (по умолчанию эти макросы определены; подробности смотрите в feature_test_macros(7)) . Если этот макрос тестирования свойств не определён, signal() работает согласно семантики System V.

## СМОТРИТЕ ТАКЖЕ
kill(1), alarm(2), kill(2), pause(2), sigaction(2), signalfd(2), sigpending(2), sigprocmask(2), sigsuspend(2), bsd_signal(3), killpg(3), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), sysv_signal(3), signal(7)