modifica:
Sono stato finalmente in grado di passare <=256 KB come singolo argomento della riga di comando (vedi modifica (4) in basso). Tuttavia, per favore leggi attentamente come l'ho fatto e decidi tu stesso se questo è un modo in cui vuoi andare. Almeno dovresti essere in grado di capire perché sei "bloccato" altrimenti da quello che ho scoperto.
Con l'accoppiamento di ARG_MAX
a ulim -s
/4 è arrivata l'introduzione di MAX_ARG_STRLEN
come massimo lunghezza di un argomento:
/*
* linux/fs/exec.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
...
#ifdef CONFIG_MMU
/*
* The nascent bprm->mm is not visible until exec_mmap() but it can
* use a lot of memory, account these pages in current->mm temporary
* for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
* change the counter back via acct_arg_size(0).
*/
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= MAX_ARG_STRLEN;
}
...
#else
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= bprm->p;
}
#endif /* CONFIG_MMU */
...
static int copy_strings(int argc, struct user_arg_ptr argv,
struct linux_binprm *bprm)
{
...
str = get_user_arg_ptr(argv, argc);
...
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
ret = -E2BIG;
if (!valid_arg_len(bprm, len))
goto out;
...
}
...
MAX_ARG_STRLEN
è definito come 32 volte la dimensione della pagina in linux/include/uapi/linux/binfmts.h
:
...
/*
* These are the maximum length and maximum number of strings passed to the
* execve() system call. MAX_ARG_STRLEN is essentially random but serves to
* prevent the kernel from being unduly impacted by misaddressed pointers.
* MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
*/
#define MAX_ARG_STRLEN (PAGE_SIZE * 32)
#define MAX_ARG_STRINGS 0x7FFFFFFF
...
La dimensione predefinita della pagina è 4 KB, quindi non puoi passare argomenti più lunghi di 128 KB.
Non posso provarlo ora, ma forse il passaggio alla modalità pagina enorme (dimensione pagina 4 MB) se possibile sul tuo sistema risolve questo problema.
Per informazioni e riferimenti più dettagliati, vedere questa risposta a una domanda simile su Unix e Linux SE.
modifiche:
(1) In base a questa risposta è possibile modificare la dimensione della pagina di x86_64
Linux a 1 MB abilitando CONFIG_TRANSPARENT_HUGEPAGE
e impostando CONFIG_TRANSPARENT_HUGEPAGE_MADVISE
a n
nella configurazione del kernel.
(2) Dopo aver ricompilato il mio kernel con le suddette modifiche alla configurazione getconf PAGESIZE
restituisce ancora 4096. Secondo questa risposta CONFIG_HUGETLB_PAGE
è anche necessario che potrei inserire tramite CONFIG_HUGETLBFS
. Sto ricompilando ora e proverò di nuovo.
(3) Ho ricompilato il mio kernel con CONFIG_HUGETLBFS
abilitato e ora /proc/meminfo
contiene il HugePages_*
corrispondente voci menzionate nella sezione corrispondente della documentazione del kernel. Tuttavia, la dimensione della pagina secondo getconf PAGESIZE
è ancora invariato. Quindi, mentre ora dovrei essere in grado di richiedere pagine enormi tramite mmap
chiamate, la dimensione predefinita della pagina del kernel che determina MAX_ARG_STRLEN
è ancora fissato a 4 KB.
(4) Ho modificato linux/include/uapi/linux/binfmts.h
a #define MAX_ARG_STRLEN (PAGE_SIZE * 64)
, ho ricompilato il mio kernel e ora il tuo codice produce:
...
117037
123196
123196
129680
129680
136505
143689
151251
159211
...
227982
227982
239981
239981
252611
252611
265906
./testCL: line 11: ./foo: Argument list too long
279901
./testCL: line 11: ./foo: Argument list too long
294632
./testCL: line 11: ./foo: Argument list too long
Quindi ora il limite è passato da 128 KB a 256 KB come previsto. Non sono a conoscenza di potenziali effetti collaterali. Per quanto ne so, il mio sistema sembra funzionare bene.
Basta inserire gli argomenti in un file e modificare il programma in modo che accetti "argomenti" da un file. Una convenzione comune (utilizzata in particolare da GCC e molti altri programmi GNU) è che un argomento come @/tmp/arglist.txt
chiede al tuo programma di leggere gli argomenti dal file /tmp/arglist.txt
, spesso una riga per argomento
Potresti forse passare alcuni dati attraverso lunghe variabili d'ambiente, ma sono anche limitate (e ciò che è limitato dal kernel infatti è la dimensione di main
stack iniziale di , contenente sia gli argomenti del programma che l'ambiente)
In alternativa, modifica il tuo programma in modo che sia configurabile attraverso un file di configurazione che contenga le informazioni che vuoi passare attraverso gli argomenti.
In altri modi, non c'è modo di aggirare tale limitazione (vedere la pagina man di execve(2) e i suoi Limiti sulla dimensione degli argomenti e dell'ambiente section) - una volta che hai alzato il tuo limite di stack (usando setrlimit(2) con RLIMIT_STACK
, generalmente con ulimit
incorporato nella shell genitore). Devi affrontarlo altrimenti.