常见IO模型
我们所说的IO都是操作系统层面的IO,在网络环境下,通俗的来说将IO分为两种:1.等、2.数据搬迁。如果想要提高效率,就等缩短等待时间。
对于一次IO访问,他会经历两个阶段:等待数据准备就绪;将数据从内核拷贝的过程中
1.阻塞IO(Blocking I/O)
当程序需要从内核态读取数据的时候,必须等待内核空间将数据返回后,才可以继续向下执行。效率低,浪费CPU资源。
2.非阻塞IO(NoBlocking I/O)
当程序发起调用后,操作系统如果没有准备好数据,返回错误状态码,应用程序开始轮询再次发起调用,不进入阻塞状态,直到操作系统数据准备好了,将数据返回给用户。对于阻塞IO而言,NIO提高了运行效率,对于CPU而言,轮询是一次较大的消耗。
3.信号驱动IO(Signal Blocking I/O)
开启信号IO驱动功能,通过系统调用sigation执行一个信号处理函数。当数据报准备好的时候,给我发送一个信号,并且调用我的信号处理函数来获取数据报。
4.I/O多路复用(multiplexing)
操作系统的底层函数提供函数进行监听,监听内核态数据有没有准备好。
select()
应用程序发送一次调用后,就由select()函数负责监听,应用程序不需要轮询,当有数据准备好了,那么就将数据向用户态返回。
优点:不需要轮询,解放CPU。
缺点:1.有监听数量的限制,最多监听1024个
2.不能直接找到已经准备好数据的,需要对整个集合进行遍历操作,直到找到就绪的为止。
poll()
与select相同,只是没有最大数量限制而已。
epoll()
给每个监听的文件符(fd)绑定一个回调函数,当数据准备就绪后,触发回调函数处理。这样的优点就是不不要遍历。
5.异步IO(asynchronous I/O)
告知内核启动某个操作,并让内核在整个操作完成之后(将数据从内核复制到自己的缓冲区),进行通知 。
和信号驱动模型的主要区别: 信号驱动IO由内核通知我们何时开始的IO操作,在client进行IO操作是需要等待的,所有是同步的。AIO模型是由内核通知我们IO何时完成的,client不需要进行IO处理,是异步的。