Я обнаружил, что это вызовет ошибку «аргумент слишком длинный»:
ls *.*
И это не подняло бы это:
for file in *.*
do
echo $file
done
Почему?
Я обнаружил, что это вызовет ошибку «аргумент слишком длинный»:
ls *.*
И это не подняло бы это:
for file in *.*
do
echo $file
done
Почему?
Ответы:
«Аргумент слишком долго» ошибка E2BIG, поднятый execveсистемного вызова , если общий размер аргументов (плюс среды, на некоторых системах) слишком велик. Этот execveвызов запускает внешние процессы, в частности, загружает другой исполняемый файл (есть другой вызов forkдля запуска отдельного процесса, код которого все еще находится в том же исполняемом файле). forЦикл является внутренней конструкцией оболочки, поэтому он не связан с вызовом execve. Команда ls *.*выдает ошибку не при расширении глобуса, а при lsвызове.
execveвыдает ошибку, E2BIGкогда общий размер аргументов команды больше, чем ARG_MAX предел . Вы можете увидеть значение этого ограничения в вашей системе с помощью команды getconf ARG_MAX. (Возможно, вы можете превысить это ограничение, если у вас достаточно памяти; сохраняйте ARG_MAXгарантии, которые execveбудут работать до тех пор, пока не возникнет несвязанная ошибка.)
execveПредел принудительно устанавливается ядром, он устанавливает ограничения, потому что аргументы необходимо скопировать через память ядра в одной точке, и пользовательским процессам нельзя разрешать запрашивать произвольный объем памяти оболочки. Внутри оболочки нет никаких ограничений, все, что умещается в виртуальной памяти, прекрасно.
Я полагаю, что в первом примере lsвыполняется bashчерез системный вызов fork/ execpair, а во втором - все внутреннее 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
/bin/bashпротив/bin/sh(что, возможно, ссылка на тире)?