system
exec je shell s argumenty "sh","-c", YourAgumentToSystem, (char*)0
(zaručeno POSIX), takže maximální délka (nepočítá se '\0'
). terminátor) je ARG_MAX -1 -3 -3 - size_of_your_environment
.
ARG_MAX
je definováno v limitech.h jako
"Maximální délka argumentu funkcí exec včetně dat prostředí."
Pokud limits.h
, nedefinuje ARG_MAX
, měli byste být schopni zavolat sysconf(_SC_ARG_MAX)
získat limit doby běhu.
Další informace poskytuje linuxová manuálová stránka pro execve (volaná systémem):
V Linuxu před jádrem 2.6.23 byla paměť používaná k ukládání řetězců prostředí a argumentů omezena na 32 stránek (definovaných konstantou jádra MAX_ARG_PAGES). Na architekturách s velikostí stránek 4 kB to poskytuje maximální velikost 128 kB.
V jádře 2.6.23 a novějších většina architektur podporuje omezení velikosti odvozené od měkkého limitu prostředků RLIMIT_STACK (viz getrlimit(2)), který je platný v době volání execve(). (Architektury bez jednotky správy paměti jsou vyjmuty:udržují si limit, který platil před jádrem 2.6.23.) Tato změna umožňuje programům mít mnohem větší seznam argumentů a/nebo prostředí. U těchto architektur je celková velikost omezena na 1/4 povolené velikosti zásobníku. (Uvedením 1/4-limitu zajistíte, že nový program bude mít vždy nějaké místo na zásobníku.) Od Linuxu 2.6.25 jádro umisťuje na tento limit velikosti 32 stránek, takže i když je RLIMIT_STACK nastaveno velmi nízko, aplikace jsou zaručeny mít alespoň tolik prostoru pro argumenty a prostředí, jaký poskytoval Linux 2.6.23 a starší. (Tato záruka nebyla poskytnuta v Linuxu 2.6.23 a 2.6.24.) Navíc je limit na řetězec 32 stránek (konstanta jádra MAX_ARG_STRLEN) a maximální počet řetězců je 0x7FFFFFFF.
Chcete-li změřit velikost vašeho prostředí, můžete spustit:
extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;
(Jak poukázal Zan Lynx v komentářích, lze to urychlit (cca 20krát podle mých měření – z 1600ns na 80ns pro 100-řetězcové 6KB prostředí, které jsem měl při měření), pokud předpokládáte char*
ukazatele v environ
ukazují na souvislou vyrovnávací paměť, což dělají po spuštění programu, ale volají setenv
, putenv
nebo unsetenv
obvykle to porušte:
extern char **environ;
char **e; for(e=environ; *e; e++) {}
size_t envsz = ($_sz)(e[-1]+strlen(e[-1])+1 - *environ);
V každém případě by na zrychlení na úkor robustnosti nemělo moc záležet, pokud očekáváte, že fork+exec (/system) brzy, vzhledem k tomu, že fork+exec obvykle stojí alespoň kolem 1-2 ms na Linuxu na moderním stroj.)
Limit je vysoce závislý na systému. Může to dokonce záviset na příkazovém shellu, který bude použit. Měli byste otestovat návratovou hodnotu system()
abyste zjistili, zda bylo systémové volání úspěšné:-1
znamená selhání a errno
by vám měl poskytnout více informací. Chování by mělo být definováno pro jakýkoli správný řetězec C.
Dokumenty POSIX, které system(command)
je ekvivalentní:
execl(<shell path>, "sh", "-c", command, (char *)0);
A také dokumenty ARG_MAX
definováno v <limits.h>
jako limit pro kombinované délky argumentů na exec
a proměnné prostředí.
Všimněte si však, že command
může obsahovat zástupné znaky a/nebo jiná shellová slova, jejichž expanze může překročit nějaký jiný limit. Vždy zkontrolujte návratovou hodnotu kvůli selhání.