You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何dd读取/dev/random与/dev/urandom时会在32MiB处停止

问题原因底层解释

这个现象是dd默认行为逻辑和Linux内核随机数设备的硬限制两个机制共同作用的结果,和发行版无关,所有使用5.x版本左右主线内核的Linux发行版都会复现该问题:

1. dd的默认读写逻辑

dd默认不会保证单次读请求凑满你指定的bs(块大小):

  • 每次调用read()系统调用时,传入你指定的bs值作为要读取的目标长度
  • 只要read()返回值大于0,不管返回的长度是否达到bs,dd都会将这次返回的内容视为一个输入块,不会自动发起额外read()补全剩余长度
  • 输出中的X+Y records in含义是:总共读到X个满大小的完整块,Y个未达到bs大小的部分块
    你看到的0+1 records in就表示:没有读到任何完整的满大小块,只读到1个长度不足bs的部分块。

注意:普通文件、块设备的read()实现通常会尽量填满请求的缓冲区,因此很少触发部分读问题;但字符设备、管道、Socket这类流式文件的read()不保证返回满长度,是这类问题的高发场景。

2. /dev/random、/dev/urandom的单次读上限

这两个字符设备共享内核中同一套随机数读实现逻辑,为了避免单个长读请求长时间占用CPU、阻塞其他进程对随机数设备的访问,上游内核在驱动中写死了单次read()调用的最大返回长度:33554431字节(即32MiB - 1)。
只要你发起的读请求长度超过这个数值,驱动单次最多只会返回33554431字节,剩余的数据需要再次发起read()调用才能获取。

3. 现象匹配逻辑

两个机制叠加后完全匹配你测试的结果:

  • 当设置的bs <= 32MiB -1(比如你测试的10M):单次read()就能返回完整的bs长度数据,dd统计到1个完整块,输出1+0 records in/out,符合预期
  • 当设置的bs > 32MiB -1(比如1G、100M、50M、33M):单次read()最多返回33554431字节,长度小于你指定的bs,dd默认不补读,加上你设置了count=1,读到1个块(哪怕是部分块)就直接退出,因此输出0+1 records in/out,总拷贝大小固定为33554431字节。
解决/验证方法

所有读字符设备、管道、socket这类不保证单次read()返回满长度数据的场景,使用dd时加上iflag=fullblock参数即可,该参数会让dd在单次read()返回长度不足时,持续发起read()调用直到凑满整个bs大小,或者读到文件末尾。
你可以执行以下命令验证,会正常读满1G数据并输出1+0 records in/out:

dd if=/dev/urandom of=/dev/null status=progress bs=1G count=1 iflag=fullblock

你也可以测试刚好等于上限的块大小bs=33554431,不需要加fullblock也能返回1+0的正常结果。


内容的提问来源于stack exchange,提问作者user19264607

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:24:20