五种IO模型

  1. 在网络环境下,通俗的讲,将IO分为两步:
    (1)等;
    (2)数据搬迁
  2. 因此如果想要提高IO效率,需要将等的时间降低。
  3. 五种IO模型包括:阻塞IO、非阻塞IO、信号驱动IO、IO多路复用以及异步IO

阻塞IO(blocking I/O)

  1. 在内核将数据准备好之前,系统调用会一直等待所有的套接字,默认的是阻塞方式
  2. fd=connect();
    write(fd);
    read(fd);
    close(fd);
    

    程序的read必须在write之后,当write阻塞住了,read就不能执行下去,一直处于等待状态

非阻塞IO

  1. 每次客户询问内核是否有数据准备好,即文件描述符缓冲区是否就绪。当有数据报准备好时,就进行拷贝数据报操作。当没有数据报准备好时,也不阻塞程序,内核直接返回未就绪的信号,等待用户程序的下一个轮询
  2. 轮询对于CPU来说是较大的浪费,一般只有在特定的场景下使用

信号驱动IO

  1. 信号驱动IO模型,应用进程告诉内核:当有数据报准备好的时候,给我发送一个信号,对SIGIO信号进行捕捉,并且调用我的信号处理函数来获取数据报。

IO多路复用

  1. IO多路复用使用select、poll和epoll函数实现
  2. 这些函数有一个集合是文件描述符集合,对这些文件描述符进行循环监听,当某个文件描述符就绪时就对这个文件描述符进行处理
  3. select、poll和epoll函数只负责等,recvfrom只负责拷贝,IO多路复用属于阻塞IO,但可以对多个文件描述符进行监听,所以效率较阻塞IO的高。

异步IO

  1. 当应用程序调用aio_read时,内核一方面去取数据报内容返回,另一方面把程序控制权还给应用进程,应用进程继续处理其他事情,是一种非阻塞状态。
  2. 当内核中有数据报就绪时,由内核将数据报拷贝应用到应用程序中,返回aio_read中定义好的函数处理程序。
  3. 很少有Linux系统支持异步IO模型,Windows的IOCP就是异步IO模型。
  4. 综上,阻塞程度:阻塞IO>非阻塞IO>多路复用IO>信号驱动IO>异步IO,效率由低到高。

epoll原理

  1. 调用顺序:
     int epoll_create(int size);
     int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
     int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout);
    
  2. 首先创建一个epoll对象,然后使用epoll_ctl对这个对象进行操作,把需要监控的描述添加进去,这些描述如将会以epoll_event结构体的形式组织成一棵红黑树,接着阻塞在epoll_wait,加入大循环,当某个fd上有事件发生时,内核会把对应的结构体放入到一个链表中,返回有事件发生的链表。