Stai osservando una combinazione del comportamento peculiare di dd
con il comportamento peculiare di /dev/random
di Linux . Entrambi, tra l'altro, raramente sono lo strumento giusto per il lavoro.
/dev/random
di Linux restituisce i dati con parsimonia. Si basa sul presupposto che l'entropia nel generatore di numeri pseudocasuali si estingua a una velocità molto elevata. Poiché la raccolta di nuova entropia è lenta, /dev/random
in genere rinuncia solo a pochi byte alla volta.
dd
è un programma vecchio e irritabile inizialmente destinato a funzionare su dispositivi a nastro. Quando gli dici di leggere un blocco di 1kB, tenta di leggere un blocco. Se la lettura restituisce meno di 1024 byte, duro, è tutto ciò che ottieni. Quindi dd if=/dev/random bs=1K count=2
fa due read(2)
chiamate. Dal momento che sta leggendo da /dev/random
, i due read
le chiamate in genere restituiscono solo pochi byte, in numero variabile a seconda dell'entropia disponibile. Vedi anche Quando dd è adatto per copiare i dati? (o, quando read() e write() sono parziali)
A meno che tu non stia progettando un programma di installazione o clonazione del sistema operativo, non dovresti mai usare /dev/random
sotto Linux, sempre /dev/urandom
. Il urandom
la pagina man è in qualche modo fuorviante; /dev/urandom
è infatti adatto alla crittografia, anche per generare chiavi di lunga durata. L'unica restrizione con /dev/urandom
è che deve essere fornito di sufficiente entropia; Le distribuzioni Linux normalmente salvano l'entropia tra i riavvii, quindi l'unica volta in cui potresti non avere abbastanza entropia è su una nuova installazione. L'entropia non svanisce in termini pratici. Per ulteriori informazioni, leggi È sicuro un rand da /dev/urandom per una chiave di accesso? e Feeding /dev/random entropy pool?.
La maggior parte degli usi di dd
sono meglio espressi con strumenti come head
o tail
. Se vuoi 2kB di byte casuali, esegui
head -c 2k </dev/urandom >rand
Con i vecchi kernel Linux, potresti farla franca
dd if=/dev/urandom of=rand bs=1k count=2
perché /dev/urandom
felicemente restituito tutti i byte richiesti. Ma questo non è più vero dal kernel 3.16, ora è limitato a 32 MB.
In generale, quando devi usare dd
per estrarre un numero fisso di byte e il suo input non proviene da un normale file o dispositivo a blocchi, devi leggere byte per byte:dd bs=1 count=2048
.
Da man 4 random
su una scatola RHEL 5:
Una volta letto, il dispositivo /dev/random restituirà solo byte casuali all'interno del numero stimato di bit di rumore nel pool di entropia.
Ottengo file di dimensioni 213 byte su quella macchina. Torna all'uomo 4 casuale:
Una volta letto, /dev/urandom device restituirà tutti i byte richiesti.
Ottengo 2048 byte da ogni invocazione di dd if=/dev/urandom of=rand bs=1K count=2
Concludo che la differenza è dovuta a quanta entropia genera la tua macchina tra le invocazioni di dd if=/dev/random ...
Perché dd
eliminare i dati? ... Gilles ha posto questa interessante domanda su dd
:
Quando dd è adatto per copiare i dati? (o, quando read() e write() sono parziali)
Ecco un estratto della domanda:
*...non è difficile incolpare dd; per esempio prova questo codice:**
yes | dd of=out bs=1024k count=10
e controlla la dimensione del file in uscita (è probabile che sia ben al di sotto dei 10 MB).
A parte il mio commento (alla fine della tua domanda), qualcosa del genere è interessante da guardare... Cattura i tuoi byte nel file $trnd
. Ho scelto in modo semi-arbitrario bs=8
Muovi il mouse e guardalo accelerare.
Con il mio computer inattivo (AFK e nessuna attività di rete) e dopo aver esaurito il pool di entropia, ci sono volute 2 ore 12 minuti per raccogliere solo 1192 bytes, a quel punto l'ho cancellato.
Poi, muovendo continuamente il mouse, ci sono voluti 1 minuto relativamente molto più breve 15 secondi per raccogliere lo stesso numero di byte.
Ciò mostra abbastanza chiaramente che la raccolta di entropia non è basata sulla velocità della CPU, ma piuttosto su eventi casuali e che il mio sistema Ubuntu usa il mouse come uno dei suoi significativi fattori casuali.
get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
echo -n "itt: $((i+=1)) ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"