关于I/O模型的种类

知识点速记

1.阻塞io:你想喝水。用烧水壶烧水,自己站在边。自己盯着。一旦开了,你把水倒到杯子里面
2.非阻塞i0:你烧水,一开烧。你就去打2分钟游戏。然后回来看一下开了没。没开就又去打2分钟游戏。你不在这里等着。直到有一次来它开了。你倒到杯子里面
3.IO多路复用:你还是想喝水,但是你找了个专门帮人烧水的邻居。他给很多人烧水。你说我想烧水,他给你烧上,你就跑回家玩游戏了。水开了他就电话打你。你赶紧来拿。但是你要倒在自己杯子里
4.信号量:你去烧水房。是自动的,没有人。通知灯和你家门铃是通的,你烧上,人就可以走。烧开了就自动响你门铃,但是有时候客人来了也响门铃。你就搞不清楚到底是啥情况
5.异步io:和3类似,还是烧水你最后还要自己倒杯子里面,吹凉了喝。这里就是他给你倒好,吹凉了。然后一喊你。你来了立马就喝上了

同步阻塞IO(BIO)

线程调用read时,如果数据还未到来,线程会一直阻塞等待

  • 优点:实现简单,调用后等待数据到达即可
  • 缺点:每个连接都需要一个线程,即使数据还没到达,线程也会被占用,导致资源浪费,不适合高并发场景

同步非阻塞IO(NIO)

read调用如果没有数据就绪会立即返回错误(或特定状态),不会阻塞线程;应用程序需要不断轮询判断数据是否就绪,但当数据拷贝到用户空间时依然是阻塞的

  • 优点:线程不会长时间阻塞,可以在无数据时执行其他任务;适用于部分实时性高的场景
  • 缺点:轮询会频繁进行系统调用,上下文切换开销大,CPU占用率高

IO多路复用

通过一个线程(或少量线程)使用select、poll、epoll等系统调用,监控多个连接的状态;只有当某个连接的数据就绪时,系统才通知应用程序,再由应用程序
调用read进行数据读取(读取时仍为阻塞操作)

  • 优点:大大减少了线程数量和上下文切换,资源利用率高
  • 缺点:依赖系统内核的支持,不同的多路复用有各自的局限

信号驱动IO

再数据就绪时发出信号通知应用程序,应用程序收到信号后再调用read

  • 优点:无需轮询,数据就绪时内核主动通知应用程序
  • 缺点:对于TCP协议,由于同一个信号可能应对多种事件,难以精准区分

异步IO(AIO)

调用aio_read时,内核负责将数据从网卡拷贝到用户空间,拷贝完成后通过回调通知应用程序,不阻塞

  • 优点:实现了非阻塞,充分利用内核,适合高并发
  • 缺点:实现复杂