无交互系统或工作站设备上的随机数填充器

转自 https://cloud.tencent.com/developer/article/1087417

一般生成随机数,可以用glibc提供的random()函数,不过这个是伪随机的函数,所以一般会在使用使用random函数之前初始化种子:srandom(time()),或者使用srandom(getpid())。但是,两次使用的种子相同的情况下,会得到相同的随机数!简单做一个实验,使用同一个seed,两次生成100个随机数,它们是相同的数列!原因也很简单,通过相同的算法做hash或者移位或者加减,必然会得到同样的结果。 所以,/dev/random出现了。用来生成随机数,避免生成相同的数列的随机数!但是在使用dev random的时候,可能会遇到生成随机数非常慢的情况,如果只是为了解决问题,直接到第四步,如果希望看一下原理,可以选择从头开始看。

分析: 1,dev random block 一个小实验,期待生成很多的随机数,使用shell命令:cat /dev/random > out。 然而,情况并非如此,很长的时间,只生成了几个byte的数据。查一下原因:

居然sleep了。。

2,stack 继续分析,查看stack:

很显然,不是cat进程自己主动调用了sleep或者yield,而是因为调用read读取的时候,被block住了。

3,random_read_wait 有了地址,就好说了。使用命令:addr2line -e vmlinux -a 0xffffffff81513767来看看问题出在了哪里: 在linux-4.0.4/drivers/char/random.c中:

好吧,需要被唤醒。所以找到wake_up_interruptible(&random_read_wait);这个函数在哪里调用的,就可以知道怎么可以触发被唤醒了。

4,haveged 在google的时候,很可能会提示安装haveged这个包。 对于ubuntu:apt-get install haveged 对于centos:yum install -y haveged 安装上了haveged包,果然可以快速生成大量的随机数了。 下载haveged的源代码包:http://www.issihosts.com/haveged/haveged-1.9.1.tar.gz

可见,haveged使用死循环调用ioctl。找到对应的kernel代码,发现在RNDADDENTROPY的时候,会唤醒 random_read_wait,进一步唤醒通过/dev/random获取随机数的进程。 那么整个过程就分析完了。

原文地址:https://www.cnblogs.com/welhzh/p/11775955.html