IO多路复用

27 阅读2分钟

IO多路复用中select、poll、epoll

select

int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout); maxfdp1:最大fd的index + 1,例如有3个文件描述符,分别是10,11,19, 这里maxfdp1 就是19+1 = 20 readset:读set,一个bitmap的数据结构,最长1024个元素,元素只有0、1,0代表的是未监听该fd,1代表的监听了该fd

writeset:写事件,如果不关心的话,可设置为NULL exceptset: timeout:超时时间

select函数是阻塞的,如果没有任何的文件描述符接受事件的话,会一直阻塞,直到有一个或者多个文件描述符有事件

readset会从用户态复制到内核态,内核态来判断是否有事件触发

poll

struct pollfd {
   int fd;
   short events;  // 在意的事件。读事件POLLIN、写事件:POLLOUT、读和写:POLLIN&POLLOUT
   short revents;  // 
}

// 初始化5个文件描述符
for(i = 0; i < 5; i++) {
   memset(&client, 0, sizeof(client));
   addrlen = sizeof(client);
   pollfds[i].fd = accept(sockfd, (struct socketaddr*) &client, &addrlen);
   pollfds[i].events = POLLIN;
}
sleep(1);
// 循环判断文件描述符是否发生变更
while(1) {
   puts("round again");
   poll(pollfds, 5, 50000);  // 阻塞函数,如果接收到事件,则将对应的文件描述符的revents置位,置位为PULLIN
   
   for(i = 0; i < 5; i++) {   // 还是需要循环数组判断
      if(pollfds[i].events & POLLIN) { // 判断revents是否被置位为POLLIN,true的话代表有数据
          pollfds[i].revents = 0;  // 恢复为0
          memset(buffer, 0, MAXBUF);
          read(pollfds[i].fd, buffer, MAXBUF);  // 读取数据并处理
          puts(buffer);
      }
   }
}

int poll ( struct pollfd * fds, unsigned int nfds, int timeout); fds:文件描述符数组 nfds:数组个数 timeout:超时时间

epoll

最新的一种多路IO复用的函数

struct epoll_event events[5];
int epfd = epoll_creat(10);

for(i = 0; i < 5; i++) {
    static struct epoll_event ev;
    memset(&client, 0, sizeof(client));
    addrlen = sizeof(client);
    ev.data.fd = accept(sockfd, (struct socketaddr*) &client, &addrlen);
    ev.events = EPOLLIN;   // 指定fd监听的事件类型
    epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev);  // 配置epollfd,初始化epfd结构,里面是一批fd_events的结构
}

while(1) {
    puts("round again");
    // 用户态和内核态共享epfd的这块内存,如果有某个fd有数据进来,则会进行epfd中数据的重排,有数据的排在前面,没数据的排在后面
    // 返回的nfds是有数据触发的fd的总数
    nfds = epoll_wait(epfd, events, 5, 10000); 
    
    for(i = 0; i < nfds; i++) {  // 只需要遍历前面几个有数据的fd
       memset(buffer, 0, MAXBUF);
       read(events[i], data.fd, buffer, MAXBUF);
       puts(buffer);
    }
}