3.2.1 I/O请求过程
I/O 请求可以分为两个阶段,分别为调用阶段和执行阶段。
- 第一个阶段为I/O 调用阶段,即用户进程向内核发起系统调用。
- 第二个阶段为I/O 执行阶段。此时,内核等待 I/O 请求处理完成返回。
该阶段分为两个过程:首先等待数据就绪,并写入内核缓冲区;随后将内核缓冲区数据拷 贝至用户态缓冲区。
3.2.2 同步阻塞(BIO)

当用户程序执行系统调用,线程会被阻塞,一直要等到内核数据准备好,并把数据从内核缓冲区拷贝到应用程序的缓冲区,拷贝完成后才返回。
因此,BIO要实现异步操作,只能使用多线程模型,一个请求对应一个线程,但是过多的线程会增加线程上下文切换的开销。
3.2.3 同步非阻塞(NIO)

非阻塞的IO请求在内核数据未准备好的情况下立即返回,通过不断轮询,直到数据准备好,内核将数据拷贝至应用程序缓冲区。
最后一次调用也是一个同步的过程,等待内核拷贝数据到用户程序缓冲区。
3.2.4 IO多路复用(异步阻塞I/O)

多路复用实现一个线程处理多个I/O句柄的操作,使用一个或多个固定的线程处理每一个Socket。select、poll、epoll都是I/O多路复用的实现,线程一次select调用可以获取内核态中多个数据通道的数据状态。多路复用解决了同步阻塞IO和同步非阻塞IO的问题。
I/O多路复用的reactor模式
3.2.5 异步I/O(AIO异步非阻塞)

当我们发起 异步 I/O之后,就立即返回,内核自动将数据从内核空间拷贝到用户空间,这个拷贝过程同样是异步的,内核自动完成的,和前面的同步操作不一样,应用程序并不需要主动发起拷贝动作。
对比生活:
食堂打饭:
餐盘 -> 用户态 ;
厨师、打饭阿姨 -> 内核态 ;
厨师做好饭菜,阿姨把菜端出来 -> 数据准备;
阿姨把饭菜打到你的餐盘中 -> 数据拷贝;
BIO:去食堂打饭发现菜还没做好,就一直等,直到菜做好,阿姨把饭菜打到自己的餐盘里;
NIO:每隔一段时间去食堂问阿姨菜好了没有,过了几次,阿姨说好了,于是等待阿姨把饭菜打到自己的餐盘里;
多路复用:有一个APP,你注册一个中午要吃饭的事件,APP去管理饭菜好了没有,饭菜好了,APP就给你发一个消息通知,收到通知后,就去食堂等待阿姨把饭菜打到自己的餐盘里;
AIO:去食堂把饭盒给阿姨,饭菜好了直接打到饭盒里,并送到自己面前,整个过程不需任何等待。
