五种IO模型

发布时间 2023-11-16 15:54:23作者: gogoy

什么是IO

其实IO就是把进程的内部数据转移到外部设备,或者把外部设备的数据迁移到进程内部。外部设备一般指硬盘、socket通讯的网卡。

 

我们来把 I/O 过程比喻成烧水+倒水的过程,等待资源(就是烧水的过程),使用资源(就是倒水的过程):

  • 如果你站在炤台边上一直等着(等待资源)水烧开,然后倒水(使用资源),那么就是同步阻塞 I/O;

  • 如果你偷点儿懒,在烧水的时候躺在沙发上看会儿电视(不再时时刻刻等待资源),但是还是要时不时的去看看水开了没有,一旦水开了,马上去倒水(使用资源),那么这就是同步非阻塞 I/O;

  • 如果你想要洗澡,需要同时烧好多壶水,那你就在看电视的间隙去看看哪壶水开了(等待多个资源),哪一壶开了就先倒哪一壶,这样就加快了烧水的速度,这就是同步多路 I/O 复用;

  • 不过你发现自己总是跑厨房去看水开了没,太累了,于是你考虑给你的水壶加一个报警器(信号,水开了报警),只要水开了就马上去倒水,这就是信号驱动 I/O;

  • 最后一种就高级了,你发明了一个智能水壶,在水烧好后自动就可以把水倒好,这就是异步 I/O。

同步阻塞IO

 

同步非阻塞IO

阻塞IO的缺点就是:如果内核数据一直没准备好,那用户进程将一直阻塞,浪费性能,可以使用非阻塞IO优化。

 

 

同步非阻塞IO

 非阻塞IO模型,简称NIO,Non-Blocking IO。它相对于阻塞IO,虽然大幅提升了性能,但是它依然存在性能问题,即频繁的轮询,导致频繁的系统调用,同样会消耗大量的CPU资源

 

 

同步IO多路复用

应用进程通过调用select函数,可以同时监控多个fd,在select函数监控的fd中,只要有任何一个数据状态准备就绪了,select函数就会返回可读状态这时应用进程再发起recvfrom请求去读取数据

 

 信号驱动IO

信号驱动IO不再用主动询问的方式去确认数据是否就绪,而是向内核发送一个信号(调用sigaction的时候建立一个SIGIO的信号),然后应用用户进程可以去做别的事,不用阻塞。当内核数据准备好后,再通过SIGIO信号通知应用进程,数据准备好后的可读状态。应用用户进程收到信号之后,立即调用recvfrom,去读取数据。

 

异步IO 

前面讲的BIO,NIO和信号驱动,在数据从内核复制到应用缓冲的时候,都是阻塞的,因此都不算是真正的异步。AIO实现了IO全流程的非阻塞,就是应用进程发出系统调用后,是立即返回的,但是立即返回的不是处理结果,而是表示提交成功类似的意思。等内核数据准备好,将数据拷贝到用户进程缓冲区,发送信号通知用户进程IO操作执行完毕。

 

 

参考:

1. https://zq99299.github.io/note-architect/hc/05/03.html#%E5%A6%82%E4%BD%95%E6%8F%90%E5%8D%87%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E6%80%A7%E8%83%BD

2. https://jiges.github.io/2018/02/07/%E4%BA%94%E5%A4%A7IO%E6%A8%A1%E5%9E%8B/

3. https://www.51cto.com/article/693213.html