一、内核缓冲区:
- IO读写对于往往都是指上层程序的IO操作。实际上不是物理设备级别的读写,反而是缓存的复制。
- read和write都不负责数据在物理设备和内核缓冲区之间的交换。这项底层交换,由操作系统内核(Kernel)来完成。
- 在应用程序中,无论是Socket的IO、还是文件IO操作,都属于上层应用的开发。
二、进程缓冲区:
- 内核缓冲区是为了减少频繁的与设备之间物理交换。
- 上层应用使用read系统调用时,仅仅把数据从内核缓冲区复制到上层应用的缓冲区(进程缓冲区)。
- 上层应用使用write系统调用时,仅仅把数据从进程缓冲区复制到内核缓冲区。这样,底层操作由操作系统控制(如读写中断)用户程序无需关心。
-
三、四种主要IO模型
- 同步阻塞IO-Blocking IO
- 通步非阻塞IO-None Blocking IO
- 异步IO模型-Asynchronous IO
四、合理配置
及时采用最先进的模型,还需要进行合理的配置,就是Linux操作系统中文件句柄数的限制。默认为1024,即一个进程最多可以接受1024个socket连接。
五、Java NIO通信
- java NIO的三个核心组件:Channel、Buffer、Selector
- OIO:面向流(字符/字节),按照流的方式顺序读取,不能随意改变指针。阻塞的。
- NIO:面向缓冲区,可随意读取Buffer中任意位置数据。非阻塞。
5.1Buffer: 重要成员属性:
- capacity(容量-个数数量)、
- position(读写位置)、
- limit(读写限制)。
- mark(标记、临时存放position)
在写入模式下,position的值变化规则如下:
- 在刚进入到写模式时,position值为0,表示当前的写入位置为从头开始。
- 每当一个数据写到缓冲区之后,position会向后移动到下一个可写的位置。
- 初始的position值为0,最大可写值position为limit-1。当position值达到limit时,缓冲区就已经无空间可写了。
在读模式下,position的值变化规则如下:
- 当缓冲区刚开始进入到读模式时,position会被重置为0。
- 当从缓冲区读取时,也是从position位置开始读。读取数据后,position向前移动到下一个可读的位置。
- position最大的值为最大可读上限limit,当position达到limit时,表明缓冲区已经无数据可读。
flip翻转:
- 起点在哪里呢?当新建一个缓冲区时,缓冲区处于写入模式,这时是可以写数据的。
- 数据写入后,如果要从缓冲区读取数据,这就要进行模式的切换,可以使用(即调用)flip翻转方法,将缓冲区变成读取模式。
- 在这个flip翻转过程中,position会进行非常巨大的调整。
- 具体的规则是:position由原来的写入位置,变成新的可读位置,也就是0,表示可以从头开始读。flip翻转的另外一半工作,就是要调整limit属性。
5.2Buffer: 重要方法:
- allocate()创建缓冲区
- put()写入到缓冲区
- flip()翻转:设置长度上限limit,设置position位置,清除mark
- get()从缓冲区读取
- rewind()倒带
- mark()和reset():mark-将当前position保存。reset-将mark恢复到position
- clear()清空缓冲区
5.3NIO Channel-通道类
通道的主要类型:FileChannel(文件)、SocketChannel(TCP连接)、ServerSocketChannel(监听)、DatagramChannel(UDP)
数据总是从通道读到缓冲区、或者从缓冲区写入到通道
5.4NIO Selector选择器
- 选择器的使命是完成IO的多路复用。
- 一般来说,一个单线程处理一个选择器,通过选择器,可以处理数百上千的通道。会大量减少线程之间上下文切换的开销。
- 注册:通道注册选择器Channel.register(Selectorsel-选择器实例,int ops-要监控IO书事件类型)
- 选择就绪事件:一个IO事件发生,如果在选择器中注册过,就会被选择器选中,并放入SelectionKey选择键集合中。
- 选择器的使用流程:1.获取选择器实例2.将通道注册到选择器3.选出感兴趣的IO事件(选择器集合)
- select方法:select()-阻塞调用,一直到至少一个通道发生IO事件。
- select方法:select(Long timeout)-阻塞调用,最长阻塞事件为timeout。
- select方法:selectNow(Long timeout)-非阻塞,不管有没有IO事件,都会立刻返回。
- select方法:返回的整数值,代表发生IO事件的通道数。即上一次select和本次select之间发生事件的通道数。