提纲:

🔥Linux中的I/O

  • BIO:阻塞式I/O

  • NIO:非阻塞I/O

  • I/O多路复用

  • 异步I/O

  • 信号驱动 I/O
🎈面试八股真题
  • 1、简单讲讲I/O 多路复用

🔥Linux中的I/O

1. BIO:阻塞式I/O

  • 两次阻塞

    • 1、在内核等待数据拷贝至内核缓冲区,例如网络 I/O,数据往往不是立刻到达

    • 2、在数据从内核缓冲区拷贝至用户进程缓冲区时阻塞

2.NIO:非阻塞I/O

  • 当数据还没有拷贝至内核缓冲区时,系统会返回给用户进程一个错误信息,提示进程不要挂起,继续执行

  • NIO 解决了 BIO 第一次阻塞的问题,但进程其实仍然需要等待,用在单个进程的 I/O 上体现不出效果,在 I/O 多路复用中能体现出重要作用

3.I/O多路复用

  • 类似于单 Reactor 模型,单个线程通过 select/epoll 指令,完成多个网络 I/O

  • 原理:单个进程通过 select/epoll 对多个连接进行轮询,有连接数据准备完成,再调用 recvfrom进行读取

  • 若连接数只有一个,I/O 多路复用还不如 BIO,因为调用了两次系统指令,但对于连接数较多情况,BIO 需要多线程处理不同连接数据,I/O 多路复用可以由一个线程来完成,且通常采用 NIO 的方式,即线程是被 select 阻塞,而不是被 I/O 阻塞,在一个 socket 没有准备就绪时,线程可以处理其他已经准备好的 socket

  • # Java 中使用 Selector 实现 I/O 多路复用,ByteBuffer 实现了零拷贝,即通过 mmap 的系统调用方式,将内核内存直接映射到进程的 vma 虚拟内存空间上,从而不需要进行第二次拷贝数据的阻塞

4.异步I/O

  • 即线程发起 I/O 后,可以立刻执行其他操作,由内核去异步进行 I/O,当内核准备就绪后,通过信号通知线程,读取数据,异步 I/O 通常可以采用 Proactor 模型来实现,即一个 Proactor 专门负责接收数据,工作线程只需要负责处理并返回结果,

5.信号驱动 I/O

  • 内核使用 signal 通知线程 I/O 完成

二、面试八股真题🎈🎈🎈

1、简单讲讲I/O 多路复用

目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,实际上他们都是同步I/O,读写过程是阻塞的。
  • select