system
exec è una shell con argomenti "sh","-c", YourAgumentToSystem, (char*)0
(garantito da POSIX), quindi la lunghezza massima (senza contare il '\0'
terminatore) è ARG_MAX -1 -3 -3 - size_of_your_environment
.
ARG_MAX
è definito in limits.h come
"Lunghezza massima dell'argomento per le funzioni exec inclusi i dati dell'ambiente."
Se limits.h
, non definisce ARG_MAX
, dovresti essere in grado di chiamaresysconf(_SC_ARG_MAX)
per ottenere un limite di runtime.
La manpage di linux per execve (chiamata dal sistema) fornisce ulteriori informazioni:
Su Linux prima del kernel 2.6.23, la memoria utilizzata per memorizzare l'ambiente e le stringhe di argomenti era limitata a 32 pagine (definite dalla costante del kernel MAX_ARG_PAGES). Su architetture con una dimensione di pagina di 4 kB, questo produce una dimensione massima di 128 kB.
Nel kernel 2.6.23 e successivi, la maggior parte delle architetture supporta un limite di dimensione derivato dal limite di risorse soft RLIMIT_STACK (vedere getrlimit(2)) che è in vigore al momento della chiamata execve(). (Sono escluse le architetture senza unità di gestione della memoria:mantengono il limite che era in vigore prima del kernel 2.6.23.) Questa modifica consente ai programmi di avere un elenco di argomenti e/o ambienti molto più ampio. Per le strutture di ricerca, la dimensione totale è limitata a 1/4 della dimensione dello stack consentita. (L'imposizione del limite di 1/4 garantisce che il nuovo programma abbia sempre un po' di spazio per lo stack.) A partire da Linux 2.6.25, il kernel pone una base di 32 pagine su questo limite di dimensione, in modo che, anche quando RLIMIT_STACK è impostato molto basso, le applicazioni sono garantite avere almeno lo stesso spazio di argomenti e ambienti fornito da Linux 2.6.23 e versioni precedenti. (Questa garanzia non era fornita in Linux 2.6.23 e 2.6.24.) Inoltre, il limite per stringa è di 32 pagine (la costante del kernel MAX_ARG_STRLEN) e il numero massimo di stringhe è 0x7FFFFFFF.
Per misurare le dimensioni del tuo ambiente, puoi eseguire:
extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;
(Come ha sottolineato Zan Lynx nei commenti, questo può essere accelerato (cca 20 volte secondo le mie misurazioni, da 1600ns a 80ns per l'ambiente 6KB a 100 stringhe che avevo durante la misurazione) se assumi il char*
puntatori in environ
puntano a un buffer contiguo, cosa che fanno dopo l'avvio di un programma, ma chiamano setenv
, putenv
o unsetenv
in genere rompi questo:
extern char **environ;
char **e; for(e=environ; *e; e++) {}
size_t envsz = ($_sz)(e[-1]+strlen(e[-1])+1 - *environ);
In ogni caso, l'accelerazione a scapito della robustezza non dovrebbe avere molta importanza se ti aspetti di fork+exec (/system) presto, dato che fork+exec in genere costa almeno circa 1-2 ms su Linux su un moderno macchina.)
Il limite dipende fortemente dal sistema. Potrebbe anche dipendere dalla shell dei comandi che verrà utilizzata. Dovresti testare il valore restituito di system()
per vedere se la chiamata di sistema ha avuto successo:-1
significa fallimento e errno
dovrebbe darti maggiori informazioni. Il comportamento dovrebbe essere definito per qualsiasi stringa C appropriata.
Documenti POSIX che system(command)
è equivalente a:
execl(<shell path>, "sh", "-c", command, (char *)0);
E anche documenti ARG_MAX
definito in <limits.h>
come limite per le lunghezze combinate degli argomenti a exec
e le variabili di ambiente.
Nota comunque che command
può contenere caratteri jolly e/o altre parole di shell la cui espansione può superare qualche altro limite. Controlla sempre il valore restituito per errore.