Pseudo-devices On GNU/Linux
先分享一则有意思Q&A,来自[The FreeBSD Funnies 17.4](https://www.freebsd.org/doc/en_US.ISO8859-1/books/faq/funnies.html) 。
Where does data written to* /dev/null* go?
It goes into a special data sink in the CPU where it is converted to heat which is vented through the heatsink / fan assembly. This is why CPU cooling is increasingly important; as people get used to faster processors, they become careless with their data and more and more of it ends up in /dev/null, overheating their CPUs. If you delete /dev/null (which effectively disables the CPU data sink) your CPU may run cooler but your system will quickly become constipated with all that excess data and start to behave erratically. If you have a fast network connection you can cool down your CPU by reading data out of /dev/random and sending it off somewhere; however you run the risk of overheating your network connection and / or angering your ISP, as most of the data will end up getting converted to heat by their equipment, but they generally have good cooling, so if you do not overdo it you should be OK.
写入* /dev/null* 的数据去了哪里?
它们进入了CPU的“垃圾槽”中并被转化为热量最终由散热装置吹走了 ;)这也是为什么CPU的散热越来越重要;随着人们习惯于使用那些飞快的CPU,他们也对那些被送入 /dev/null 的数据不那么关心了——于是CPU可倒霉了。如果你删掉了/dev/null(这会马上堵住CPU的“垃圾槽”。真的可以删掉。。。),你的CPU可能会舒服点但是你的系统也会因为那些无处可去的额外数据而马上”便秘“。如果你的网挺快,也可以试试从dev/random读取数据并发到网上(后面会讲解random是如何工作的),以此来为你的CPU降温。然而这也是有风险的,毕竟网络和你的磁盘也会发热(I/O桥??),电信运营商也会抓狂——那些数据会被他们的设备转化为热量。不过他们的散热一般很好,所以偶尔搞一搞也是无妨的 ; )
下面开始正经的说一说/dev下的Pseudo-devices:
/dev/random与/dev/urandom
首先介绍一下随机数的性质分类(学过密码学的跳过吧)
- 随机性——不存在统计学的偏差,是完全杂乱的数列(前几天看家伟做的一道线性同余的题就是这种)。
- 不可预测性——不能从过去的数列推测出下一个出现的数。
- 不可重现性——除非将数列记录下来,否则不可能重现相同的数列。
以上三个性质中,越往下越严格。密码技术中所使用的随机数,仅仅具备随机性是不够的,至少还要具备不可预测的性质。 一般的,将以上三个性质分别称为”弱伪随机数“,”强伪随机数“,”真随机数“。
给真随机数举一个简单的例子:你不小心把一个玻璃杯打碎了,这个玻璃杯打碎过程中的破碎轨迹,破碎后碎片的分布对所有人来说都是随机的,也是当前几乎无法完全重现的。真随机数生成麻烦,一般用来做伪随机数的种子,以此来利用扩张的随机性。
为了方便计算机获得真随机数(不用你去砸杯子了),新型的X86 CPU中都内置了数字随机数生成器(Digital Random Number Generator, DRNG),并提供了RDSEED和RDRAND两条指令。这种CPU生成随机数的原料(随机信号源)来自于电路中产生的热噪声。(如果你用过GnuPG生成对称密钥,它会提醒你移动鼠标或者使用磁盘,这也是为了方便收集真随机数)。
从Linux 1.3.30开始,/dev有了random和urandom两个character special files,通过这两个接口,用户可以使用内核的随机数字发生器。
随机数字发生器会收集硬件驱动产生的背景噪声(真随机数),并把它们放在随机池里。同时发生器会时时记录下随机池里剩余的随机数。通过这个随机池,我们就可以产生很多伪随机数了。
那这两个文件有什么区别呢?
当random文件/设备被读时,它仅仅只会返回随机池里的真随机数,所以random文件适合于那些需要非常高安全性的场合——比如需要使用一次性密码本或者作为其他伪随机数生成器的种子(比如密钥生成器)。当随机池空的时候,random会暂停输出知到新的热噪声被收集到池子中。(你可以试一下cat /dev/random,待到输出停止后再移动一下鼠标或者打开一个视频,新的真随机数就会继续被输出。)
而当你读urandom文件/设备时,它不会为了等待新的噪声而暂停输出。如果池子里的真随机数不够,它会调用内核里的一个伪随机发生器来继续产生随机数。所以,在这种情况下攻击是可能的,但是到目前为止没有发现针对这个文件/设备的有效攻击。不放心的话就用random吧。
从3.16的内核开始,从urandom读的话最多能收到32MB的随机数,从random的话有512bytes(2.6以前只有340bytes)。
如果你向random或者urandom写数据的话,写入的数据会覆盖掉随机池里的真随机数,但是这不会提高安全性;也不会提高从random读出随机数的速度。
提醒一下,很多伪随机数的库函数都仅仅满足了随机性,例如C的rand,java的java.util.Random等等,以后写安全方面的代码时要注意。 (上次一航讲的一个web500就用到了弱伪随机数的可预测性)
/dev/full
这个文件通常被用来测试软件是如何处理磁盘空间不够的情况,当你向这个文件写数据时,会收到一个ENOSPC error。从该文件读的话会得到一连串NULL('\00')字符。
frank@under:~$ echo hello > /dev/full
bash: echo: write error: No space left on device
/dev/null
”talk is cheap, show me the code“,就按着kernel的源码来讲吧。
声明:
static const struct file_operations null_fops = {
.llseek = null_lseek,
.read = read_null,
.write = write_null,
.read_iter = read_iter_null,
.write_iter = write_iter_null,
.splice_write = splice_write_null,
};
只分析read_null和write_null,其他的类似。
read_null():
static ssize_t read_null(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
return 0;
}
可以看到,如果从null里面读取数据的话就是返回有符号整型”0“,也不会处理用户给他的file指针或者buffer指针和其他数据。,通常情况下这就是一个EOF——你得不到任何数据。
write_null():
static ssize_t write_null(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return count;
}
这个也是”毫无用处“,仅仅只是返回我们告诉null我们想要写入文件的字节大小(也是有符号整型)。通过这种通用的”写入成功“返回方式,使得一般的软件将流定向到null可以收到”正确写入“的消息,猜想这会方便软件无用流的编写。
/dev/zero
上面说到读null会得到一个有符号整型“0”。那么zero呢?你会得到一连串的NULL字符('\0')(说明处理了文件指针)。
$ dd if=/dev/null of=file count=10
0+0 records in
0+0 records out
0 bytes (0 B) copied, 0.000276193 s, 0.0 kB/s
$ dd if=/dev/zero of=file count=10
10+0 records in
10+0 records out
5120 bytes (5.1 kB) copied, 0.00090775 s, 5.6 MB/s
声明:
static const struct file_operations zero_fops = {
.llseek = zero_lseek,
.write = write_zero,
.read_iter = read_iter_zero,
.write_iter = write_iter_zero,
.mmap = mmap_zero,
.get_unmapped_area = get_unmapped_area_zero,
#ifndef CONFIG_MMU
.mmap_capabilities = zero_mmap_capabilities,
#endif
};
仅分析一下zero_lseek和write_zero。
zero_lseek:
#define zero_lseek null_lseek
/*
* Special lseek() function for /dev/null and /dev/zero. Most notably, you
* can fopen() both devices with "a" now. This was previously impossible.
* -- SRB.
*/
static loff_t null_lseek(struct file *file, loff_t offset, int orig)
{
return file->f_pos = 0;
}
f_pos定义在file结构体(定义在<linux/fs.h>),表示文件当前的读写位置,因此现在可以appending的方式打开这两个特殊文件了。
write_zero:
#define write_zero write_null
static ssize_t write_null(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return count;
}
这就很有意思了,看起来向zero写文件和null应该是一个效果。。。(不过这么写代码的话别人会觉得奇怪吧)
看来null和zero很像两兄弟,不过传统上还是建议把null当成一个”只写“的黑洞,把zero当成一个只读的NULL字符(‘\0’)产生器吧。
ps:
- 大家可能会对null返回的整型“0“和zero返回的NULL字符 '\0'的区别感到疑惑,可以参考stackoverflow上一篇文章。
- /dev/zero 通常被用来创建swap。
- 详细的文档可以man full、urandom、zero等。
happy hacking!
参考:
- https://en.wikipedia.org/wiki//dev/random
- https://en.wikipedia.org/wiki/Null_device
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/mem.c?id=refs/tags/v4.9-rc3#n774
- https://stackoverflow.com/questions/3690273/did-i-understand-dev-urandom
- https://www.reddit.com/r/linuxquestions/comments/5b5wq5/eli5_how_does_devnull_work/
- https://unix.stackexchange.com/questions/63238/purpose-of-dev-zero
- https://unix.stackexchange.com/questions/254384/difference-between-dev-null-and-dev-zero
- 《图解密码学》第三版
- Linux Programmer's Manual
Pseudo-devices On GNU/Linux的更多相关文章
- Gnu/Linux的学习探索
1.Gnu/Linux是一个基于POSIX和UNIX的多用户多任务 支持多线程多CPU的类UNIX的操作系统. 继承了UNIX以网络为核心的设计思想 是性能稳定的多用户网络操作系统. 1991年10月 ...
- GNU Linux启动时文件系统mountall挂载出错问题的处理
/********************************************************************* * Author : Samson * Date ...
- (转)完全用GNU/Linux工作 by 王珢
完全用GNU/Linux工作 王珢 (看完这篇博文,非常喜欢王珢的这篇博客,也我坚定了学gnu/linux的决心,并努力去按照国外的计算机思维模式去学习编程提高自己.看完这篇文章令我热血沸腾 ...
- GNU/Linux复习笔记(1)
第一次接触GNU/Linux还是大四上学期实习的那两个月在window里装了 个虚拟机玩红帽的系统,那段时间稍微学了一点命令就不玩了.后来大四下学期认识了王总,装了双系统,那段时间又对linux有了进 ...
- 下一代GNU/Linux显示服务Wayland 1.12正式发布
导读 最近,Bryce Harrington很高兴地宣布了“面向GNU/Linux操作系统的Wayland 1.12.0显示服务已正式发布”的消息.与它一同到来的,还有Weston 1.12.0合成器 ...
- ZFS(一):ZFS在Debian GNU/Linux上的安装
以下内容翻译自https://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/,并附有原文,由于是第一次翻译,如有任何翻译不恰当之处,欢迎指出 ...
- debian7 请把标有“Debian GNU/Linux 7.1.0 _Wheezy_ - Official amd64 DVD Binary-1 20130615-23:06”的盘片插入驱动器“/media/cdrom/”再按回车键
有时候,在通过apt-get install 安装软件的时候,会出现: 更换介质:请把标有“Debian GNU/Linux 7.1.0 _Wheezy_ - Official amd64 DVD B ...
- 完全用 GNU/Linux 工作(转)
转自:http://www.chinaunix.net/old_jh/4/16102.html 看到一半,实在太长,但已觉得很好,转来分享一下. 完全用 GNU/Linux 工作 - 摈弃 Windo ...
- 世纪大争论:Linux还是GNU/Linux?
我们在网上已经习惯用“Linux”来称呼Linux操作系统了,然而,偶尔也用“GNU/Linux”来称呼和指代同样的操作系统和软件.同时人们也在争论这两种称呼哪个更合适. 本文将不会选边站队,仅力图向 ...
- GNU/Linux Distribution Timeline v12.10
GNU/Linux Distribution Timeline v12.10 原图下载 GNULinux Distribution Timeline 12.10.png GNU/Linux Distr ...
随机推荐
- windows中更换Jdk版本不生效
本机已经安装了jdk1.7,而比较早期的项目需要依赖jdk1.6,于是同时在本机安装了jdk1.6和jdk1.7. 安装jdk1.6前,执行java -version得到 C:\Users\liuxi ...
- Python之文件与目录
file 通常建议使用open()打开文件,file用于类型判断 如果要把数据写到磁盘上,除调用flush()外,还得用sync(),以确保数据从系统缓冲区同步到磁盘.close()总是会调用这两个方 ...
- HTML5 Web缓存&运用程序缓存&cookie,session
在介绍HTML5 web缓存前,来认识一下cookie和session: session: 由于HTTP是无状态的,你是谁?你干了什么?抱歉服务器都是不知道的. 因此session(会话)出现了,它会 ...
- Builder模式的思考(Effective Java)
<Effective Java>(第2版)中第二条中提到:遇到多个构造器参数时要考虑用构建器.在复习static关键字和内部类时回头看了一下,这才明白了为什么要用静态内部类来做处理,这里记 ...
- java多线程系列(九)---ArrayBlockingQueue源码分析
java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ...
- 巧学DBhelper
这几天在教我很重要的人学习,她属于那种超级小白,很超级的那种. 教她的过程中 发现有的知识点 不管这么教都不会.DBhelper就是不知道怎么记. 当时我就想到 杰哥(程杰)的出的大话系列,和他写书的 ...
- JS弹窗带遮蔽的功能
很不错的JS原生自定义弹窗,很实用! function myAlert(str,click,useCancel){ var overflow=""; var $hidder=nul ...
- Javascript-基础概念总结
[作用域]javascript中的作用域可以理解为一个语句执行的环境大小,有全局的作用域,函数作用域和eval作用域.在JS中没有块级作用域.讲到作用域,不得不讲执行环境,执行环境在JS中是最为重要的 ...
- Android 软键盘的显示和隐藏,这样操作就对了
一.前言 如果有需要用到输入的地方,通常会有需要自动弹出或者收起软键盘的需求.开篇明义,本文会讲讲弹出和收起软键盘的一些细节,最终还会从源码进行分析. 想要操作软键盘,需要使用到 InputMetho ...
- 一些公司对quantitative的要求
来自日月光华BBS: Company: UBS AG Job Title: Quantitative Developers / Analysts (Entry Level, Multiple Posi ...