GNU/Linux >> Linux Esercitazione >  >> Linux

Cosa definisce la dimensione massima per un singolo argomento di comando?

Avevo l'impressione che la lunghezza massima di un singolo argomento non fosse il problema qui tanto quanto la dimensione totale dell'array di argomenti generale più la dimensione dell'ambiente, che è limitata a ARG_MAX . Così ho pensato che qualcosa come il seguente avrebbe avuto successo:

env_size=$(cat /proc/$$/environ | wc -c)
(( arg_size = $(getconf ARG_MAX) - $env_size - 100 ))
/bin/echo $(tr -dc [:alnum:] </dev/urandom | head -c $arg_size) >/dev/null

Con il - 100 essendo più che sufficiente per spiegare la differenza tra la dimensione dell'ambiente nella shell e l'echo processi. Invece ho ricevuto l'errore:

bash: /bin/echo: Argument list too long

Dopo aver giocato per un po', ho scoperto che il massimo era un ordine di grandezza esadecimale più piccolo:

/bin/echo 
  $(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) 
  >/dev/null

Quando il meno uno viene rimosso, l'errore ritorna. Apparentemente il massimo per un singolo argomento è in realtà ARG_MAX/16 e il -1 rappresenta il byte null posto alla fine della stringa nell'array di argomenti.

Un altro problema è che quando l'argomento viene ripetuto, la dimensione totale dell'array di argomenti può essere più vicina a ARG_MAX , ma non è ancora lì:

args=( $(tr -dc [:alnum:] </dev/urandom | head -c $(($(getconf ARG_MAX)/16-1))) )
for x in {1..14}; do
  args+=( ${args[0]} )
done

/bin/echo "${args[@]}" "${args[0]:6534}" >/dev/null

Usando "${args[0]:6533}" qui rende l'ultimo argomento più lungo di 1 byte e fornisce la Argument list too long errore. È improbabile che questa differenza sia spiegata dalla dimensione dell'ambiente data:

$ cat /proc/$$/environ | wc -c
1045

Domande:

  1. Si tratta di un comportamento corretto o c'è un bug da qualche parte?
  2. Se no, questo comportamento è documentato da qualche parte? Esiste un altro parametro che definisce il massimo per un singolo argomento?
  3. Questo comportamento è limitato a Linux (o anche a versioni particolari di tale)?
  4. Cosa spiega la discrepanza aggiuntiva di circa 5 KB tra la dimensione massima effettiva dell'array di argomenti più la dimensione approssimativa dell'ambiente e ARG_MAX ?

Informazioni aggiuntive:

uname -a
Linux graeme-rock 3.13-1-amd64 #1 SMP Debian 3.13.5-1 (2014-03-04) x86_64 GNU/Linux

Risposta accettata:

Risposte

  1. Sicuramente non è un bug.
  2. Il parametro che definisce la dimensione massima per un argomento è MAX_ARG_STRLEN . Non c'è documentazione per questo parametro oltre ai commenti in 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
    

    Come mostrato, Linux ha anche un limite (molto grande) al numero di argomenti per un comando.

  3. Un limite alla dimensione di un singolo argomento (che differisce dal limite generale per argomenti più ambiente) sembra essere specifico di Linux. Questo articolo fornisce un confronto dettagliato di ARG_MAX ed equivalenti su sistemi simili a Unix. MAX_ARG_STRLEN viene discusso per Linux, ma non viene menzionato alcun equivalente su nessun altro sistema.

    L'articolo precedente afferma anche che MAX_ARG_STRLEN è stato introdotto in Linux 2.6.23, insieme a una serie di altre modifiche relative ai massimi degli argomenti dei comandi (discussi di seguito). Il log/diff per il commit può essere trovato qui.

  4. Non è ancora chiaro cosa spieghi l'ulteriore discrepanza tra il risultato di getconf ARG_MAX e la dimensione massima effettiva possibile degli argomenti più l'ambiente. La risposta correlata di Stephane Chazelas suggerisce che parte dello spazio è rappresentato da puntatori a ciascuna delle stringhe argomento/ambiente. Tuttavia, la mia indagine suggerisce che questi puntatori non vengono creati all'inizio di execve chiamata di sistema quando potrebbe ancora restituire un E2BIG errore nel processo di chiamata (sebbene i puntatori a ogni argv le stringhe vengono sicuramente create in seguito).

    Inoltre, le stringhe sono contigue nella memoria per quanto posso vedere, quindi nessun vuoto di memoria dovuto all'allineamento qui. Anche se è molto probabile che sia un fattore all'interno di ciò che fa consuma la memoria extra. Capire cosa utilizza lo spazio extra richiede una conoscenza più dettagliata di come il kernel alloca la memoria (che è una conoscenza utile da avere, quindi indagherò e aggiornerò in seguito).

