hwrng 也提供了一种从virtio中获取真随机数的方法,代码在drivers/char/hw_random/virtio-rng.c中,通过前面的分析hw_rng的工作原理都清楚了,那我们看看做核心的read函数的实现
vi->hwrng = (struct hwrng) {
.read = virtio_read,
.cleanup = virtio_cleanup,
.priv = (unsigned long)vi,
.name = vi->name,
.quality = 1000,
};
从这里的qulity等于1000,可以看出virtio提供的hw_rng还是很随进的,比有些硬件提供qulity都高。那我们看看read的实现
static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
{
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
if (vi->hwrng_removed)
return -ENODEV;
#原来只有在virtio工作的时候也就是busy的时候才能提供真随机数,如果不busy的话,就初始化一个完成量
等busy的时候在释放完成量,从而继续往下走获取随机数
if (!vi->busy) {
vi->busy = true;
reinit_completion(&vi->have_data);
register_buffer(vi, buf, size);
}
if (!wait)
return 0;
#等待virtio提供随机数
ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0)
return ret;
vi->busy = false;
#返回随机数
return vi->data_avail;
}
那这里的data_avail 到底是啥呢,可以看看看random_recv_done
static void random_recv_done(struct virtqueue *vq)
{
struct virtrng_info *vi = vq->vdev->priv;
/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
return;
complete(&vi->have_data);
}
继续看virtqueue_get_buf
void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
{
return virtqueue_get_buf_ctx(_vq, len, NULL);
}
这里基本就可以看到data_avail就是vq中buf,对应的长度len。