我最近遇到了Linux 空块设备驱动程序,null_blk
同时我对 I/O 堆栈而不是特定的块设备进行基准测试。我发现在此驱动程序下创建的设备(让我们使用设备名称/dev/nullb0
作为示例)非常有趣,特别是考虑到它们的名称与/dev/null
设备的相似性。由于我找不到有关该主题的任何现有问题,因此我决定寻求澄清。
我的主要问题是:和设备驱动程序下创建的块设备有什么区别?/dev/null
null_blk
到目前为止:我已经注意到了一些区别。
- 首先,(据我了解),空设备
/dev/null
不经过任何驱动程序。但是,在其下创建的设备null_blk
是数据必须经过的真正的块驱动程序。我还通过fio
在两台设备上运行来证实了这一点;/dev/null
在随机读取 IOPS 和提交延迟方面表现更好。 - 其次,我们知道读取
/dev/null
会产生 EOF(例如,cat /dev/null
),但当我尝试 时cat /dev/nullb0
,它不会返回 EOF 而是挂起。 - 此外,作为旁注,内核文档提到了
null_blk
配置参数,但我没有看到任何类似的/dev/null
配置选项。
看来,相似的名字下却存在着很大的差异。有人可以对这些差异提供进一步的正式见解或澄清吗?谢谢!
/dev/null
由设备驱动程序处理,但它非常简单。/dev/null
和 的主要区别在于null_blk
前者是字符设备,后者是块设备。前者通过直接实现由使用它的程序调用的操作来处理字符序列,而在使用设备的系统调用和在驱动程序中实现相应操作的代码之间没有太多间接。后者要复杂得多,并且在整个扇区上运行,并支持命令队列等。处理任何单个请求还有更多的事情要做。当然,目的也有一个主要区别:
/dev/null
旨在实际直接使用,而它null_blk
是为想要对块设备处理堆栈的其他部分进行基准测试的内核开发人员提供的支持功能。/dev/null
是一个“字符设备”,所有读取都返回空,所有写入完全完成,没有额外的副作用。这些是自 1974 年 V5 UNIX 以来的语义,并且由 POSIX 强制执行 - 没有任何参数可以对其进行参数化。驱动程序创建的设备
null_blk
是“块设备”,这意味着它们具有固定的大小和缓存含义。提供的设备null_blk
忽略所有写入并返回所有零,使它们更像/dev/zero
.的目的
/dev/null
和提供的设备null_blk
是不同的:/dev/null
经过极其优化,返回 0(用于读取)或写入大小(用于写入),因为这就是它所做的一切。相反,根据文档,null_blk
这意味着它会像请求是真实的一样执行相关的 I/O 请求管理代码,然后才将请求标记为已完成,而不实际执行任何读/写操作。这意味着每个请求需要做更多的工作
/dev/null
,并解释了您的fio
结果。