system
exec es un shell con argumentos "sh","-c", YourAgumentToSystem, (char*)0
(garantizado por POSIX), por lo que la longitud máxima (sin contar el '\0'
terminador) es ARG_MAX -1 -3 -3 - size_of_your_environment
.
ARG_MAX
se define en limites.h como
"Longitud máxima del argumento de las funciones ejecutivas, incluidos los datos del entorno".
Si limits.h
, no define ARG_MAX
, debería poder llamar a sysconf(_SC_ARG_MAX)
para obtener un límite de tiempo de ejecución.
La página de manual de Linux para execve (llamada por el sistema) proporciona más información:
En Linux antes del kernel 2.6.23, la memoria utilizada para almacenar el entorno y las cadenas de argumentos estaba limitada a 32 páginas (definidas por la constante del kernel MAX_ARG_PAGES). En arquitecturas con un tamaño de página de 4 kB, esto produce un tamaño máximo de 128 kB.
En el kernel 2.6.23 y posteriores, la mayoría de las arquitecturas admiten un límite de tamaño derivado del límite de recursos suave RLIMIT_STACK (ver getrlimit(2)) que está vigente en el momento de la llamada execve(). (Se exceptúan las arquitecturas sin unidad de gestión de memoria:mantienen el límite que estaba en vigor antes del kernel 2.6.23.) Este cambio permite que los programas tengan una lista de argumentos y/o entornos mucho más grande. Para las arquitecturas de búsqueda, el tamaño total está limitado a 1/4 del tamaño de pila permitido. (Imponer el límite de 1/4 asegura que el nuevo programa siempre tenga algo de espacio en la pila.) Desde Linux 2.6.25, el kernel establece un límite mínimo de 32 páginas en este límite de tamaño, de modo que, incluso cuando RLIMIT_STACK se establece en un valor muy bajo, las aplicaciones están garantizadas tener al menos tanto espacio de argumento y entorno como el proporcionado por Linux 2.6.23 y versiones anteriores. (Esta garantía no se proporcionó en Linux 2.6.23 y 2.6.24). Además, el límite por cadena es de 32 páginas (la constante del kernel MAX_ARG_STRLEN), y el número máximo de cadenas es 0x7FFFFFFF.
Para medir el tamaño de su entorno, puede ejecutar:
extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;
(Como Zan Lynx ha señalado en los comentarios, esto se puede acelerar (unas 20 veces según mis medidas, de 1600 ns a 80 ns para el entorno de 6 KB de 100 cadenas que tenía al medir) si asume el char*
punteros en environ
apuntan a un búfer contiguo, lo que hacen después de que se inicia un programa, pero llaman a setenv
, putenv
o unsetenv
típicamente rompe esto:
extern char **environ;
char **e; for(e=environ; *e; e++) {}
size_t envsz = ($_sz)(e[-1]+strlen(e[-1])+1 - *environ);
En cualquier caso, la velocidad a costa de la robustez no debería importar mucho si esperas bifurcar+exec (/sistema) pronto, dado que fork+exec normalmente cuesta al menos alrededor de 1-2 ms en Linux en un sistema moderno. máquina.)
El límite depende en gran medida del sistema. Incluso puede depender del shell de comandos que se utilizará. Debe probar el valor de retorno de system()
para ver si la llamada al sistema fue exitosa:-1
significa falla y errno
debería darte más información. El comportamiento debe definirse para cualquier cadena C adecuada.
Documentos POSIX que system(command)
es equivalente a:
execl(<shell path>, "sh", "-c", command, (char *)0);
Y también documentos ARG_MAX
definido en <limits.h>
como límite para las longitudes combinadas de los argumentos a exec
y las variables de entorno.
Sin embargo, tenga en cuenta que command
puede contener comodines y/u otras palabras shell cuya expansión puede exceder algún otro límite. Siempre verifique el valor devuelto por falla.