I figure there is a cache somewhere that is holding up the final 5MB but I thought fsync should make sure that doesn't happen
conv=fsync
означает обратную запись всех кэшей путем вызоваfsync
-после того, какdd
запишет все данные. Подвешивание в конце - это именно то, что он будет делать.Если выходной файл медленнее входного, данные, записанные с помощью
dd
, могут накапливаться в кеше. Кэш ядра иногда может занимать значительную часть оперативной памяти системы. Это приводит к очень вводящей в заблуждение информации о прогрессе. Ваши «последние 5 МБ» были просто артефактом того, какdd
показывает прогресс.Если ваша система действительно кэшировала около 8 ГБ (, т.е.половина из 16 ГБ записанных данных ), то я думаю, что у вас либо должно быть около 32 ГБ ОЗУ, либо вы возились с некоторыми параметрами ядра. См. ссылку lwn.net ниже. Я согласен, что не получать никакой информации о прогрессе в течение 15 минут довольно неприятно.
Существуют альтернативные
dd
команды, которые вы можете использовать. Если вы хотите, чтобыdd
отображал более точный прогресс, вам, возможно, придется согласиться с большей сложностью. Я ожидаю, что следующее будет работать без ухудшения вашей производительности, хотя, возможно, у реальности другие идеи, чем у меня.gunzip -c serial2udp.image.gz | dd iflag=fullblock bs=4M | sudo dd iflag=fullblock oflag=direct conv=fsync status=progress bs=4M of=/dev/mmcblk0
oflag=direct iflag=fullblock
позволяет избежать накопления кеша ядра, потому что он полностью обходит его.iflag=fullblock
требуется в такой команде AFAIK (, например. потому что вы читаете из канала и пишете, используя прямой ввод-вывод ). Эффект отсутствияfullblock
— еще одна досадная сложностьdd
. Некоторые сообщения на этом сайте используют это, чтобы доказать, что вы всегда должны использовать другую команду. Однако трудно найти другой способ прямого или синхронизированного ввода-вывода.conv=fsync
по-прежнему следует использовать для обратной записи кэша устройства .- Я добавил дополнительный
dd
послеgunzip
для буферизации распакованного вывода параллельно с записью на диск. Это одна из проблем, которая усложняет работу сoflag=direct
илиoflag=sync
. Обычный ввод-вывод (не -прямой, не -синхронный )не должен нуждаться в этом, так как он уже буферизован кешем ядра. Вам также может не понадобиться дополнительный буфер, если вы записываете на жесткий диск с 4 МБ кеша обратной записи, но я не думаю, что на SD-карте его так много.В качестве альтернативы вы можете использовать
oflag=direct,sync
(и не использоватьconv=fsync
). Это может быть полезно для хорошей информации о прогрессе, если у вас есть странное устройство вывода с сотнями мегабайт кеша . Но обычно я думаю оoflag=sync
как о потенциальном барьере для производительности.Существует статья 2013 года https://lwn.net/Articles/572911/, в которой упоминаются минутные -длительные задержки, подобные вашей.Многие люди считают эту возможность кэширования данных обратной записи на несколько минут нежелательной. Проблема заключалась в том, что ограничение на размер кэша применялось без разбора, как к быстрым, так и к медленным устройствам. Обратите внимание, что для ядра -непросто измерить скорость устройства, поскольку она зависит от местоположения данных. Например. если кэшированные записи разбросаны в случайных местах, жесткому диску потребуется больше времени на многократное перемещение записывающей головки.
why do the updates hang
fsync()
— это единый системный вызов, который применяется ко всему диапазону устройствафайла. Он не возвращает никаких обновлений статуса до того, как это будет сделано.
Как объясняется в комментариях, ${x:?}
сам по себе не может этого сделать. Однако то, что вы хотите, можно легко сделать с помощью условного оператора:
% sth() { [[ -n $1 ]] || return; local url="$1" }
% sth; print $?
1