简介
所有的io设备都可以被分为流设备和块设备,块设备指的是把数据打包成块进行传输,传输基本单位为块,传输过程中需要缓冲区(buffer)支持,当然,读写也是以块作为基本单位.对于流设备(也称为字符设备),传输过程是以字节流形式进行的,这样的设备是不需要缓冲机制的.
块和流
块:Block:基本的数据单位,一个块通常包含多个字节(字节数目固定)
块设备:Block-Device:其提供的IO操作均是面向块的,也只能面向块,无论是读还是写,(CD,DVD)
流:Stream:基本的数据单位,一个流通常包含多个字节或者只有一个字节
流设备:Stream-Device:提供的IO面向流(键盘,鼠标,终端)
区别:
在操作系统和应用程序中经常把块设备当成一个块数组来进行操作,块操作是需要缓冲区的协助,缓冲区积满之后进行数据传输,当你的程序中包含了缓冲区的话,现在的操作系统采用内存映射将文件直接映射到用户空间中来加速操作。流io原理模仿了通道(channel),I/O 字节流必须顺序存取,常见的例子有TTY(控制台)设备、打印机端口和网络连接。流的传输一般(也不必然如此)比块设备慢,经常用于间歇性输入。
总结:
流io一般速度低于块io,并不是绝对,拿水龙头来比喻:流就像水龙头滴水,每次只有一滴;块就像水龙头往水壶放水,放满之后对一整个水壶的水进行操作。 * 1:针对一段固定大小的数据 n byte,流是对每一个字节进行读取,每次读取调用一次系统函数,所以是需要n次调用。而块则是一次一块,假设块大小为b因此系统函数调用的次数为[n/b]+1,特别是当数据比较大时,效率更高 * 2,流io为阻塞模式,而块io支持非阻塞(不考虑消息轮询);多线程情况下,把文件看成一个块数组的话,我们可以多线程对不同的块进行操作,比如thread1 操作块1,thread2操作块2...而对于流,由于流只能顺序读取,因此基本没有优势。 * 3,在数据的实时性要求比较严的情况下,流就很方便了,每次写入一个字节系统就能立即将数据传输给程序,而块则是等到缓冲区满或者flush之后才进行处理 * 4,处理数据方面,我们可以非常方便的节为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分。而对于一整块的数据处理起来相对就麻烦了。 * 5,占用内存:由于流面向字节,一次只需要少量内存即可,而面向快由于需要缓冲区的协助,因此内存的大小与块的大小以及数量直接相关,即使块中数据并没有填满,仍然需要占用这么多内存。
参考:
- 1 : Block-Oriented Devices vs. Stream-Oriented Devices
- 2 : Java NIO vs. IO
- 3 : Java nio 笔记:系统IO、缓冲区、流IO、socket通道
- 4 : 从 Linux 内核访问用户空间内存
- 5 : 内存映射文件原理探索]