Das especificações :
- Se o
bs=
expr
operando for especificado e nenhuma conversão além de sync
, noerror
ou notrunc
for solicitada, os dados retornados de cada bloco de entrada serão gravados como um bloco de saída separado; se o read()
retorno for menor que um bloco completo e a sync
conversão não for especificada, o bloco de saída resultante deverá ter o mesmo tamanho que o bloco de entrada.
Então é provavelmente isso que causa sua confusão. Sim, por dd
ser projetado para bloqueio, por padrão, os parciais read()
s serão mapeados 1: 1 para os parciais write()
, ou então serão sync
preenchidos com NUL de preenchimento de cauda ou caracteres de bs=
tamanho de espaço quando conv=sync
especificados.
Isso significa que dd
é seguro usar para copiar dados (sem risco de corrupção devido a uma leitura ou gravação parcial) em todos os casos, mas aquele em que ele é arbitrariamente limitado por um count=
argumento, porque, caso contrário, dd
será feliz write()
sua saída em blocos de tamanho idêntico para aqueles em que sua entrada era read()
até que ela read()
passasse completamente. E mesmo esta ressalva é verdade apenas quando bs=
for especificado ou obs=
se não especificado, como a próxima sentença nos estados de especificação:
- Se o
bs=
expr
operando não for especificado, ou uma conversão diferente de sync
, noerror
ou notrunc
for solicitada, a entrada deve ser processada e coletada em blocos de saída de tamanho normal até que o final da entrada seja alcançado.
Sem ibs=
e / ou obs=
argumentos, isso não importa - porque ibs
e obs
ambos são do mesmo tamanho por padrão. No entanto, você pode ser explícito sobre o buffer de entrada especificando tamanhos diferentes para um e para não especificar bs=
(porque tem precedência) .
Por exemplo, se você fizer:
IN| dd ibs=1| OUT
... então um POSIX dd
irá write()
em pedaços de 512 bytes, coletando cada read()
byte isolado em um único bloco de saída.
Caso contrário, se você fizer ...
IN| dd obs=1kx1k| OUT
... um POSIX dd
terá read()
no máximo 512 bytes de cada vez, mas write()
cada bloco de saída do tamanho de megabytes (o kernel permite e exceto, possivelmente, o último - porque esse é EOF) por completo, coletando entrada em blocos de saída de tamanho completo .
Também das especificações, no entanto:
count=n
- Copie apenas n blocos de entrada.
count=
mapas para i?bs=
blocos e, portanto, para lidar com um limite arbitrário em count=
portabilidade, você precisará de dois dd
s. A maneira mais prática de fazer isso com dois dd
s é canalizar a saída de um para a entrada de outro, o que certamente nos coloca na área de leitura / gravação de um arquivo especial, independentemente do tipo de entrada original.
Um canal IPC significa que, ao especificar [io]bs=
argumentos que, para fazê-lo com segurança, você deve manter esses valores dentro do PIPE_BUF
limite definido pelo sistema . O POSIX afirma que o kernel do sistema deve garantir apenas atômica read()
s e write()
s dentro dos limites PIPE_BUF
definidos em limits.h
. POSIX garante que PIPE_BUF
seja pelo menos ...
{_POSIX_PIPE_BUF}
- Número máximo de bytes que são garantidos como atômicos ao gravar em um pipe.
- Valor: 512
... (que também é dd
o tamanho de bloco de E / S padrão ) , mas o valor real geralmente é de pelo menos 4k. Em um sistema linux atualizado, é, por padrão, 64k.
Portanto, quando você configura seus dd
processos, deve fazê-lo em um fator de bloco com base em três valores:
- bs = (obs =
PIPE_BUF
ou menor)
- n = número total desejado de bytes lidos
- contagem = n / bs
Gostar:
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
Você precisa sincronizar o i / ow / dd
para manipular entradas não procuráveis. Em outras palavras, torne os buffers de pipe explícitos e eles deixam de ser um problema. É para isso que dd
serve. A quantidade desconhecida aqui é yes
o tamanho do buffer - mas se você bloquear uma quantidade conhecida com outra dd
, uma pequena multiplicação informada poderá ser dd
segura para copiar dados (sem risco de corrupção devido a leitura ou gravação parcial) mesmo ao limitar arbitrariamente a entrada com count=
qualquer tipo de entrada arbitrária em qualquer sistema POSIX e sem perder um único byte.
Aqui está um trecho da especificação POSIX :
ibs=
expr
- Especifique o tamanho do bloco de entrada, em bytes, por (o padrão é 512) .
expr
obs=
expr
- Especifique o tamanho do bloco de saída, em bytes, por (o padrão é 512) .
expr
bs=
expr
- Defina os tamanhos dos blocos de entrada e saída como
expr
bytes, substituindo ibs=
e obs=
. Se nenhuma conversão diferente de sync
, noerror
e notrunc
for especificada, cada bloco de entrada deve ser copiado para a saída como um único bloco sem agregar blocos curtos.
Você também encontrará algumas dessas explicações melhor aqui .