在driver/char/hwrng/core.c中会生成一个文件系统如下:
可以查询可以选择的hwrng,可以看当前选择的hwrng,以及手动选择hwrng
./sys/devices/virtual/misc/hw_random/rng_current
[root@ip134 /]# cd /sys/devices/virtual/misc/hw_random/
[root@ip134 hw_random]# ls
dev power rng_available rng_current rng_selected subsystem uevent
[root@ip134 hw_random]# cat rng_available
[root@ip134 hw_random]# cat rng_current
none
[root@ip134 hw_random]#
我们看看rng_available的实现
static ssize_t hwrng_attr_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err;
struct hwrng *rng;
err = mutex_lock_interruptible(&rng_mutex);
if (err)
return -ERESTARTSYS;
buf[0] = '\0';
#可见这里所有的hwrng都是放在rng_list中,只要遍历这个就可以得到所有的hwrng
list_for_each_entry(rng, &rng_list, list) {
strlcat(buf, rng->name, PAGE_SIZE);
strlcat(buf, " ", PAGE_SIZE);
}
strlcat(buf, "\n", PAGE_SIZE);
mutex_unlock(&rng_mutex);
return strlen(buf);
}
rng_selected 用于从rng_list中选择一个hwrng
static ssize_t hwrng_attr_selected_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
#就是设置cur_rng_set_by_user 为想要的hwrng就行,会有个现成自动切换到用户手动选择的hwrng
return snprintf(buf, PAGE_SIZE, "%d\n", cur_rng_set_by_user);
}
而rng_current 则可以查询并设置hwrng
显示rng_current
static ssize_t hwrng_attr_current_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
ssize_t ret;
struct hwrng *rng;
#得到当前的hwrng
rng = get_current_rng();
if (IS_ERR(rng))
return PTR_ERR(rng);
#将当前hwrng的name打印出来
ret = snprintf(buf, PAGE_SIZE, "%s\n", rng ? rng->name : "none");
put_rng(rng);
return ret;
}
设置rng_current
static ssize_t hwrng_attr_current_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
int err = -ENODEV;
struct hwrng *rng, *old_rng, *new_rng;
err = mutex_lock_interruptible(&rng_mutex);
if (err)
return -ERESTARTSYS;
#保存老的hwrng
old_rng = current_rng;
#如果用户给的参数是空的,系统自动选择排名第一的rhwng
if (sysfs_streq(buf, "")) {
err = enable_best_rng();
} else {
#比较用户设置的hwrng的name,如果确实存在着用用户设置的hwrng作为current hwrng,并设置标志cur_rng_set_by_user
list_for_each_entry(rng, &rng_list, list) {
if (sysfs_streq(rng->name, buf)) {
cur_rng_set_by_user = 1;
err = set_current_rng(rng);
break;
}
}
}
#获得当前current的hwrng
new_rng = get_current_rng_nolock();
mutex_unlock(&rng_mutex);
#如果新的hwrng 不为null,且不等于老的hwrng,曾增加随机值
if (new_rng) {
if (new_rng != old_rng)
add_early_randomness(new_rng);
put_rng(new_rng);
}
return err ? : len;
}