为什么 dd from /dev/random 给出不同的文件大小?

Dan*_*iel 35 linux dd random

我在 ubuntu 系统上运行以下命令:

dd if=/dev/random of=rand bs=1K count=2
Run Code Online (Sandbox Code Playgroud)

但是,每次运行它时,我都会得到一个不同大小的文件。为什么是这样?如何生成填充随机数据的给定大小的文件?

Gil*_*il' 43

您正在观察dd的特殊行为与 Linux 的特殊行为的组合/dev/random。顺便说一下,两者都很少是适合这项工作的工具。

Linux/dev/random很少返回数据。它基于伪随机数发生器中的熵以非常快的速度消失的假设。由于收集新的熵很慢,/dev/random通常一次只放弃几个字节。

dd是一个旧的、古怪的程序,最初打算在磁带设备上运行。当您告诉它读取一个 1kB 的块时,它会尝试读取一个块。如果读取返回少于 1024 个字节,很难,这就是你所得到的。所以dd if=/dev/random bs=1K count=2打了两个read(2)电话。由于它是从 读取的/dev/random,这两个read调用通常只返回几个字节,数量取决于可用的熵。另请参阅dd 何时适合复制数据?(或者,什么时候 read() 和 write() 是部分的)

除非您正在设计操作系统安装程序或克隆程序,否则永远不要/dev/random在 Linux 下使用/dev/urandom. 该urandom手册页有所误导; /dev/urandom实际上适用于密码学,甚至适用于生成长寿命密钥。唯一的限制/dev/urandom是它必须提供足够的熵;Linux 发行版通常会在重新启动之间保存熵,因此唯一可能没有足够熵的时间是全新安装。熵在实际中不会消失。有关更多信息,请阅读/dev/urandom 中的 rand 是否安全用于登录密钥?和喂养 /dev/random 熵池?.

使用或 之类的dd工具可以更好地表达 的大多数用途。如果您想要 2kB 的随机字节,请运行headtail

head -c 2k </dev/urandom >rand
Run Code Online (Sandbox Code Playgroud)

使用较旧的 Linux 内核,您可以逃脱

dd if=/dev/urandom of=rand bs=1k count=2
Run Code Online (Sandbox Code Playgroud)

因为很/dev/urandom高兴返回了请求的字节数。但是从内核 3.16 开始就不再如此,现在限制为 32MB。

一般而言,当您需要使用dd提取固定数量的字节并且其输入不是来自常规文件或块设备时,您需要逐字节读取:dd bs=1 count=2048。


Bru*_*ger 11

从man 4 random在RHEL 5盒:

读取时,/dev/random 设备将仅返回熵池中估计的噪声位数内的随机字节。

我在那台机器上得到大小为 213 字节的文件。回到人4随机:

读取时,/dev/urandom 设备将返回所请求的字节数。

我从每次调用中得到 2048 个字节 dd if=/dev/urandom of=rand bs=1K count=2

我得出结论,差异是由于您的机器在调用之间产生了多少熵 dd if=/dev/random ...

  • @cjc:这是因为当您在阻塞 FD 上调用 `read(fd, mybuf, 1024)` 时,它会在底层设备返回 *some* 数据后立即返回。如果有 1024 个字节要读取,则返回该字节。如果只有 201 个字节,则返回 201。如果有 0 个字节可用,它将阻塞,直到至少有一个字节可用,然后返回它/它们。 (5认同)

Pet*_*r.O 5

为什么会dd丢数据?... Gilles提出了这个引人入胜的问题dd:
dd 何时适合复制数据?(或者,什么时候是 read() 和 write() 部分的)
这是该问题的摘录:

    *...不难将 dd 归咎于错误;例如,试试这个代码:**
        yes | dd of=out bs=1024k count=10
    并检查输出文件的大小(它可能远低于 10MB)。


除了我的评论(在你的问题结束时),像这样的东西值得关注......它会在 file 中捕获你的字节$trnd。我半随意地选择了 bs=8

移动你的鼠标,看着它加速。
在我的计算机空闲(AFK 且没有网络活动)的情况下,在耗尽熵池后,仅收集1192字节花了2小时12 分钟,此时我取消了它。

然后,随着我不断移动鼠标,收集相同数量的字节所需的时间相对较短1分15 秒。

这很清楚地表明,收集熵不是基于 CPU 速度,而是基于随机事件,并且我的 Ubuntu 系统使用鼠标作为其重要的随机因素之一。

get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
    dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
    echo -n "itt: $((i+=1))  ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"
Run Code Online (Sandbox Code Playgroud)