Czy używałeś tej samej powłoki w obu eksperymentach? Może /bin/bashvs. /bin/sh(który może być linkiem do myślnika)?
maxschlepzig
Tak, przeprowadziłem eksperyment z 10000 plikami o nazwie pliku, które są dość długie. „ls *” nie powiodło się i „for f in *” powiodło się.
lamwaiman1988
Odpowiedzi:
13
Błąd „zbyt długi argument” jest E2BIGwywoływany przez execvewywołanie systemowe, jeśli całkowity rozmiar argumentów (plus środowisko, w niektórych systemach) jest zbyt duży. execveWezwanie jest ten, który rozpoczyna procesów zewnętrznych, a konkretnie ładuje inny plik wykonywalny (jest inna rozmowa, forkna prowadzenie oddzielnego procesu, którego kod jest nadal z tego samego pliku wykonywalnego). forPętli wewnętrzna konstrukcja płaszcza tak, że nie obejmuje wywołanie execve. Polecenie ls *.*podnosi błąd nie po rozwinięciu globu, ale po lswywołaniu.
execvekończy się błędem, E2BIGgdy całkowity rozmiar argumentów polecenia jest większy niż ARG_MAXlimit . Możesz zobaczyć wartość tego limitu w swoim systemie za pomocą polecenia getconf ARG_MAX. (Możliwe, że możesz przekroczyć ten limit, jeśli masz wystarczającą ilość pamięci; utrzymywanie poniżej ARG_MAXgwarancji, które execvebędą działać, dopóki nie wystąpi niepowiązany błąd).
@ gunbuster363 execveLimit jest egzekwowany przez jądro, nakłada ograniczenia, ponieważ argumenty muszą zostać skopiowane przez pamięć jądra w jednym punkcie, a procesy użytkownika nie mogą żądać dowolnej ilości pamięci powłoki. Wewnątrz powłoki nie ma powodu, aby mieć limit, wszystko, co mieści się w pamięci wirtualnej, jest w porządku.
Gilles „SO- przestań być zły”
5
Przypuszczam, że w pierwszym przykładzie lsjest wykonywana bashprzez wywołanie systemowe fork/ execpair, w drugim cała praca jest wewnętrzna bash.
execWezwanie ma swoje granice, wewnętrzny roboczy bashzamiast nie ma (albo lepiej, ma różne ograniczenia, które nie mają nic wspólnego z exec, być może ilość dostępnej pamięci).
Zdecydowanie istnieje limit rozszerzania powłoki. Jest to bardzo związane z ilością dostępnej pamięci RAM. Spróbuj tego; mój system 4 GB RAM wysadza uszczelkę około 15,2 miliona 8-bajtowych argumentów:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O
4
@fred Naprawdę nie sądziłem, że trzeba wspomnieć o RAM jako limicie.
Šimon Tóth
2
Może to nie być potrzebne, ale taka jest natura komentarzy. Ktoś może uznać to za interesujące, a nawet wartościowe.
Peter.O
@fred: właściwie tak, jeśli częstym problemem jest rozwijanie bardzo dużych argumentów, można je zaimplementować bez przechowywania wszystkiego w pamięci.
/bin/bash
vs./bin/sh
(który może być linkiem do myślnika)?Odpowiedzi:
Błąd „zbyt długi argument” jest
E2BIG
wywoływany przezexecve
wywołanie systemowe, jeśli całkowity rozmiar argumentów (plus środowisko, w niektórych systemach) jest zbyt duży.execve
Wezwanie jest ten, który rozpoczyna procesów zewnętrznych, a konkretnie ładuje inny plik wykonywalny (jest inna rozmowa,fork
na prowadzenie oddzielnego procesu, którego kod jest nadal z tego samego pliku wykonywalnego).for
Pętli wewnętrzna konstrukcja płaszcza tak, że nie obejmuje wywołanieexecve
. Poleceniels *.*
podnosi błąd nie po rozwinięciu globu, ale pols
wywołaniu.execve
kończy się błędem,E2BIG
gdy całkowity rozmiar argumentów polecenia jest większy niżARG_MAX
limit . Możesz zobaczyć wartość tego limitu w swoim systemie za pomocą poleceniagetconf ARG_MAX
. (Możliwe, że możesz przekroczyć ten limit, jeśli masz wystarczającą ilość pamięci; utrzymywanie poniżejARG_MAX
gwarancji, któreexecve
będą działać, dopóki nie wystąpi niepowiązany błąd).źródło
execve
Limit jest egzekwowany przez jądro, nakłada ograniczenia, ponieważ argumenty muszą zostać skopiowane przez pamięć jądra w jednym punkcie, a procesy użytkownika nie mogą żądać dowolnej ilości pamięci powłoki. Wewnątrz powłoki nie ma powodu, aby mieć limit, wszystko, co mieści się w pamięci wirtualnej, jest w porządku.Przypuszczam, że w pierwszym przykładzie
ls
jest wykonywanabash
przez wywołanie systemowefork
/exec
pair, w drugim cała praca jest wewnętrznabash
.exec
Wezwanie ma swoje granice, wewnętrzny roboczybash
zamiast nie ma (albo lepiej, ma różne ograniczenia, które nie mają nic wspólnego zexec
, być może ilość dostępnej pamięci).źródło
exec
w/usr/include/linux/limits.h
zazwyczaj zdefiniowany jakoARG_MAX
.Ponieważ w tym przypadku
ls
jest to argument, a liczba argumentów jest ograniczona.W przypadku
for
cyklu jest to tylko lista pozycji. Nie ma żadnych ograniczeń (o ile mi wiadomo).źródło
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done