Cree datos aleatorios con dd y obtenga una "advertencia de lectura parcial". ¿Los datos después de la advertencia ahora son realmente aleatorios?

Cree datos aleatorios con dd y obtenga una "advertencia de lectura parcial". ¿Los datos después de la advertencia ahora son realmente aleatorios?

Creo un archivo de 1TB con datos aleatorios con dd if=/dev/urandom of=file bs=1M count=1000000. Ahora verifico kill -SIGUSR1 <PID>el progreso y obtengo lo siguiente:

691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s

No puedo interpretar la advertencia. ¿Qué dice? ¿Mi archivo es realmente aleatorio después de la advertencia o hay algún problema? ¿Qué significa +0 o +1 en 800950+1 Datensätze einy 800950+0 Datensätze aussignifica? Después de la advertencia es +1. ¿Es un recuento de errores?

Respuesta1

Resumen: ddes una herramienta de mal humor que es difícil de usar correctamente. No lo uses, a pesar de los numerosos tutoriales que así te lo indican. ddtiene una vibra de “credibilidad callejera Unix”, pero si realmente entiendes lo que estás haciendo, sabrás que no deberías tocarlo con un poste de 10 pies.

ddrealiza una única llamada a la readllamada del sistema por bloque (definida por el valor de bs). No hay garantía de que la readllamada al sistema devuelva tantos datos como el tamaño del búfer especificado. Esto tiende a funcionar para archivos normales y dispositivos de bloque, pero no para tuberías y algunos dispositivos de caracteres. Ver¿Cuándo es adecuado dd para copiar datos? (o, cuando son parciales lectura() y escritura())para más información. Si la readllamada al sistema devuelve menos de un bloque completo, ddtransfiere un bloque parcial. Todavía copia la cantidad especificada de bloques, por lo que la cantidad total de bytes transferidos es menor que la solicitada.

La advertencia sobre una "lectura parcial" le dice exactamente esto: una de las lecturas fue parcial, por lo que ddtransfirió un bloque incompleto. En el conteo de bloques, +1significa que un bloque fue leído parcialmente; Dado que el recuento de salida es +0, todos los bloques se escribieron como leídos.

Esto no afecta la aleatoriedad de los datos: todos los bytes que ddse escriben son bytes de los que se lee /dev/urandom. Pero obtuviste menos bytes de los esperados.

Linux /dev/urandomadmite solicitudes grandes y arbitrarias (fuente:extract_entropy_useren drivers/char/random.c), por lo que ddnormalmente es seguro leerlo. Sin embargo, leer grandes cantidades de datos lleva tiempo. Si el proceso recibe una señal, la readllamada al sistema regresa antes de llenar su búfer de salida. Este es un comportamiento normal y se supone que las aplicaciones llaman readen un bucle; ddno hace esto, por razones históricas ( ddlos orígenes de 's son confusos, pero parece haber comenzado como una herramienta para acceder a cintas, que tienen requisitos peculiares, y nunca se adaptó para ser una herramienta de propósito general). Cuando verifica el progreso, esto envía al ddproceso una señal que interrumpe la lectura. Tiene la opción de saber cuántos bytes ddse copiarán en total (asegúrese de no interrumpirlo, sin verificación de progreso, sin suspensión) o saber cuántos bytes ddse han copiado hasta el momento, en cuyo caso no podrá saber cuántos más. bytes que copiará.

la versión dedden GNU coreutils(como se encuentra en Linux no integrado y en Cygwin) tiene un indicador fullblockque indica ddllamar readen un bucle (y lo mismo para write) y, por lo tanto, siempre transferir bloques completos. El mensaje de error sugiere que lo utilice; siempre debe usarlo (tanto en los indicadores de entrada como de salida), excepto en circunstancias muy especiales (principalmente al acceder a cintas); si ddes que lo usa, es decir: generalmente hay mejores soluciones (ver más abajo).

dd if=/dev/urandom iflag=fullblock of=file bs=1M count=1000000

Otra forma posible de estar seguro de lo que ddfuncionará es pasar un tamaño de bloque de 1. Luego podrá saber cuántos bytes se copiaron del recuento de bloques, aunque no estoy seguro de qué sucederá si readse interrumpe a antes de leer el primero. byte (lo cual no es muy probable en la práctica, pero puede suceder). Sin embargo, incluso si funciona, es muy lento.

El consejo general sobre su uso ddesno utilicedd. Aunque dda menudo se anuncia como un comando de bajo nivel para acceder a dispositivos, en realidad no es tal cosa: toda la magia ocurre en la /dev/…parte del archivo del dispositivo (la), ddes solo una herramienta común y corriente con un alto potencial de uso indebido que resulta en pérdida de datos. . En la mayoría de los casos, existe una forma más sencilla y segura de hacer lo que quieras, al menos en Linux.

Por ejemplo, para leer una cierta cantidad de bytes al comienzo de un archivo, simplemente llame a head:

head -c 1000000m </dev/urandom >file

Hice una prueba comparativa rápida en mi máquina y no observé ninguna diferencia de rendimiento entre ddun tamaño de bloque grande y head.

Si necesita omitir algunos bytes al principio, ingrese taila head:

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

Si desea ver el progreso, llame lsofpara ver el desplazamiento del archivo. Esto solo funciona en un archivo normal (el archivo de salida en su ejemplo), no en un dispositivo de caracteres.

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

Puedes llamarpvpara obtener un informe de progreso (mejor que ddel de), a expensas de un elemento adicional en proceso (en cuanto al rendimiento, es apenas perceptible).

Respuesta2

La advertencia ocurre cuando ddno se pudieron obtener suficientes datos para completar un bloque en una sola lectura. Esto sucede con fuentes de datos erráticas o lentas, o fuentes que escriben datos en unidades más pequeñas que el tamaño de bloque solicitado.

No hay ningún problema con la integridad de los datos, pero el problema es que dduna lectura parcial todavía cuenta como un bloque de lectura.

Si no está utilizando la countopción, la advertencia apenas importa, es sólo una consideración de rendimiento. Pero con count, no obtendrá la cantidad de datos que solicitó. Debido a lecturas parciales, ofserá más pequeño que count*bsal final.

Entonces, cuando usas count, técnicamente siempre debes usarlo iflag=fullblocktambién.

Debería +xser el número de bloques parciales.

Respuesta3

< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file

^Eso simplemente funcionará. La información errónea que se tiene aquí es manifiestamente falsa. ddLos buffers sonexplícitoy así, para almacenar en búfer la entrada acontarocurrencias que necesita almacenar en buffer explícitamente. Eso es todo. No compres la mierda.

información relacionada