В продолжение https://stackoverflow.com/questions/14176089/system-command-line-max-length-in-perl, в котором говорится, что максимальная длина аргументов exec/ командной строки контролируется ARG_MAX .

Поэтому я хочу увеличить максимальную длину такой командной строки, и кажется, что перекомпиляция ядра - единственный вариант. Хорошо. Однако мой вопрос по ARG_MAX , потому что все говорят, что это тот, который должен быть увеличен, но я прочитал с http://www.in-ulm.de/~mascheck/various/argmax/#linux, что,

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

Так ARG_MAX не используется или нет? Как увеличить максимальную длину для аргументов exec/ командной строки? потому что моя максимальная длина командной строки ограничена некоторым меньшим значением, чем я предпочитаю.

Спасибо

1 ответ1

2

Поскольку Linux-2.6.23 ARG_MAX не обязательно предварительно определенная константа, общий размер аргументов разрешаются составлять до 1/4 от размера стека (см ulimit -s размер стека в Кб, но /proc/1/limits более определенны). Однако ARG_MAX предназначен не только для аргументов процесса, он также содержит переменные среды, которые вам, возможно, придется учитывать.

POSIX определяет, что означает ARG_MAX, и приемлемый нижний предел _POSIX_ARG_MAX 4096). Его статическое значение (исторически) доступно через #define в системных заголовках, а также оно устанавливается в заголовочных файлах ядра Linux. Его эффективное значение доступно с помощью sysconf() или getconf ARG_MAX из командной строки.

Если вы проверите заголовки glibc (sys/param.h), вы увидите это:

/* The kernel headers defines ARG_MAX.  The value is wrong, though.  */
#ifdef __undef_ARG_MAX
# undef ARG_MAX
# undef __undef_ARG_MAX
#endif

Это из glibc-2.17, это появилось около 2.11 (2009), первая поддержка для этих дат - 2.8 (2008), но до 2.14 (2011) была ошибка в вышеупомянутой логике, которая мешала ему работать должным образом. Цель состоит в том, чтобы убедиться, что ARG_MAX не определен, если он не является константой, поэтому программы должны полагаться на sysconf() . (Даже если он определен, это может быть только нижний гарантированный предел, и программы должны использовать sysconf() для определения верхних пределов переменной, см. sysconf(3))

Вы можете проверить, что видит ваш компилятор C (только синтаксис gcc , bash/zsh ):

$ gcc -E -dM -x c <(echo "#include <sys/param.h>") | fgrep ARG
#define ARG_MAX 131072
#define NCARGS ARG_MAX
#define _POSIX_ARG_MAX 4096

Приведенный выше вывод получен из старой системы (2.6.27), в которой есть поддержка ядра, но не полная среда выполнения (поддержка glibc). Если вы не видите строки ARG_MAX то это не предопределенный предел, и вы должны использовать (sysconf) getconf ARG_MAX:

$ getconf ARG_MAX
2097152

Полезный способ проверить поддержку также:

$ xargs --show-limits < /dev/null
Your environment variables take up 2542 bytes
POSIX upper limit on argument length (this system): 2092562
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090020
Size of command buffer we are actually using: 131072

Это из системы linux-2.6.37/glib-2.13 с более высокими лимитами. Обратите внимание на последнюю строку вывода, xargs умолчанию (время сборки) до "разумного" предела, возможно, в случае, если какой-либо из процессов, которые он запускает, не способен обрабатывать очень большие значения. Вы можете изменить это во время выполнения с опцией -s . Кроме того, если у вас действует ulimit -s , эти цифры могут быть ниже. Это должно работать правильно, начиная с findutils-4.3.9 (2007). Смотрите также: http://www.gnu.org/software/coreutils/faq/coreutils-faq.html#Argument-list-too-long

Чтобы проверить Perl:

% perl -MPOSIX -e 'print ARG_MAX . "\n"';
131072

Выше опять из старой системы, новая система должна показать:

% perl -MPOSIX -e 'print ARG_MAX . "\n"';
Your vendor has not defined POSIX macro ARG_MAX, used at -e line 1

Подвести итоги:

  • Если вы работаете с ядром, выпущенным после 2.6.23, ядро разрешит передавать большие размеры при создании процесса. Это необходимое, но не достаточное условие.
  • Родительский процесс не должен применять какие-либо неверные ограничения времени выполнения (например, с жестко запрограммированным ARG_MAX), вместо этого он должен проверять коды ошибок exec() E2BIG и должен использовать sysconf(_SC_ARG_MAX) при необходимости.
  • Дочерний процесс не должен применять какие-либо неправильные ограничения времени выполнения, в частности его код запуска, который обрабатывает ядро, при условии, что параметры не должны иметь неправильных жестко заданных ограничений (например, при настройке argc , argc , области среды для использования во время выполнения). Обычно это делается в libc (glibc).
  • Для родителей и детей вам также может понадобиться настроить и собрать поддержку времени из libc (или эквивалентную). Для glibc для этого требуется как минимум glibc-2.8 (хотя должна быть возможность обойти его, он может быть не простым и не чистым)

Проблемной комбинацией является обновленное (linux> = 2.6.23) ядро, но отсутствует или подозревается поддержка glibc (glibc <= 2.14)

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


Программы должны иметь возможность обрабатывать произвольные значения, но это не всегда так: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html

Приложения не должны принимать какое-либо конкретное значение для ограничения. [...] Однако следует отметить, что многие из перечисленных пределов не являются инвариантными, и во время выполнения значение предела может отличаться от значений, указанных в этом заголовке, по следующим причинам:

  • Предел зависит от имени пути.
  • Предел различается между компиляцией и машинами времени выполнения.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .