Estás observando una combinación del comportamiento peculiar de dd
con el peculiar comportamiento del /dev/random
de Linux . Ambos, por cierto, rara vez son la herramienta adecuada para el trabajo.
/dev/random
de Linux devuelve datos con moderación. Se basa en la suposición de que la entropía en el generador de números pseudoaleatorios se extingue a un ritmo muy rápido. Dado que la recopilación de nueva entropía es lenta, /dev/random
normalmente renuncia solo a unos pocos bytes a la vez.
dd
es un programa antiguo y malhumorado inicialmente destinado a operar en dispositivos de cinta. Cuando le dices que lea un bloque de 1kB, intenta leer un bloque. Si la lectura devuelve menos de 1024 bytes, difícil, eso es todo lo que obtienes. Entonces dd if=/dev/random bs=1K count=2
hace dos read(2)
llamadas Ya que está leyendo desde /dev/random
, los dos read
las llamadas generalmente devuelven solo unos pocos bytes, en un número variable según la entropía disponible. Consulte también ¿Cuándo es adecuado dd para copiar datos? (o, cuando son parciales read() y write())
A menos que esté diseñando un instalador o un clonador del sistema operativo, nunca debe usar /dev/random
bajo Linux, siempre /dev/urandom
. El urandom
la página de manual es algo engañosa; /dev/urandom
es de hecho adecuado para la criptografía, incluso para generar claves de larga duración. La única restricción con /dev/urandom
es que debe estar provisto de suficiente entropía; Las distribuciones de Linux normalmente guardan la entropía entre reinicios, por lo que la única vez que puede no tener suficiente entropía es en una instalación nueva. La entropía no desaparece en términos prácticos. Para obtener más información, lea ¿Es seguro un rand de /dev/urandom para una clave de inicio de sesión? y Feeding /dev/random entropy pool?.
La mayoría de los usos de dd
se expresan mejor con herramientas como head
o tail
. Si desea 2kB de bytes aleatorios, ejecute
head -c 2k </dev/urandom >rand
Con kernels de Linux más antiguos, podría salirse con la suya
dd if=/dev/urandom of=rand bs=1k count=2
porque /dev/urandom
felizmente devolvió tantos bytes como se solicitó. Pero esto ya no es cierto desde el kernel 3.16, ahora está limitado a 32 MB.
En general, cuando necesite usar dd
para extraer un número fijo de bytes y su entrada no proviene de un archivo normal o dispositivo de bloque, debe leer byte por byte:dd bs=1 count=2048
.
Desde man 4 random
en una caja RHEL 5:
Cuando se lee, el dispositivo /dev/random solo devolverá bytes aleatorios dentro del número estimado de bits de ruido en el grupo de entropía.
Obtengo archivos de 213 bytes de tamaño en esa máquina. Volver al hombre 4 al azar:
Cuando se lea, el dispositivo /dev/urandom devolverá tantos bytes como se soliciten.
Obtengo 2048 bytes de cada invocación de dd if=/dev/urandom of=rand bs=1K count=2
Concluyo que la diferencia se debe a la cantidad de entropía que genera su máquina entre las invocaciones de dd if=/dev/random ...
¿Por qué dd
soltar datos? ... Guillermo ha planteado esta interesante pregunta sobre dd
:
¿Cuándo es adecuado dd para copiar datos? (o, cuando son lectura() y escritura() parciales)
Aquí hay un extracto de esa pregunta:
*...no es difícil culpar a dd; por ejemplo, prueba este código:**
yes | dd of=out bs=1024k count=10
y verifique el tamaño del archivo de salida (es probable que tenga menos de 10 MB).
Aparte de mi comentario (al final de tu pregunta), algo como esto es interesante de ver... Captura tus bytes en el archivo $trnd
. Elegí semi-arbitrariamente bs=8
Mueve el ratón y observa cómo se acelera.
Con mi computadora inactiva (AFK y sin actividad de red), y después de agotar el grupo de entropía, tomó 2 horas 12 minutos para recoger sólo 1192 bytes, momento en el que lo cancelé.
Luego, mientras movía el mouse continuamente, tomó relativamente mucho menos 1 minuto 15 segundos para recoger el mismo número de bytes.
Esto muestra claramente que la recopilación de entropía no se basa en la velocidad de la CPU, sino en eventos aleatorios. y que mi sistema Ubuntu usa el mouse como uno de sus importantes factores aleatorios.
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"