Correlati:qual è la differenza tra punto e virgola e doppia e&&?

ARG_MAX Confusione

Da Linux 2.6.23 (come risultato di questo commit), ci sono state modifiche al modo in cui vengono gestiti i massimi degli argomenti dei comandi che rendono Linux diverso da altri sistemi simili a Unix. Oltre ad aggiungere MAX_ARG_STRLEN e MAX_ARG_STRINGS , il risultato di getconf ARG_MAX ora dipende dalla dimensione dello stack e potrebbe essere diverso da ARG_MAX in limits.h .

Normalmente il risultato di getconf ARG_MAX sarà 1/4 della dimensione della pila. Considera quanto segue in bash usando ulimit per ottenere la dimensione dello stack:

$ echo $(( $(ulimit -s)*1024 / 4 ))  # ulimit output in KiB
2097152
$ getconf ARG_MAX
2097152

Tuttavia, il comportamento di cui sopra è stato leggermente modificato da questo commit (aggiunto in Linux 2.6.25-rc4~121). ARG_MAX in limits.h ora funge da limite inferiore rigido sul risultato di getconf ARG_MAX . Se la dimensione dello stack è impostata in modo tale che 1/4 della dimensione dello stack è inferiore a ARG_MAX in limits.h , quindi limits.h verrà utilizzato il valore:

$ grep ARG_MAX /usr/include/linux/limits.h 
#define ARG_MAX       131072    /* # bytes of args + environ for exec() */
$ ulimit -s 256
$ echo $(( $(ulimit -s)*1024 / 4 ))
65536
$ getconf ARG_MAX
131072

Nota anche che se la dimensione dello stack è inferiore al minimo possibile ARG_MAX , quindi la dimensione dello stack (RLIMIT_STACK ) diventa il limite superiore della dimensione dell'argomento/ambiente prima di E2BIG viene restituito (sebbene getconf ARG_MAX mostrerà comunque il valore in limits.h ).

Un'ultima cosa da notare è che se il kernel è compilato senza CONFIG_MMU (supporto per hardware di gestione della memoria), quindi il controllo di ARG_MAX è disabilitato, quindi il limite non si applica. Sebbene MAX_ARG_STRLEN e MAX_ARG_STRINGS si applicano ancora.

Ulteriori letture

  • Risposta correlata di Stephane Chazelas – https://unix.stackexchange.com/a/110301/48083
  • In una pagina dettagliata che copre la maggior parte di quanto sopra. Include una tabella di ARG_MAX (ed equivalenti) valori su altri sistemi simili a Unix – http://www.in-ulm.de/~mascheck/various/argmax/
  • Apparentemente l'introduzione di MAX_ARG_STRLEN ha causato un bug in Automake che incorporava script di shell in Makefiles usando sh -c – http://www.mail-archive.com/[email protetta]/msg05522.html

Linux
  1. Necessità del builtin "costruito"?

  2. Qual è la dimensione massima del valore di una variabile di ambiente Linux?

  3. Come trovo la dimensione massima dello stack?

  4. A cosa serve il test di Linux:un test di comando?

  5. Modificato il PERCORSO, ora ricevo il comando non trovato per tutto

Cos'è il comando Linux Watch + Esempi

Qual è il comando kill in Linux?

qual è il comando più affidabile per trovare la dimensione effettiva di un file linux

Qual è lo scopo di cd ` (backtick)?

Qual è il numero massimo di porte?

Come determinare la migliore dimensione in byte per il comando dd