IO的多路复用

一、select()
1.1、处理流程

1、创建文件描述符集合 fd_set

2、添加文件描述符到集合中 int FD_ISSET(int fd, fd_set *set);

3、通知内核开始监测 select 

4、内核返回的结果(两个结果,1、是那种类型得文件),做对应得操作(对IO读、写操作)

1.2、函数接口

(1)select()函数接口

  #include
   #include
   #include

   int select(int nfds, fd_set *readfds, fd_set *writefds,
              fd_set *exceptfds, struct timeval *timeout);
功能:检查多了IO
参数:
     nifds:最大文件描述符+1(方便内核查找)
      readfds 关注读事件的文件描述符集合
      writefds:关注的写事件的文件描述符集合
      exceptfds:其他异常文件描述符的集合
      timeout:超时时间,等到了这个时间到了,就不在死等了,如果不设置超时时间,则设置为NULL
代参宏
   void FD_CLR(int fd, fd_set *set);把这个套接字从这个集合中删除掉
   int  FD_ISSET(int fd, fd_set *set);判断对应位有没有设置为1
   void FD_SET(int fd, fd_set *set);要有多个设置文件,则每个调用一遍
   void FD_ZERO(fd_set *set);
   返回值
   成功:返回到达事件的个数(因为IO端口事件可能同时到达)
   失败L:-1设置了超时时间:超时时间到达但没有时间,返回0

  • 文件描述符的范围 0~1023
二、epoll()
2.1、流程
  1. 创建文件描述符集合
  2. 添加文件描述符到集合
  3. 通知内核开始监测
  4. 根据返回的结果做对应的操作,对io读,写操作
2.2、epoll函数

epoll:

1、创建文件描述符集合:(在内核中)

函数接口

#include

   int epoll_create(int size);告诉内核大概放多少个文件描述符
   返回值:
   成功:返回一个文件描述符(集合句柄)
   失败:-1

2、添加文件描述符到集合

#include

   int  epoll_ctl(int  epfd,  int  op,  int  fd,  struct  epoll_event*event);
   参数:
   epfd :文件描述符集合句柄
   op :
          EPOLL_CTL_ADD:向集合中添加文件描述符
          EPOLL_CTL_MOD:修改集合
          EPOLL_CTL_DEL:删除文件描述符
          EPOLL_CTL_DEL(集合,对象)
          删除的时候不需要关注他具体做什么操作
    fd:文件描述符
    struct  epoll_event *event:
    对这个文件描述符所对应的事件做什么操作
     struct epoll_event {
               uint32_t     events;      /* Epoll events */
               EPOLLIN  读操作
               EPOLLOUT 写操作
               epoll_data_t data;        /* User data variable */
typedef union epoll_data {
               void        *ptr;
               int          fd;//设置读事件或者写事件的关注的文件描述符
               uint32_t     u32;
               uint64_t     u64;
           } epoll_data_t;
返回值
成功:返回0
失败:返回-1或者errno

3、通知内核开始监测

#include

   int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
   功能:监测IO事件
   参数:
   epfd:文件描述符集合句柄
   events:保存最终的结果,的数组的首地址(a)
   maxevents: 监测时事件的个数
   timeout :超时时间
   -1:设置超时时间
   返回值:
   成功:返回到达事件的个数
   失败:返回-1
   超时时间结束:0
三、三者的特点
3.1、select

1.select监听文件描述符最大个数为1024(数组)时间复杂度为0(n)

2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据

3.select需要循环遍历一次才能找到产生的事件

4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)

3.2、poll

1.监测文件描述符不受上限限制(链表)O(n)

2.监听的文件描述符集合在用户层,需要内核层向用户层传递数据

3.需要循环遍历一次才能找到产生的事件

4.只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)

3.3、epoll
  1. 创建内核事件表,不受到文件描述符上限限制(红黑树)
  2. 监听的事件表在内核中,直接在内核中监测事件效率高
  3. epol1会直接获得产生事件的文件描述符的信息,而不需要遍历检测
  4. epo11既能工作在水平触发模式,也能工作在边沿触发模式
四、 应用场景

IO多路复用只用一个进程

耗时比较大;不适合处理比较耗时的任务

应用场景

1、构建并发服务器,用来检测多个客户端套接字

2、使用io多路复用监测多个IO所对应的通信(如:网络、串口、can)

3、在阻塞io中,进行超时监测

实际上是在一个进程中监测多个io的读和写

五、注意
  • linux一切皆文件
  • 并发量比较小的时候,三者之间的区别不大
  • 只有并发量比较大的时候,epoll才体现优势

你可能感兴趣的:(linux,服务器,运维,tcp/ip,进程)