чому цикл не викликає помилку "занадто довгий аргумент"?


9

Я виявив, що це призведе до помилки "занадто довгий аргумент":

ls *.*

І це не підніме це:

for file in *.*
do
    echo $file
done

Чому?


Чи використовували ви одну і ту ж оболонку в обох експериментах? Можливо, /bin/bashпроти /bin/sh(що, можливо, посилання на тире)?
maxschlepzig

Так, я здійснив експеримент із 10000 файлами з назвою файлів, які досить довгі. "ls *" не вдалося і "for f in *" вдалося.
lamwaiman1988

Відповіді:


13

«Аргумент занадто довго» помилка E2BIG, піднятий execveсистемного виклику , якщо загальний розмір аргументів (плюс середовища, на деяких системах) занадто великий. execveВиклик є той , який запускає зовнішні процеси, в Зокрема , завантаження іншої виконуваний файл (є вхідний дзвінок, forkдля запуску окремого процесу, код якого до цих пір з того ж самого виконуваного файлу). forЦикл є внутрішньою конструкцією оболонки, тому він не пов'язаний з викликом execve. Команда ls *.*викликає помилку не тоді, коли глобус розгорнутий, а коли lsвикликається.

execveне вдається з помилкою, E2BIGколи загальний розмір аргументів команди перевищує ARG_MAX обмеження . За допомогою команди можна побачити значення цього обмеження у вашій системі getconf ARG_MAX. (Можливо, ви можете перейти цей ліміт, якщо у вас є достатня кількість пам'яті; зберігаючи ARG_MAXгарантії, які execveпрацюватимуть до тих пір, поки не виникне непов'язана помилка.)


і чому оболонка не мала межі?
lamwaiman1988

1
@ gunbuster363 execveОбмеження застосовується ядром, воно встановлює обмеження, оскільки аргументи потрібно копіювати через пам'ять ядра в один момент, і користувацькі процеси не можуть дозволити запитувати довільну кількість пам'яті оболонки. Всередині оболонки немає жодних причин мати обмеження, все, що вписується у віртуальну пам'ять, добре.
Жил 'ТАК - перестань бути злим'

5

Я припускаю, що в першому прикладі lsвиконується bashчерез системний виклик fork/ execпара, у другому - все, що працює, є внутрішнім bash.

execВиклик має межі, внутрішня обробка bashзамість не має (або краще, має різні обмеження , які не мають нічого спільного з exec, можливо , обсягом доступної пам'яті).


Ви можете знайти обмеження execв, /usr/include/linux/limits.hяк правило, визначеному як ARG_MAX.
jw013

Якщо ми використовуємо оболонку для циклу, чи вважаєте ви, що великий список елементів буде споживати всю оперативну пам’ять?
lamwaiman1988

Ця відповідь невірна. Це не "внутрішнє", це лише те, що межі аргументів та команд різні.
многочлен

5

Тому що у разі lsце аргумент, а кількість аргументів обмежена.

У випадку forциклу це лише перелік елементів. Для цього немає обмежень (наскільки мені відомо).


Виразно існує обмеження для розширення оболонки. Це дуже пов'язано з тим, скільки у вас є оперативної пам’яті. Спробуйте це; моя 4 Гб оперативної пам’яті for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
пробиває

4
@fred Я не дуже вважав, що потрібно згадувати оперативну пам'ять як обмеження.
Šimon Tóth

2
Це може не знадобитися, але така природа коментарів .. хтось може вважати це цікавим або навіть корисним.
Пітер.O

@fred: насправді так, якщо поширення дуже великих аргументів було загальною проблемою, можна було б реалізувати це, не зберігаючи все в пам’яті.
Маттео
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.