11

I recently encountered the Linux Null Block device driver, null_blk, while I benchmarking the I/O stack instead of on a specific block device. I found the devices created under this driver (let's use the device name /dev/nullb0 as an example) quite intriguing, especially considering their similarity in name to the /dev/null device. Since I couldn't find any existing questions on this topic from Stackoverflow, I decided to reach out for clarification.

My main question is: what are the differences between the /dev/null and the block device created under the null_blk device driver?


To this point: I've already noticed some distinctions.

  • First, (as far as I understand), the null device /dev/null doesn't go through any driver. However, devices created under null_blk are true block drivers that the data must pass through. I also confirmed this by running fio on both devices; /dev/null performs much better in terms of random read IOPS and submission latency.
  • Second, we know that reading from /dev/null results in an EOF (for example, cat /dev/null), but when I attempt cat /dev/nullb0, it doesn't return an EOF and instead hangs.
  • Additionally, as a side note, the kernel documentation for null_blk mentions parameters for configuration, but I don't see any similar options for /dev/null to be configured.

It seems, large number of differences exist under the similar names. Can someone provide further also formal insights or clarification on these differences? Thanks!

2 Answers 2

21

/dev/null is handled by a device driver, but it’s a very simple one.

The major difference between /dev/null and null_blk is that the former is a character device, the latter a block device. The former handles sequences of characters with direct implementations of the operations invoked by programs using it, without much indirection between a system call using the device and the code implementing the corresponding operation in the driver. The latter is much more complex, and operates on full sectors, with support for command queues etc. There is much more going on to handle any single request.

Of course there is also a major difference in purpose: /dev/null is intended for actual direct use, whereas null_blk is a support feature for kernel developers wanting to benchmark other parts of the block-device-handling stack.

2
  • 3
    IIRC some standard commands special-case /dev/null (eg GNU grep - github.com/BurntSushi/ripgrep/discussions/2717 ) to make things even faster. They don't do this for other device drivers (eg /dev/null_blk)
    – abligh
    Apr 12 at 6:00
  • 2
    LOL. Looking at the grep code, it literally stats both /dev/null and stdout and compares their inodes, to determine whether it's being redirected to /dev/null. That's hilarious. Though, it's worth mentioning that it doesn't do so to speed up the process of writing output — it does it to enable an early exit at the first match, since that's the moment when it can set the process exit code and stop all work. (No point in finding more matches just to output them into a black hole.)
    – FeRD
    Apr 12 at 22:38
16

/dev/null is a "character device", on which all reads return empty and all writes complete fully with no additional side-effects. These are the semantics since V5 UNIX in 1974, and are mandated by POSIX – there is nothing to parameterise about it.

The devices created by the null_blk driver are "block devices", which means they have a fixed size and a caching implication. The devices provided by null_blk ignore all writes and return all zeroes, making them more like /dev/zero.

The purposes of /dev/null and the devices provided by null_blk are different: /dev/null is extremely-well-optimised to return 0 (for reads) or the write size (for writes), since that's all it ever does. Conversely, per the documentation, null_blk

is used for benchmarking the various block-layer implementations

This means it exercises the relevant I/O request management code just as if the request was real, and only then marks the request as completed without actually doing any reads/writes. This means more work per request than /dev/null does, and explains your fio results.

2
  • 1
    Yes. For fio latency test (iodepth=1, numjobs=1), the huge overhead in null_blk in submission latency slat (nsec): min=1873, max=798595, avg=2305.53, stdev=904.17, while the /dev/null superfast slat (nsec): min=520, max=89552, avg=573.89, stdev=135.13. It results in the IOPS and latency difference. (The completion latency of both is in the same level.)
    – JGL
    Apr 10 at 9:08
  • It's actually kind of fascinating how complex the read implementation for /dev/zero actually is, when you compare it to the one for /dev/null which is, in its entirety: return 0;.
    – FeRD
    Apr 12 at 22:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .