getrlimit(2) | System Calls Manual | getrlimit(2) |
getrlimit, setrlimit, prlimit - считывает/устанавливает ограничения использования ресурсов
Standard C library (libc, -lc)
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim);
int prlimit(pid_t pid, int resource, const struct rlimit *_Nullable new_limit, struct rlimit *_Nullable old_limit);
prlimit():
_GNU_SOURCE
Системные вызовы getrlimit() и setrlimit() получают и устанавливают ограничения использования ресурсов. Каждому ресурсу назначается мягкое и жёсткое ограничение, определяемое структурой rlimit:
struct rlimit {
rlim_t rlim_cur; /* мягкое ограничение */
rlim_t rlim_max; /* жёсткое ограничение (максимум для rlim_cur) */ };
Мягким ограничением является значение, принудительно устанавливаемое ядром для соответствующего ресурса. Жёсткое ограничение работает как максимальное значение для мягкого ограничения: непривилегированные процессы могут определять только свои мягкие ограничения в диапазоне от 0 до жёсткого ограничения, то есть однозначно меньше жёсткого ограничения. Привилегированные процессы (в Linux: имеющие мандат CAP_SYS_RESOURCE в начальном пространстве имён пользователя) могут устанавливать произвольные значения в любых пределах.
Значение RLIM_INFINITY означает отсутствие ограничений для ресурса (в структуре, возвращаемой getrlimit() и в структуре, передаваемой в setrlimit()).
Значение resource должно быть одним из:
bytes = attr.mq_maxmsg * sizeof(struct msg_msg) +
MIN(attr.mq_maxmsg, MQ_PRIO_MAX) *
sizeof(struct posix_msg_tree_node)+
/* издержки */
attr.mq_maxmsg * attr.mq_msgsize;
/* данные из сообщения */
bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
/* издержки */
attr.mq_maxmsg * attr.mq_msgsize;
/* данные из сообщения */
Системный вызов prlimit(), который есть только в Linux объединяет и расширяет функции setrlimit() и getrlimit(). Он может использоваться для задания и получения ограничений ресурсов произвольного процесса.
Аргумент resource имеет тот же смысл что и в setrlimit() и getrlimit().
Если значение аргумента new_limit не равно NULL, то структура rlimit, на которую он указывает, используется для задания новых значений мягкий и жёстких ограничений для resource. Если значение аргумента old_limit не равно NULL, то успешный вызов prlimit() помещает текущие значения мягких и жёстких ограничений для resource в структуру rlimit, на которую указывает old_limit.
В аргументе pid задаётся идентификатор процесса с которым работает вызов. Если pid равно 0, то вызов применяется к вызывающему процессу. Для установки и получения ресурсов не своего процесса, вызывающий должен иметь мандат CAP_SYS_RESOURCE в пользовательском пространстве имён процесса, ограничения ресурсов которого изменяются или реальный, эффективный и сохранённый идентификатор пользователя процесса назначения должен совпадать с реальным идентификатором пользователя вызывающего и реальный, эффективный и сохранённый идентификатор группы процесса назначения должны совпадать с реальным идентификатором группы вызывающего.
On success, these system calls return 0. On error, -1 is returned, and errno is set to indicate the error.
Системный вызов prlimit() появился в Linux 2.6.36. Поддержка в glibc доступна начиная с версии 2.13.
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
getrlimit(), setrlimit(), prlimit() | Безвредность в нитях | MT-Safe |
getrlimit(), setrlimit(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
prlimit(): только в Linux.
Ограничение RLIMIT_MEMLOCK и RLIMIT_NPROC появились из BSD и их нет в POSIX.1; они есть в BSD и Linux, но реализации несколько различны. Ограничение RLIMIT_RSS появилось из BSD и его нет в POSIX.1; тем не менее оно есть в большинстве реализаций. Ограничения RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_RTPRIO, RLIMIT_RTTIME и RLIMIT_SIGPENDING есть только в Linux.
Дочерний процесс, созданный fork(2), наследует ограничения ресурсов родителя. Ограничения ресурсов сохраняются при execve(2).
Атрибуты ограничения ресурсов есть у каждого процесса, они являются общими для всех нитей процесса.
Уменьшение мягкого ограничения ресурса ниже текущего потребления процесса будет выполнено (но в дальнейшем процесс не сможет увеличить потребление ресурса).
Ограничения ресурсов интерпретатора командной строки можно устанавливать с помощью встроенной команды ulimit (limit в csh(1)). Ограничения ресурсов интерпретатора наследуются дочерними процессами, которые он создаёт при выполнении команд.
Начиная с Linux 2.6.24, ограничения ресурсов любого процесса можно узнать с помощью /proc/pid/limits; смотрите proc(5).
В старых системах была функция vlimit() с подобным setrlimit() назначением. Для обратной совместимости в glibc также есть функция vlimit(). Во всех новых приложениях должен быть использован setrlimit().
Since glibc 2.13, the glibc getrlimit() and setrlimit() wrapper functions no longer invoke the corresponding system calls, but instead employ prlimit(), for the reasons described in BUGS.
Обёрточная функция в glibc называется prlimit(); нижележащий системный вызов называется prlimit64().
In older Linux kernels, the SIGXCPU and SIGKILL signals delivered when a process encountered the soft and hard RLIMIT_CPU limits were delivered one (CPU) second later than they should have been. This was fixed in Linux 2.6.8.
In Linux 2.6.x kernels before Linux 2.6.17, a RLIMIT_CPU limit of 0 is wrongly treated as "no limit" (like RLIM_INFINITY). Since Linux 2.6.17, setting a limit of 0 does have an effect, but is actually treated as a limit of 1 second.
A kernel bug means that RLIMIT_RTPRIO does not work in Linux 2.6.12; the problem is fixed in Linux 2.6.13.
In Linux 2.6.12, there was an off-by-one mismatch between the priority ranges returned by getpriority(2) and RLIMIT_NICE. This had the effect that the actual ceiling for the nice value was calculated as 19 - rlim_cur. This was fixed in Linux 2.6.13.
Начиная с Linux 2.6.12, если процесс имеет мягкое ограничение RLIMIT_CPU и установлен обработчик для SIGXCPU, то, помимо вызова обработчика сигнала, ядро увеличивает мягкое ограничение на одну секунду. Такое поведение повторяется, если процесс продолжает потреблять процессорное время, и происходит это до тех пор, пока не будет достигнуто жёсткое ограничение, после чего процесс будет завершён. В других реализациях мягкое ограничение RLIMIT_CPU не меняется подобным образом, и поведение Linux, вероятно, нестандартно; переносимые приложения не должны полагаться на данную специфику Linux. Ограничение Linux RLIMIT_RTTIME демонстрирует такое же поведение, при исчерпании мягкого ограничения.
Kernels before Linux 2.4.22 did not diagnose the error EINVAL for setrlimit() when rlim->rlim_cur was greater than rlim->rlim_max.
В целях совместимости, Linux не возвращает ошибку при неудачной попытке назначения RLIMIT_CPU.
The glibc getrlimit() and setrlimit() wrapper functions use a 64-bit rlim_t data type, even on 32-bit platforms. However, the rlim_t data type used in the getrlimit() and setrlimit() system calls is a (32-bit) unsigned long. Furthermore, in Linux, the kernel represents resource limits on 32-bit platforms as unsigned long. However, a 32-bit data type is not wide enough. The most pertinent limit here is RLIMIT_FSIZE, which specifies the maximum size to which a file can grow: to be useful, this limit must be represented using a type that is as wide as the type used to represent file offsets—that is, as wide as a 64-bit off_t (assuming a program compiled with _FILE_OFFSET_BITS=64).
Если программа пытается задать ограничение ресурса значением, большим чем можно представить 32-битным unsigned long, то, чтобы обойти это ограничение ядра, обёрточная функция glibc setrlimit() просто преобразует значение ограничения в RLIM_INFINITY. Иначе говоря, запрашиваемое назначение ограничения ресурса просто игнорируется.
Since glibc 2.13, glibc works around the limitations of the getrlimit() and setrlimit() system calls by implementing setrlimit() and getrlimit() as wrapper functions that call prlimit().
Представленная ниже программа показывает использование prlimit().
#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include <err.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/resource.h> #include <time.h> int main(int argc, char *argv[]) {
pid_t pid;
struct rlimit old, new;
struct rlimit *newp;
if (!(argc == 2 || argc == 4)) {
fprintf(stderr, "Использование: %s <pid> [<новое-мягкое-ограничение> "
"<новое-жёсткое-ограничение>]\n", argv[0]);
exit(EXIT_FAILURE);
}
pid = atoi(argv[1]); /* PID процесса назначения */
newp = NULL;
if (argc == 4) {
new.rlim_cur = atoi(argv[2]);
new.rlim_max = atoi(argv[3]);
newp = &new;
}
/* Установить ограничение на время ЦП процесса назначения;
получить и показать предыдущее ограничение */
if (prlimit(pid, RLIMIT_CPU, newp, &old) == -1)
err(EXIT_FAILURE, "prlimit-1");
printf("Previous limits: soft=%jd; hard=%jd\n",
(intmax_t) old.rlim_cur, (intmax_t) old.rlim_max);
/* Получить и показать новое ограничение времени ЦП */
if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1)
err(EXIT_FAILURE, "prlimit-2");
printf("New limits: soft=%jd; hard=%jd\n",
(intmax_t) old.rlim_cur, (intmax_t) old.rlim_max);
exit(EXIT_SUCCESS); }
prlimit(1), dup(2), fcntl(2), fork(2), getrusage(2), mlock(2), mmap(2), open(2), quotactl(2), sbrk(2), shmctl(2), malloc(3), sigqueue(3), ulimit(3), core(5), capabilities(7), cgroups(7), credentials(7), signal(7)
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
5 февраля 2023 г. | Linux man-pages 6.03 |