Das especificações :
- Se o
bs=exproperando for especificado e nenhuma conversão além de sync, noerrorou notruncfor 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 syncconversã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 ddser projetado para bloqueio, por padrão, os parciais read()s serão mapeados 1: 1 para os parciais write(), ou então serão syncpreenchidos com NUL de preenchimento de cauda ou caracteres de bs=tamanho de espaço quando conv=syncespecificados.
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, ddserá 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=exproperando não for especificado, ou uma conversão diferente de sync, noerrorou notruncfor 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 ibse obsambos 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 ddirá 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 ddterá 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 dds. A maneira mais prática de fazer isso com dois dds é 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_BUFlimite 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_BUFdefinidos em limits.h. POSIX garante que PIPE_BUFseja 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 é ddo 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 ddprocessos, deve fazê-lo em um fator de bloco com base em três valores:
- bs = (obs =
PIPE_BUFou 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 / ddpara 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 ddserve. A quantidade desconhecida aqui é yeso 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
exprbytes, substituindo ibs=e obs=. Se nenhuma conversão diferente de sync, noerrore notruncfor 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 .