Из спецификации :
- Если
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=переносимость вам понадобится два dds. Наиболее практичный способ сделать это с двумя dds - это передать вывод одного на вход другого, что, несомненно, ставит нас в область чтения / записи специального файла независимо от исходного типа ввода.
Канал 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, каждый входной блок должен быть скопирован на выход как один блок без агрегирования коротких блоков.
Вы также найдете некоторые из этих объяснений лучше здесь .