深入理解NIO底层原理--epoll多路复用

在使用选择和轮询时,我们管理用户空间上的所有内容,并在每次调用时发送集合以等待。要添加另一个套接字,我们需要将其添加到集合中并再次调用select/poll。

epoll系统调用帮助我们创建和管理内核中的上下文。我们将任务分为3个步骤:

  1. 使用epoll_create在内核中创建上下文
  2. 使用epoll_ctl在上下文中添加或删除文件描述符
  3. 使用epoll_wait等待上下文中的事件

epoll底层逻辑

struct epoll_event events[5];
  // 使用epoll_create在内核中创建上下文
  int epfd = epoll_create(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 sockaddr*)&client, &addrlen);
    ev.events = EPOLLIN;
    // 上下文中添加或删除文件描述符
    epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev); 
  }
  
  while(1){
  	puts("round again");
        // 等待上下文中的事件
  	nfds = epoll_wait(epfd, events, 5, 10000);
	
        // 遍历nfds次受影响事件个数
	for(i=0;i<nfds;i++) {
	    memset(buffer,0,MAXBUF);
	    read(events[i].data.fd, buffer, MAXBUF);
	    puts(buffer);
	}
  }

linux-io-multiplexing-epoll图解:

epoll优点:

epoll解决了深入理解NIO底层原理--poll多路复用提到的两个缺点:

  • 由于用户态和内核态共享epfd,避免了用户态--内核态切换的开销
  • epoll_wait返回具有就绪文件描述符对象的个数,不再需要O(n)再遍历

源码参考

https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/#.X2gdbYu-uUm

 

 

 


版权声明:本文为wangzuojia001原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。