在我当前的 Linux 系统(Debian Jessie amd64)上,我得到了不同的dd
使用行为/dev/urandom
(/dev/random
行为已正确记录)。如果我天真地想要 1G 的随机数据:
$ dd if=/dev/urandom of=random.raw bs=1G count=1
0+1 records in
0+1 records out
33554431 bytes (34 MB) copied, 2.2481 s, 14.9 MB/s
$ echo $?
0
在这种情况下,仅存储 34MB 的随机数据,而如果我使用多次读取:
$ dd if=/dev/urandom of=random.raw bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB) copied, 70.4749 s, 14.9 MB/s
然后我就正确地得到了我的1G随机数据。
其文档/dev/urandom
相当难以捉摸:
从 /dev/urandom 设备读取不会阻塞等待更多熵。因此,如果熵池中没有足够的熵,则返回的值理论上很容易受到驱动程序使用的算法的加密攻击。目前的非机密文献中还没有关于如何做到这一点的知识,但理论上这种攻击可能存在。如果这是您的应用程序中的一个问题,请改用 /dev/random。
我猜文档暗示存在某种最大读取大小urandom
。
我还猜测我的系统上熵池的大小为 34MB,这可以解释为什么第一个read
1G 在大约 34MB 时失败。
但我的问题是我如何知道熵池的大小?或者被dd
另一个因素阻止(某种与 相关的计时问题urandom
?)。
答案1
如果你检查从 /dev/urandom 读取 33554431 字节后给出 EOF并遵循讨论,它指出另一个错误报告特德·曹 (Ted Tso) 指出...
...提交 79a8468747c5 导致读取大于 32MB,导致 read(2) 系统调用仅返回 32MB。也就是说,它会导致短读。 POSIX 始终允许短读取(2),并且任何程序都必须检查短读取。
dd 的问题是 POSIX 需要 count=X 参数,基于读取,而不是字节。这可以通过 iflag=fullblock 进行更改。
按照gnu dd
手动的:
Note if the input may return short reads as could be the case when reading from
a pipe for example, ‘iflag=fullblock’ will ensure that ‘count=’ corresponds to
complete input blocks rather than the traditional POSIX specified behavior of
counting input read operations.
所以如果你添加iflag=fullblock
:
dd if=/dev/urandom of=random.raw bs=1G count=1 iflag=fullblock
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB) copied, 65.3591 s, 16.4 MB/s
这实际上得到了确认dd
,如果您省略iflag
并增加读取的计数32
,即大致的字节数32
x
33554431
(或乘法后缀上的每个页面部分),它将输出一个简短的警告:=
1073741792
1G
1.1GB
dd
man
dd if=/dev/urandom of=random.raw bs=1G count=32
dd: warning: partial read (33554431 bytes); suggest iflag=fullblock
0+32 records in
0+32 records out
1073741792 bytes (1.1 GB) copied, 59.6676 s, 18.0 MB/s
答案2
我以前没有意识到 urandom 的这种奇怪之处,但是你遇到了 dd 的“短读”。看:
dd什么时候适合复制数据? (或者,什么时候 read() 和 write() 是部分的)
在第一个示例中,您所做的是要求内核在一次 read() 调用中使用随机数据填充 1GB 内存。由于内存是延迟分配的,因此您实质上是要求内核在第一次调用时向您的进程分配 1GB 内存。他们提早停止的原因可能有很多。另外,如果它按照您的要求进行操作,您可能会耗尽内存,具体取决于您正在尝试的系统。
哦,我怀疑这和你的熵池有什么关系。 urandom 很有用,因为即使熵池耗尽,它也会继续返回数据。