¿Usaste el mismo caparazón en ambos experimentos? ¿Quizás /bin/bashvs. /bin/sh(que quizás sea un enlace al guión)?
maxschlepzig
Sí, hice el experimento con 10000 archivos con nombre de archivo que son bastante largos. "ls *" falló y "for f in *" tuvo éxito.
lamwaiman1988
Respuestas:
13
El error de "argumento demasiado largo" es E2BIGprovocado por la execvellamada al sistema si el tamaño total de los argumentos (más el entorno, en algunos sistemas) es demasiado grande. La execvellamada es la que inicia procesos externos, específicamente cargando un archivo ejecutable diferente (hay una llamada diferente fork, para ejecutar un proceso separado cuyo código todavía es del mismo archivo ejecutable). El forbucle es una construcción de shell interna, por lo que no implica llamar execve. El comando ls *.*genera el error no cuando el globo se expande sino cuando lsse llama.
execvefalla con el error E2BIGcuando el tamaño total de los argumentos para el comando es mayor que el ARG_MAXlímite . Puede ver el valor de este límite en su sistema con el comando getconf ARG_MAX. (Es posible que pueda superar este límite si tiene suficiente memoria; mantener bajo ARG_MAXgarantías que execvefuncionará siempre que no se produzca un error no relacionado).
@ gunbuster363 El execvelímite es impuesto por el núcleo, pone límites porque los argumentos deben copiarse a través de la memoria del núcleo en un punto y no se puede permitir que los procesos del usuario soliciten una cantidad arbitraria de memoria de shell. Dentro del shell, no hay razón para tener ningún límite, todo lo que cabe en la memoria virtual está bien.
Gilles 'SO- deja de ser malvado'
5
Supongo que en el primer ejemplo lsse ejecuta a bashtravés de una llamada al sistema fork/ execpair, en el segundo, todo el trabajo es interno bash.
La execllamada tiene límites, el funcionamiento interno bashno tiene (o mejor, tiene límites diferentes que no tienen nada que ver exec, tal vez la cantidad de memoria disponible).
Definitivamente hay un límite para la expansión de shell. Está muy relacionado con la cantidad de RAM que tiene disponible. Pruebe esto; mi sistema de 4 GB de RAM explota en aproximadamente 15.2 millones de for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
argumentos de
44
@fred Realmente no pensé que mencionar RAM como límite sea necesario.
Šimon Tóth
2
Puede que no sea necesario, pero esa es la naturaleza de los comentarios ... alguien puede encontrarlo interesante o incluso valioso.
Peter.O
@fred: en realidad sí, si expandir argumentos muy grandes fuera un problema común, sería posible implementarlo sin tener todo en la memoria.
/bin/bash
vs./bin/sh
(que quizás sea un enlace al guión)?Respuestas:
El error de "argumento demasiado largo" es
E2BIG
provocado por laexecve
llamada al sistema si el tamaño total de los argumentos (más el entorno, en algunos sistemas) es demasiado grande. Laexecve
llamada es la que inicia procesos externos, específicamente cargando un archivo ejecutable diferente (hay una llamada diferentefork
, para ejecutar un proceso separado cuyo código todavía es del mismo archivo ejecutable). Elfor
bucle es una construcción de shell interna, por lo que no implica llamarexecve
. El comandols *.*
genera el error no cuando el globo se expande sino cuandols
se llama.execve
falla con el errorE2BIG
cuando el tamaño total de los argumentos para el comando es mayor que elARG_MAX
límite . Puede ver el valor de este límite en su sistema con el comandogetconf ARG_MAX
. (Es posible que pueda superar este límite si tiene suficiente memoria; mantener bajoARG_MAX
garantías queexecve
funcionará siempre que no se produzca un error no relacionado).fuente
execve
límite es impuesto por el núcleo, pone límites porque los argumentos deben copiarse a través de la memoria del núcleo en un punto y no se puede permitir que los procesos del usuario soliciten una cantidad arbitraria de memoria de shell. Dentro del shell, no hay razón para tener ningún límite, todo lo que cabe en la memoria virtual está bien.Supongo que en el primer ejemplo
ls
se ejecuta abash
través de una llamada al sistemafork
/exec
pair, en el segundo, todo el trabajo es internobash
.La
exec
llamada tiene límites, el funcionamiento internobash
no tiene (o mejor, tiene límites diferentes que no tienen nada que verexec
, tal vez la cantidad de memoria disponible).fuente
exec
en/usr/include/linux/limits.h
usualmente, definido comoARG_MAX
.Porque en el caso de
ls
esto es un argumento, y el número de argumentos es limitado.En el caso del
for
ciclo, es solo una lista de elementos. No hay límites (hasta donde yo sé) para eso.fuente
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done