As others have noted, this reads from an infinite supply of zeros, and writes to a pseudodevice that discards whatever is written.
A good way to understand what's happening in a case like this in to run it under strace:
% strace -T dd if=/dev/zero of=/dev/null bs=50M count=1
Skipping some startup and shutdown system calls, the heart of what this does is
openat(AT_FDCWD, "/dev/zero", O_RDONLY) = 3 <0.000049>
...
openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 ...
mmap(NULL, 52441088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd61de31000 <0.000046>
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 52428800) = 52428800 <0.070642>
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 52428800) = 52428800 <0.001773>
close(0) = 0 <0.000040>
close(1) = 0 <0.000031>
That is:
openat
to open the two devices for read and write respectively.
mmap
to allocate a writable 50M buffer.
- One big
read
and then one big write
.
- Close the files and exit.
Also interesting in this is that the read
(at 70ms on this slow machine, shown at the right of the log) is significantly slower than the write
(1ms). The read
needs to write zeros over 50MB of process memory. The write
, just needs to work out that it's writing to /dev/null
and then return success, without actually touching the data.
An interesting thing about this is that strace will actually do the reads and writes, even though from a certain point of view it ought to "know" that /dev/zero
will always give zeros and writes to /dev/null
are always pointless. (It could be argued that this is useful for benchmarking, but it's a rather unrepresentative benchmark.)
For example if you use sudo strace -T dd if=/dev/zero of=/dev/sdasomething
to wipe a disk, you can see it does spend a percentage of its time pointlessly reading pages and pages of zeros from the kernel, instead of allocating zeros once and writing them repeatedly.
/dev/null
is a good destination for testing/timing read operations./dev/zero
is a good source for testing/timing write operations. Combining this source and destination in one operation doesn't make much sense. Not even sure if this provides any meaningful overhead number.