专栏名称: 唤之
目录
相关文章推荐
程序猿  ·  字节跳动因代码抄袭,被判赔8266.8万元 ·  昨天  
51CTO官微  ·  DeepSeek爆火!我们整理了80余页宝典 ... ·  3 天前  
OSC开源社区  ·  8G的容器Java堆才4G怎么就OOM了? ·  4 天前  
OSC开源社区  ·  DS豆包通义BTY王炸组合,我做了个元宵AI ... ·  3 天前  
程序员的那些事  ·  马斯克开团豪掷 974 ... ·  4 天前  
51好读  ›  专栏  ›  唤之

Java NIO分析(1): Unix网络模型

唤之  · 掘金  · 程序员  · 2018-07-17 02:43

正文

要谈Java的NIO, 还是先从I/O开始说起。
Unix提供了5种不同的I/O模型,分别是

  • 阻塞I/O(blocking I/O)
  • 非阻塞I/O(non-blocking I/O)
  • I/O复用(I/O multiplexing)
  • 信号驱动式I/O(signal-driven I/O)
  • 异步I/O(asynchronous I/O)

一个I/O操作需要从用户态进入内核态运行,通常包括俩阶段

  1. 等待数据
  2. 从内核向进程复制数据

对于socket I/O而言,第一步通常是等待数据从网络中到达,到达之后会复制到内核的某个缓冲区
第二布就是从内核缓冲区复制到应用进程缓冲区

阻塞I/O

默认情况下,所有的socket都是阻塞的. 如图所示

  1. 应用发起recvfrom这个系统调用, 应用被阻塞
  2. 内核等待数据准备好
  3. 数据准备好, 内核将数据复制到应用缓冲区
  4. 应用从阻塞里恢复,处理数据

这也是理解和编程起来比较简单的模型,所以计算机早期用的很多,现在在处理超大文件的时候,也依然适用于这种模型。

非阻塞I/O

相比于 Blocking I/O , Non-Blocking I/O 等待数据 阶段不会被阻塞,也就是说操作系统不会挂起应用, 应用
不断 轮询(polling) 内核看是否数据准备好。某次轮询发现准备好了,再直接发系统调用阻塞取数据.

Unix网络编程 里对 轮询 的定义是:
应用进程对非阻塞描述符循环发送系统调用,以查看某个操作是否就绪

I/O多路复用


在处理非常多的描述符的时候,I/O多路复用技术显得非常有用。I/O多路复用需要发送2次系统调用:

  1. select或者poll, 获取可读条件, 等待描述符变成可读
  2. 发起recvfrom系统调用,内核复制数据到应用。

在只有1个客户端的时候,I/O多路复用技术甚至不如阻塞I/O.因为多发了一次系统调用。
但有些常用的网络场景,如:

  • 既要处理TCP,又要处理UDP
  • 一个服务器处理多个服务或者多个协议
  • 一个TCP服务器既要监听socket,又要处理已连接socket

这些场景下,多发的这次系统调用能带来更高的I/O处理效率,能更均匀的使用服务器时间片, 处理更多连接。
常用的方法是把I/O多路复用和非阻塞I/O结合使用,这样应用进程不需要阻塞,能处理别的业务,同时又能够处理多个I/O请求

信号驱动I/O

信号模型的步骤是:

  1. 应用进程发起一个信号,告诉内核要什么文件,然后立马返回
  2. 内核准备好数据
  3. 应用进程收到信号发起recvfrom系统调用来阻塞取数据

信号驱动模型类似于你去一点点买奶茶,对方给你一个小票。
什么时候好了对方喊xx号(这就是信号)好了.然后你来取奶茶(recvfrom取数据)

异步I/O







请到「今天看啥」查看全文