Вы использовали одну и ту же оболочку в обоих экспериментах? Возможно /bin/bashпротив /bin/sh(что, возможно, ссылка на тире)?
maxschlepzig
Да, я провел эксперимент с 10000 файлами с довольно длинным именем файла. «ls *» не удалось, а «для f in *» успешно.
lamwaiman1988
Ответы:
13
«Аргумент слишком долго» ошибка E2BIG, поднятый execveсистемного вызова , если общий размер аргументов (плюс среды, на некоторых системах) слишком велик. Этот execveвызов запускает внешние процессы, в частности, загружает другой исполняемый файл (есть другой вызов forkдля запуска отдельного процесса, код которого все еще находится в том же исполняемом файле). forЦикл является внутренней конструкцией оболочки, поэтому он не связан с вызовом execve. Команда ls *.*выдает ошибку не при расширении глобуса, а при lsвызове.
execveвыдает ошибку, E2BIGкогда общий размер аргументов команды больше, чем ARG_MAXпредел . Вы можете увидеть значение этого ограничения в вашей системе с помощью команды getconf ARG_MAX. (Возможно, вы можете превысить это ограничение, если у вас достаточно памяти; сохраняйте ARG_MAXгарантии, которые execveбудут работать до тех пор, пока не возникнет несвязанная ошибка.)
@ gunbuster363 execveПредел принудительно устанавливается ядром, он устанавливает ограничения, потому что аргументы необходимо скопировать через память ядра в одной точке, и пользовательским процессам нельзя разрешать запрашивать произвольный объем памяти оболочки. Внутри оболочки нет никаких ограничений, все, что умещается в виртуальной памяти, прекрасно.
Жиль "ТАК - перестань быть злым"
5
Я полагаю, что в первом примере lsвыполняется bashчерез системный вызов fork/ execpair, а во втором - все внутреннее bash.
execВызов имеет пределы, внутренняя обработка bashвместо не имеет (или лучше, имеет различные ограничения , которые не имеют ничего общего с exec, возможно , объемом доступной памяти).
Определенно есть предел для расширения оболочки. Это очень сильно зависит от того, сколько у вас оперативной памяти. Попробуйте это; моя система 4 ГБ ОЗУ обеспечивает прокладку примерно в 15,2 млн. 8-байтовых аргументов:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O
4
@fred Я действительно не думал, что упоминание ОЗУ как предела необходимо.
Шимон Тот
2
Это может не понадобиться, но такова природа комментариев. Кто-то может найти это интересным или даже ценным.
Peter.O
@fred: на самом деле да, если бы расширение очень больших аргументов было распространенной проблемой, было бы возможно реализовать это, не сохраняя все в памяти.
/bin/bash
против/bin/sh
(что, возможно, ссылка на тире)?Ответы:
«Аргумент слишком долго» ошибка
E2BIG
, поднятыйexecve
системного вызова , если общий размер аргументов (плюс среды, на некоторых системах) слишком велик. Этотexecve
вызов запускает внешние процессы, в частности, загружает другой исполняемый файл (есть другой вызовfork
для запуска отдельного процесса, код которого все еще находится в том же исполняемом файле).for
Цикл является внутренней конструкцией оболочки, поэтому он не связан с вызовомexecve
. Командаls *.*
выдает ошибку не при расширении глобуса, а приls
вызове.execve
выдает ошибку,E2BIG
когда общий размер аргументов команды больше, чемARG_MAX
предел . Вы можете увидеть значение этого ограничения в вашей системе с помощью командыgetconf ARG_MAX
. (Возможно, вы можете превысить это ограничение, если у вас достаточно памяти; сохраняйтеARG_MAX
гарантии, которыеexecve
будут работать до тех пор, пока не возникнет несвязанная ошибка.)источник
execve
Предел принудительно устанавливается ядром, он устанавливает ограничения, потому что аргументы необходимо скопировать через память ядра в одной точке, и пользовательским процессам нельзя разрешать запрашивать произвольный объем памяти оболочки. Внутри оболочки нет никаких ограничений, все, что умещается в виртуальной памяти, прекрасно.Я полагаю, что в первом примере
ls
выполняетсяbash
через системный вызовfork
/exec
pair, а во втором - все внутреннееbash
.exec
Вызов имеет пределы, внутренняя обработкаbash
вместо не имеет (или лучше, имеет различные ограничения , которые не имеют ничего общего сexec
, возможно , объемом доступной памяти).источник
exec
в/usr/include/linux/limits.h
обычно, определяемый какARG_MAX
.Потому что в случае
ls
этого есть аргумент, а количество аргументов ограничено.В случае
for
цикла это просто список предметов. Для этого нет пределов (насколько я знаю).источник
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done