Чтобы увидеть, что происходит, давайте посмотрим на вывод strace
для аналогичного вызова:
execve("/bin/dd", ["dd", "of=X", "bs=1M", "count=2"], [/* 72 vars */]) = 0
…
read(0, "testing\ntesting\ntesting\ntesting\n"..., 1048576) = 69632
write(1, "testing\ntesting\ntesting\ntesting\n"..., 69632) = 69632
read(0, "testing\ntesting\ntesting\ntesting\n"..., 1048576) = 8192
write(1, "testing\ntesting\ntesting\ntesting\n"..., 8192) = 8192
close(0) = 0
close(1) = 0
write(2, "0+2 records in\n0+2 records out\n", 31) = 31
write(2, "77824 bytes (78 kB) copied", 26) = 26
write(2, ", 0.000505796 s, 154 MB/s\n", 26) = 26
…
В результате dd
делает одиночный read()
вызов для чтения каждого блока. Это уместно при чтении с ленты, для которой изначально использовался dd
. На лентах read
действительно читает блок. При чтении из файла вы должны быть осторожны, чтобы не указывать слишком большой размер блока, иначе read
будет усечен. При чтении из канала хуже: размер читаемого блока будет зависеть от скорости команды, производящей данные.
Мораль этой истории не в том, чтобы использовать dd
для копирования данных, за исключением безопасных небольших блоков. И никогда из трубы, кроме как с bs=1
.
(GNU dd имеет флаг fullblock
, указывающий, что он должен вести себя достойно. Но другие реализации этого не делают.)