De la especificación :
- Si
bs=
expr
se especifica el operando y no se solicitan conversiones que no sean sync
, noerror
o notrunc
se soliciten, los datos devueltos de cada bloque de entrada se escribirán como un bloque de salida separado; Si el read()
retorno es inferior a un bloque completo y sync
no se especifica la conversión, el bloque de salida resultante será del mismo tamaño que el bloque de entrada.
Entonces esto es probablemente lo que causa tu confusión. Sí, debido a que dd
está diseñado para el bloqueo, de manera predeterminada, los read()
s parciales se asignarán 1: 1 a write()
s parciales , o bien se sync
dotarán de NUL de relleno de cola o caracteres de espacio bs=
cuando conv=sync
se especifique.
Esto significa que dd
es seguro de usar para copiar datos (sin riesgo de corrupción debido a una lectura o escritura parcial) en todos los casos, excepto uno en el que está limitado arbitrariamente por un count=
argumento, porque de lo contrario dd
felizmente write()
su salida en bloques de tamaño idéntico a aquellos en los que su entrada fue read()
hasta que read()
la atravesó por completo. E incluso esta advertencia es sólo es cierto cuando bs=
se especifica o obs=
se no se especifica, como el siguiente oración en los estados de especificaciones:
- Si
bs=
expr
no se especifica el operando , o si se solicita una conversión diferente a sync
, noerror
o notrunc
se solicita, la entrada se procesará y se recopilará en bloques de salida de tamaño completo hasta llegar al final de la entrada.
Sin ibs=
y / o obs=
argumentos esto no puede importa - porque ibs
y obs
son a la vez el mismo tamaño por defecto. Sin embargo, puede ser explícito sobre el almacenamiento en búfer de entrada especificando diferentes tamaños para cualquiera y no especificando bs=
(porque tiene prioridad) .
Por ejemplo, si haces:
IN| dd ibs=1| OUT
... entonces un POSIX lo dd
hará write()
en fragmentos de 512 bytes al recopilar cada read()
byte individualmente en un solo bloque de salida.
De lo contrario, si lo haces ...
IN| dd obs=1kx1k| OUT
... un POSIX dd
tendrá read()
un máximo de 512 bytes a la vez, pero write()
cada bloque de salida de un tamaño de megabyte (el kernel permite y exceptúa posiblemente el último, porque eso es EOF) completo al recopilar la entrada en bloques de salida de tamaño completo .
Sin embargo, también de la especificación:
count=n
- Copie solo n bloques de entrada.
count=
asigna a i?bs=
bloques, por lo que para manejar un límite arbitrario de forma count=
portátil necesitarás dos dd
s. La forma más práctica de hacerlo con dos dd
s es canalizando la salida de uno en la entrada de otro, lo que seguramente nos coloca en el ámbito de la lectura / escritura de un archivo especial independientemente del tipo de entrada original.
Una tubería IPC significa que al especificar [io]bs=
argumentos que, para hacerlo de manera segura, debe mantener dichos valores dentro del PIPE_BUF
límite definido del sistema . POSIX establece que el núcleo del sistema sólo debe garantizar atómicas read()
s y write()
s dentro de los límites de PIPE_BUF
como se define en limits.h
. POSIX garantiza que PIPE_BUF
sea al menos ...
{_POSIX_PIPE_BUF}
- Número máximo de bytes que se garantiza que son atómicos cuando se escribe en una tubería.
- Valor: 512
... (que también es el dd
tamaño de bloque de E / S predeterminado ) , pero el valor real suele ser al menos 4k. En un sistema Linux actualizado es, por defecto, 64k.
Entonces, cuando configura sus dd
procesos, debe hacerlo en un factor de bloque basado en tres valores:
- bs = (obs =
PIPE_BUF
o menor)
- n = número total deseado de bytes leídos
- cuenta = n / bs
Me gusta:
yes | dd obs=1k | dd bs=1k count=10k of=/dev/null
10240+0 records in
10240+0 records out
10485760 bytes (10 MB) copied, 0.1143 s, 91.7 MB/s
Tiene que sincronizar i / ow / dd
para manejar entradas no buscables. En otras palabras, haga explícitos los amortiguadores de tubería y dejarán de ser un problema. Para eso dd
es eso . La cantidad desconocida aquí es yes
el tamaño del búfer, pero si bloquea eso a una cantidad conocida con otra, dd
entonces una pequeña multiplicación informada puede ser dd
segura de usar para copiar datos (sin riesgo de corrupción debido a una lectura o escritura parcial) incluso cuando limite arbitrariamente la entrada con count=
cualquier tipo de entrada arbitraria en cualquier sistema POSIX y sin perder un solo byte.
Aquí hay un fragmento de la especificación POSIX :
ibs=
expr
- Especifique el tamaño del bloque de entrada, en bytes, por (el valor predeterminado es 512) .
expr
obs=
expr
- Especifique el tamaño del bloque de salida, en bytes, por (el valor predeterminado es 512) .
expr
bs=
expr
- Establezca los tamaños de bloque de entrada y salida en
expr
bytes, reemplazando ibs=
y obs=
. Si no se especifica otra conversión que sync
, noerror
y notrunc
se especifica, cada bloque de entrada se copiará a la salida como un bloque único sin agregar bloques cortos.
También encontrarás algo de esto mejor explicado aquí .