printf("unrepresentable");

#endif

else

printf("%lld", (long long) rlim.rlim_cur);

printf("; hard=");

if (rlim.rlim_max == RLIM_INFINITY)

printf("infinite\n");

#ifdef RLIM_SAVED_MAX /* Не определено в некоторых системах */

else if (rlim.rlim_max == RLIM_SAVED_MAX)

printf("unrepresentable");

#endif

else

printf("%lld\n", (long long) rlim.rlim_max);

return 0;

}

procres/print_rlimit.c

Листинг 36.3. Установление ограничения RLIMIT_NPROC

procres/rlimit_nproc.c

#include

#include "print_rlimit.h" /* Объявление функции printRlimit() */

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

struct rlimit rl;

int j;

pid_t childPid;

if (argc < 2 || argc > 3 || strcmp(argv[1], "-help") == 0)

usageErr("%s soft-limit [hard-limit]\n", argv[0]);

printRlimit("Initial maximum process limits: ", RLIMIT_NPROC);

/* Устанавливаем новые ограничения для процесса (по умолчанию

жесткое и мягкое совпадают) */

rl.rlim_cur = (argv[1][0] == 'i')? RLIM_INFINITY:

getInt(argv[1], 0, "soft-limit");

rl.rlim_max = (argc == 2)? rl.rlim_cur:

(argv[2][0] == 'i')? RLIM_INFINITY:

getInt(argv[2], 0, "hard-limit");

if (setrlimit(RLIMIT_NPROC, &rl) == –1)

errExit("setrlimit");

printRlimit("New maximum process limits: ", RLIMIT_NPROC);

/* Создаем как можно больше дочерних процессов */

for (j = 1;; j++) {

switch (childPid = fork()) {

case –1: errExit("fork");

case 0: _exit(EXIT_SUCCESS); /* Потомок */

default: /* Родитель выводит сообщение о каждом новом потомке

и позволяет учитывать процессы-"зомби" */

printf("Child %d (PID=%ld) started\n", j, (long) childPid);

break;

}

}

}

procres/rlimit_nproc.c

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

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

Чтобы помочь переносимым приложениям справляться со случаями, когда ограничение на ресурсы выходит за пределы допустимого диапазона, стандарт SUSv3 предоставляет две константы, обозначающие значения ограничений, которые не могут быть представлены: RLIM_SAVED_CUR и RLIM_SAVED_MAX. Если мягкое ограничение нельзя представить с помощью типа данных rlim_t, вызов getrlimit() возвращает в поле rlim_cur значение RLIM_SAVED_CUR. Точно так же константа RLIM_SAVED_MAX используется для жесткого ограничения, возвращаемого в поле rlim_max.

Если тип rlim_t позволяет представить все возможные значения ограничения на ресурсы, то стандарт SUSv3 разрешает объявить константы RLIM_SAVED_CUR и RLIM_SAVED_MAX равными RLIM_INFINITY. Именно так сделано в Linux; это подразумевает, что rlim_t может вместить любые значения ограничений. Однако это не относится к 32-битным архитектурам, таким как x86-32. В таких системах в среде компиляции больших файлов (то есть когда макросу _FILE_OFFSET_BITS, который проверяет наличие тех или иных возможностей, присваивается значение 64, как описано в разделе 5.10) библиотека glibc содержит 64-битную структуру rlim_t, однако в ядре для представления ограничений на ресурсы используется тип unsigned long, размер которого равен 32 битам. Современные версии glibc решают эту проблему следующим образом: если программа, скомпилированная с макросом _FILE_OFFSET_BITS=64, пытается установить ограничение на ресурсы, которое не вмещается в 32-битный тип unsigned long, тогда обертка для вызова setrlimit() из состава glibc автоматически меняет это значение на RLIM_INFINITY. Иными словами, запрашиваемое ограничение на ресурсы не устанавливается.

Во многих дистрибутивах с архитектурой x86-32 утилиты для работы с файлами обычно скомпилированы с макросом _FILE_OFFSET_BITS=64, поэтому невозможность установить ограничение, которое нельзя представить 32-битным значением, является проблемой, затрагивающей не только программистов, но и конечных пользователей.

С одной стороны, было бы лучше, если бы обертка setrlimit() из состава glibc возвращала ошибку, когда запрашиваемое ограничение не помещается в 32-битный тип unsigned long. Однако в основе проблемы лежит ограничение ядра, и для решения этой проблемы разработчиками glibc был выбран подход, описанный выше.

36.3. Подробности об отдельных ограничениях на ресурсы
Перейти на страницу:

Похожие книги