Из спецификации :
- Если
bs=
expr
операнд определен и никаких преобразований, кроме sync
, noerror
или notrunc
просят, то данные , возвращенные из каждого входного блока должна быть записана в виде отдельного выходного блока; если read()
возвращается меньше, чем полный блок, и sync
преобразование не указано, результирующий выходной блок должен быть того же размера, что и входной блок.
Так что это, вероятно, то, что вызывает ваше замешательство. Да, поскольку dd
он предназначен для блокировки, по умолчанию частичные read()
s будут отображаться в пропорции 1: 1 в частичные write()
s, или же sync
, bs=
если conv=sync
задано значение NUL или символьный пробел в d, если задано.
Это означает , что dd
является безопасным для использования для копирования данных (ж / без риска коррупции из - за частичное чтение или запись) , в каждом случае , кроме одного , в котором она произвольно ограничена по count=
аргументу, поскольку в противном случае dd
будет счастливо write()
его выход в одинаковом размере блоков к тем, в которых вход был read()
до тех пор, пока он read()
полностью не прошел через него. И даже это предостережение только справедливо , если bs=
указан или obs=
в не указан, как следующее предложение в спецификации говорится:
- Если
bs=
expr
операнд не указан, или преобразования, кроме sync
, noerror
или notrunc
запрашиваются, вход должен быть обработан и собран в полноразмерные выходных блоки до конца ввода не будет достигнут.
Без ibs=
и / или obs=
аргументы , это не может дело - потому что ibs
и obs
оба тот же размер по умолчанию. Тем не менее, вы можете получить явные сведения о буферизации ввода, указав разные размеры для каждого и не указав bs=
(потому что это имеет приоритет) .
Например, если вы делаете:
IN| dd ibs=1| OUT
... тогда POSIX dd
будет write()
состоять из 512 байтов, собирая каждый read()
отдельный байт в один выходной блок.
В противном случае, если вы делаете ...
IN| dd obs=1kx1k| OUT
... POSIX dd
будет read()
максимум 512 байт за раз, но write()
каждый выходной блок размером с мегабайт (ядро разрешает и исключает, возможно, последний - потому что это EOF) полностью, собирая входные данные в полноразмерные выходные блоки .
Также из спецификации, хотя:
count=n
- Скопируйте только n входных блоков.
count=
сопоставляется с i?bs=
блоками, и поэтому для обработки произвольного ограничения на count=
переносимость вам понадобится два dd
s. Наиболее практичный способ сделать это с двумя dd
s - это передать вывод одного на вход другого, что, несомненно, ставит нас в область чтения / записи специального файла независимо от исходного типа ввода.
Канал IPC означает, что при указании [io]bs=
аргументов, чтобы сделать это безопасно, вы должны держать такие значения в пределах определенного PIPE_BUF
предела системы. POSIX заявляет, что ядро системы должно гарантировать только атомарные read()
s и write()
s в пределах, PIPE_BUF
определенных в limits.h
. POSIX гарантирует, что PIPE_BUF
будет хотя бы ...
{_POSIX_PIPE_BUF}
- Максимальное количество байтов, которое гарантированно будет атомарным при записи в канал.
- Значение: 512
... (который также является dd
размером блока ввода-вывода по умолчанию ) , но фактическое значение обычно составляет не менее 4k. В современной системе Linux это по умолчанию 64 КБ.
Поэтому, когда вы настраиваете свои dd
процессы, вы должны делать это с блочным фактором на основе трех значений:
- bs = (obs =
PIPE_BUF
или меньше)
- n = общее количество прочитанных байтов
- count = n / bs
Подобно:
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
Вы должны синхронизировать I / OW / dd
для обработки входов без поиска. Другими словами, сделайте конвейерные буферы явными, и они перестанут быть проблемой. Вот для чего dd
. Неизвестное количество здесь - yes
это размер буфера, но если вы заблокируете его в известном количестве с другим, dd
то небольшое информированное умножение может быть dd
безопасно использовано для копирования данных (без риска повреждения из-за частичного чтения или записи) даже когда произвольно ограничивает ввод count=
с любым произвольным типом ввода в любой системе POSIX и не пропускает ни одного байта.
Вот фрагмент из спецификации POSIX :
ibs=
expr
- Укажите размер входного блока в байтах (по умолчанию 512) .
expr
obs=
expr
- Укажите размер выходного блока в байтах (по умолчанию 512) .
expr
bs=
expr
- Установите размеры входного и выходного блоков в
expr
байтах, заменяя ibs=
и obs=
. Если не указано никакого преобразования, кроме sync
, noerror
и notrunc
, каждый входной блок должен быть скопирован на выход как один блок без агрегирования коротких блоков.
Вы также найдете некоторые из этих объяснений лучше здесь .