最近组里小伙伴做了次分享,感觉挺好的,虽然我不是后端开发,拿出来整理整理,做做笔记。
-
基础概念
内核是操作系统的核心软件。
它独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限,为应用程序提供对计算机硬件的安全访问服务。
为了保证内核安全,避免用户进程直接操作内核,操作系统将内存寻址空间划分为两部分:
(1)内核空间Kernel-space
(2)用户空间:供内核程序使用
-
IO流
概念:抽象数据流(I/O流)的概念:指一组有顺序的、有起点和终点的字节集合
作用:实现程序逻辑与底层硬件解耦。通过引入数据流作为程序与硬件设备之间的抽象层,面 向通用的数据流输入输出接口编程,而不是具体硬件特性,程序和底层硬件可以独立灵活替换和扩展。
I/O工作原理
-
磁盘IO
1、读写操作基于系统调用实现
2、读写操作经过用户缓冲区,内核缓冲区,应用进程并不能直接操作磁盘
3、应用进程读操作时需阻塞直到读取到数据DMA:全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。基于 DMA 访问方式,系统主内存与硬件设备的数据传输可以省去CPU 的全程调度
- 网络I/O(阻塞式I/O)
网络I/O读写操作经过用户缓冲区,Sokcet缓冲区,服务端线程在从调用recvfrom开始到它返回有数据报准备好这段时间是阻塞的,recvfrom、accept返回成功后,线程开始处理数据报。(recvfrom,accept是socket接收数据的函数)
NIO
- java-I/O存在问题:
- 数据多次拷贝:JVM GC的存在,导致对象在堆中的位置往往会发生移动,移动后传入系统函数的地址参数就不是真正的缓冲区地址了
- 操作阻塞:建立连接(connect),读取网络I/O数据(read),发送数据(send)
- 三大组件(Java NIO核心三大核心组件是Buffer(缓冲区)、Channel(通道)、Selector)
- Buffer
- Channel
Channel(通道)的概念可以类比I/O流对象,NIO中I/O操作主要基于Channel;
从Channel进行数据读取 :创建一个缓冲区,然后请求Channel读取数据;
从Channel进行数据写入 :创建一个缓冲区,填充数据,请求Channel写入数据。Channel和流的区别:
Channel可以读和写,而标准I/O流是单向的 Channel可以异步读写,标准I/O流需要线程阻塞等待直到读写操作完成 Channel总是基于缓冲区Buffer读写
- Selector
Selector(选择器),它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。实现单线程管理多个Channel,也就是可以管理多个网络连接Selector核心在于基于操作系统提供的I/O复用功能,单个线程可以同时监视多个连接描述符,一旦某个连接就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作,常见有select、poll、epoll等不同实现。
NIO基本原理
- 初始化Selector对象,服务端ServerSocketChannel对象
- 向Selector注册ServerSocketChannel的socket-accept事件
- 线程阻塞于selector.select(),当有客户端请求服务端,线程退出阻塞
- 基于selector获取所有就绪事件,此时先获取到socket-accept事件,向Selector注册客户端SocketChannel的数据就绪可读事件事件
- 线程再次阻塞于selector.select(),当有客户端连接数据就绪,可读
- 基于ByteBuffer读取客户端请求数据,然后写入响应数据,关闭channel
Reactor模式与Proactor模式
Reactor模式(也叫 Dispatcher 模式)采用同步IO,而Proactor采用异步IO。Reactor和Proactor模式的主要区别就是真正的读取和写入操作是有谁来完成的,Reactor中需要应用程序自己读取或者写入数据,而Proactor模式中,应用程序不需要进行实际的读写过程,它只需要从缓存区读取或者写入即可,操作系统会读取缓存区或者写入缓存区到真正的IO设备。