命令中发生了什么
sudo dd if=/dev/zero of=/dev/null bs=500M count=1.
这些零到底去哪儿了?一般情况下会发生什么?速度是 905 MB/s
如果我将其复制到 ramdisk,速度只有 388 MB/s。如果我dd
将其复制到 hdd,速度只有 63.2 MB/s
答案1
/dev/zero
读取时提供无限的零字节流。此功能由内核提供,不需要分配内存。所有写入/dev/null
都会被默默丢弃。
因此,当您执行 时dd
,系统会生成 500 兆字节的零字节,这些字节会被丢弃。除了临时缓冲区外,在此操作之前、期间或之后不会存储任何数据。
/dev/zero
从到 的传输速度/dev/null
主要取决于处理器和相关系统调用的速度。(在您的例子中,缓冲区为 500 MB,因此该操作也会测试内存的速度。)
答案2
我会为你翻译这个命令:
dd if=/dev/zero of=/dev/null bs=500M count=1
使用 500M 大小的块(= 块大小)将数据( )从(虚拟无限供应)的dd
输入文件( )复制到(虚拟天坑)的输出文件()中,并重复此操作( )一次()。if
/dev/zero
0
of
/dev/null
bs
count
1
一般来说,此命令应该只测量内存和总线速度。但是,如果您没有 500MB 的可用 RAM,它可能会失败。因此,从某种意义上说,它还隐式地衡量了您的操作系统分配大内存块的速度。
答案3
答案4
正如其他人所指出的,这将从无限的零中读取,并写入丢弃所有写入内容的伪设备。
了解此类情况下发生的情况的一个好方法是在 strace 下运行它:
% strace -T dd if=/dev/zero of=/dev/null bs=50M count=1
跳过一些启动和关闭系统调用,其核心功能是
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>
那是:
openat
分别打开两个设备进行读写。mmap
分配一个可写的 50M 缓冲区。- 一个大
read
,然后又一个大write
。 - 关闭文件并退出。
另一个有趣的地方是read
(在这台慢速机器上为 70ms,如日志右侧所示)明显慢于write
(1ms)。read
需要在 50MB 的进程内存上写入零。write
只需要确定它正在写入的内容/dev/null
,然后返回成功,而无需实际接触数据。
有趣的是,strace 实际上会执行读取和写入操作,尽管从某种角度来看,它应该“知道”结果/dev/zero
始终为零,而写入/dev/null
始终毫无意义。(有人可能会说这对于基准测试很有用,但这是一个相当不具代表性的基准测试。)
例如如果你用它sudo strace -T dd if=/dev/zero of=/dev/sdasomething
来擦除磁盘,你会发现它确实花费了一定比例的时间无意义地从内核读取一页又一页的零,而不是分配一次零并重复写入它们。