When you write a file to a block device, use
oflag=direct. This uses O_DIRECT writes, which avoids using your RAM as a writeback cache. Note that to get good performance,
oflag=direct usually needs a large block size.
This will avoid seeing impossibly fast progress, unless you have a weird device which itself has a very large RAM cache.
A lot of devices have a small amount of cache. In this case
oflag=direct will show a realistic rate of progress. This is more meaningful, but it does not tell you everything you want to know :-). It does not guarantee the last writes are finished when
dd says it is finished. You can make sure all writes are finished - and also check for any write errors - by using the option
conv=fsync. This calls fsync() at the end to make sure the cache is flushed. Here is an example:
dd if=my.iso of=/dev/sdc oflag=direct bs=4M status=progress conv=fsync
Some people run the
sync command afterwards, and understandably do not bother to remember
conv=fsync. This is not quite as good.
sync will not report whether one of the writes failed.
If the device has a very large RAM cache, you would have to use
oflag=direct,sync. But normally I think of
oflag=sync as a potential barrier to performance. You might want to increase the block size even further, to decrease the frequency of cache flushes. When doing very synchronous IO and reading multiple hardware blocks at a time like this, you might want to use double-buffering to maintain good performance, i.e. using a second
dd command as in the link below.
Sometimes you might also want to pipe a disk image from another program, such as
gunzip. In this case, good performance also depends on
iflag=fullblock and piping through another
dd command. There is a full example in the answer here: Why does a gunzip to dd pipeline slow down at the end?