在使用选择和轮询时,我们管理用户空间上的所有内容,并在每次调用时发送集合以等待。要添加另一个套接字,我们需要将其添加到集合中并再次调用select/poll。
epoll系统调用帮助我们创建和管理内核中的上下文。我们将任务分为3个步骤:
- 使用epoll_create在内核中创建上下文
- 使用epoll_ctl在上下文中添加或删除文件描述符
- 使用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版权协议,转载请附上原文出处链接和本声明。