왜 for 루프가 "인수가 너무 깁니다"오류를 일으키지 않습니까?


9

이것이 "인수가 너무 깁니다"오류가 발생한다는 것을 알았습니다.

ls *.*

그리고 이것은 그것을 높이 지 않을 것입니다 :

for file in *.*
do
    echo $file
done

왜?


두 실험에서 동일한 쉘을 사용 했습니까? 아마도 /bin/bash/bin/sh(아마도 대시 링크)?
maxschlepzig

예, 파일 이름이 10000 인 10000 파일로 실험을했습니다. "ls *"에 실패했으며 "f in *"에 성공했습니다.
lamwaiman1988 년

답변:


13

인수 의 전체 크기 (및 일부 시스템의 경우 환경)가 너무 큰 경우 시스템 호출에 E2BIG의해 "인수가 너무 깁니다"오류가 발생합니다 execve. execve호출은 외부 프로세스를 시작 하는 호출이며, 특히 다른 실행 파일을로드합니다 ( fork코드가 여전히 동일한 실행 파일에서 별도의 프로세스를 실행하기위한 다른 호출 이 있음). for가 호출 포함하지 않도록 루프는 내부 쉘 구조이다 execve. ls *.*glob가 확장 될 때가 아니라 ls호출 될 때 명령 이 오류를 발생시킵니다 .

execveE2BIG명령에 대한 인수의 총 크기가 ARG_MAX 한계 보다 큰 경우 오류와 함께 실패합니다 . 명령을 사용하여 시스템에서이 제한 값을 볼 수 있습니다 getconf ARG_MAX. 메모리가 충분하면이 제한을 초과 할 수 있습니다 . 관련 오류가 발생하지 않는 한 작동하도록 ARG_MAX보장 execve합니다.


그리고 왜 쉘에 한계가 없었습니까?
lamwaiman1988

1
@ gunbuster363 execve커널에 의해 제한이 적용됩니다. 인수는 한 시점에서 커널 메모리를 통해 복사해야하고 사용자 프로세스가 임의의 양의 쉘 메모리를 요청할 수 없기 때문에 제한이 있습니다. 셸 내부에는 제한이 없어야 할 이유가 없습니다. 가상 메모리에 적합한 것은 괜찮습니다.
Gilles 'SO- 악마 그만해'

5

첫 번째 예제 ls에서 / pair 시스템 호출 을 bash통해 실행 되고 두 번째 예제 에서는 모든 작업이 내부에 있다고 가정 합니다.forkexecbash

exec호출의 내부 작업, 한계가 bash대신하지가 (또는 더 나은,와는 아무 상관이없는 다른 한계가 exec, 사용할 수있는 메모리의 아마 양을).


당신은에 한계를 찾을 수 exec/usr/include/linux/limits.h일반적으로 정의 ARG_MAX.
jw013

우리가 쉘 for 루프를 사용한다면, 큰 아이템 목록이 모든 RAM을 소비 할 것이라고 생각하십니까?
lamwaiman1988

이 답변은 잘못되었습니다. '내부'가 아니라 인수와 명령의 한계가 다르다는 것입니다.
다항식

5

왜냐하면 ls인수 의 경우 인수의 수가 제한 되기 때문입니다.

for사이클의 경우 항목 목록 일뿐입니다. 그것에 대해 (내가 아는 한) 제한이 없습니다.


쉘 확장에는 한계가 있습니다. 사용 가능한 RAM 용량과 매우 관련이 있습니다. 내 4GB RAM 시스템은 약 15.2 백만 8 바이트 args에서 개스킷을 for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
날립니다

4
@fred 나는 RAM을 한계로 언급하는 것이 실제로 필요하다고 생각하지 않았습니다.
Šimon Tóth

2
필요하지 않을 수도 있지만 그것이 의견의 본질입니다. 누군가가 흥미 롭거나 가치있는 것을 발견 할 수도 있습니다.
Peter.O

@fred : 사실 그렇습니다. 매우 큰 인수를 확장하는 것이 일반적인 문제라면 모든 것을 메모리에 보관하지 않고 구현할 수 있습니다.
Matteo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.