先分享一则有意思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

首先介绍一下随机数的性质分类(学过密码学的跳过吧)

  1. 随机性——不存在统计学的偏差,是完全杂乱的数列(前几天看家伟做的一道线性同余的题就是这种)。
  2. 不可预测性——不能从过去的数列推测出下一个出现的数。
  3. 不可重现性——除非将数列记录下来,否则不可能重现相同的数列。

以上三个性质中,越往下越严格。密码技术中所使用的随机数,仅仅具备随机性是不够的,至少还要具备不可预测的性质。 一般的,将以上三个性质分别称为”弱伪随机数“,”强伪随机数“,”真随机数“。

给真随机数举一个简单的例子:你不小心把一个玻璃杯打碎了,这个玻璃杯打碎过程中的破碎轨迹,破碎后碎片的分布对所有人来说都是随机的,也是当前几乎无法完全重现的。真随机数生成麻烦,一般用来做伪随机数的种子,以此来利用扩张的随机性。

为了方便计算机获得真随机数(不用你去砸杯子了),新型的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:

  1. 大家可能会对null返回的整型“0“和zero返回的NULL字符 '\0'的区别感到疑惑,可以参考stackoverflow上一篇文章
  2. /dev/zero 通常被用来创建swap。
  3. 详细的文档可以man full、urandom、zero等。

happy hacking!

参考:

  1. https://en.wikipedia.org/wiki//dev/random
  2. https://en.wikipedia.org/wiki/Null_device
  3. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/mem.c?id=refs/tags/v4.9-rc3#n774
  4. https://stackoverflow.com/questions/3690273/did-i-understand-dev-urandom
  5. https://www.reddit.com/r/linuxquestions/comments/5b5wq5/eli5_how_does_devnull_work/
  6. https://unix.stackexchange.com/questions/63238/purpose-of-dev-zero
  7. https://unix.stackexchange.com/questions/254384/difference-between-dev-null-and-dev-zero
  8. 《图解密码学》第三版
  9. Linux Programmer's Manual

Pseudo-devices On GNU/Linux的更多相关文章

  1. Gnu/Linux的学习探索

    1.Gnu/Linux是一个基于POSIX和UNIX的多用户多任务 支持多线程多CPU的类UNIX的操作系统. 继承了UNIX以网络为核心的设计思想 是性能稳定的多用户网络操作系统. 1991年10月 ...

  2. GNU Linux启动时文件系统mountall挂载出错问题的处理

    /********************************************************************* * Author  : Samson * Date    ...

  3. (转)完全用GNU/Linux工作 by 王珢

    完全用GNU/Linux工作 王珢      (看完这篇博文,非常喜欢王珢的这篇博客,也我坚定了学gnu/linux的决心,并努力去按照国外的计算机思维模式去学习编程提高自己.看完这篇文章令我热血沸腾 ...

  4. GNU/Linux复习笔记(1)

    第一次接触GNU/Linux还是大四上学期实习的那两个月在window里装了 个虚拟机玩红帽的系统,那段时间稍微学了一点命令就不玩了.后来大四下学期认识了王总,装了双系统,那段时间又对linux有了进 ...

  5. 下一代GNU/Linux显示服务Wayland 1.12正式发布

    导读 最近,Bryce Harrington很高兴地宣布了“面向GNU/Linux操作系统的Wayland 1.12.0显示服务已正式发布”的消息.与它一同到来的,还有Weston 1.12.0合成器 ...

  6. ZFS(一):ZFS在Debian GNU/Linux上的安装

    以下内容翻译自https://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/,并附有原文,由于是第一次翻译,如有任何翻译不恰当之处,欢迎指出 ...

  7. 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 ...

  8. 完全用 GNU/Linux 工作(转)

    转自:http://www.chinaunix.net/old_jh/4/16102.html 看到一半,实在太长,但已觉得很好,转来分享一下. 完全用 GNU/Linux 工作 - 摈弃 Windo ...

  9. 世纪大争论:Linux还是GNU/Linux?

    我们在网上已经习惯用“Linux”来称呼Linux操作系统了,然而,偶尔也用“GNU/Linux”来称呼和指代同样的操作系统和软件.同时人们也在争论这两种称呼哪个更合适. 本文将不会选边站队,仅力图向 ...

  10. GNU/Linux Distribution Timeline v12.10

    GNU/Linux Distribution Timeline v12.10 原图下载 GNULinux Distribution Timeline 12.10.png GNU/Linux Distr ...

随机推荐

  1. [转载] HBase vs Cassandra:我们迁移系统的原因

    转载自http://www.csdn.net/article/2010-11-29/282698 我的团队近来正在忙于一个全新的产品——即将发布的网络游戏www.FightMyMonster.com. ...

  2. Spring MVC工作原理

    1. 客户端请求提交到DispatcherServlet2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller3. Dispat ...

  3. Javaweb学习(一):tomcat服务器配置与启动

    目前所使用的集成开发环境为myeclipse10.7,tomcat版本为apache-tomcat-7.0.82,部分编写地方可能有所不同,但是工具不是最主要的,重要的是掌握的知识. tomcat在m ...

  4. ORA-01843: 无效的月份

    1.插入的日期如果是DateTime类型的,没有影响 2.如果DateTime.ToString()获取的日期,就会报错,例如(@param_datetime = cf.GetServerDateTi ...

  5. 常见的Mysql数据库优化总结

    索引 1.主键索引 作用:唯一约束和提高查询速度 #建表时创建主键索引 create table `table_name`( `id` int unsigned not null auto_incre ...

  6. 七、VueJs 填坑日记之渲染一个列表

    在上一篇博文中,我们对vue组件有了一个简单的认识和大概的理解.在之前认识项目结构的时候,我们在/src目录中创建了一个components的文件夹,而今天就要用到了,这个文件夹的作用就是放置我们的自 ...

  7. 企业级应用TOMCAT

    第1章 Tomcat 1.1 Tomcat简介 Tomcat是一个免开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不多的场合下被普遍使用,是开发调试JSP程序的首选,另 ...

  8. 初识CC_MVPMatrix

    初识CC_MVPMatrix CC_MVPMatrix是一个mat4类型的uniform,在shader代码被编译之前,它由cocos2d-x框架插入进来的. bool GLProgram::comp ...

  9. redis配置文件之复制

    主从复制使用slaveof将Redis实例作为另一个Redis服务器的副本. 1) Redis复制是异步的,master可以配置成如果它连接的slave没有达到给定的数量,就停止接受写入.2) 如果断 ...

  10. 史上最全常用正则表达式(Javascript公众号推文)

    2017-04-13 zxin JavaScript很多不太懂正则的朋友,在遇到需要用正则校验数据时,往往是在网上去找很久,结果找来的还是不很符合要求.所以我最近把开发中常用的一些正则表达式整理了一下 ...