IO多路复用接口Linux内核源码剖析,源码之前,了无秘密
Linux epoll内核源码剖析
前面介绍了select/poll,此文章将讲解epoll,epoll是select/poll的增强版,epoll更加高效,当然也更加复杂
epoll高效的一个重要的原因是在获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就可以
本文将先讲解如何使用epoll,然后再深入Linux内核源码分析epoll机制
epoll应用程序编写
epoll机制提供了三个系统调用epoll_create
、epoll_ctl
、epoll_wait
下面是这三个函数的原型
-
epoll_create
int epoll_create(int size);
此函数返回一个epoll的文件描述符
-
epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
此函数是添加、删除、修改事件
epfd:epoll的文件描述符
op:表示选项,EPOLL_CTL_ADD(添加事件)、EPOLL_CTL_MOD(修改事件)、EPOLL_CTL_DEL(删除事件)
fd:要操作的文件描述符
event:事件信息
-
epoll_wait
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
此函数是等待条件满足,放回值为准备就绪的事件数
epfd:epoll的文件描述符
events:返回的事件信息
maxevents:要等待的最大事件数
timeout:超时时间
-
epoll_event
struct epoll_event { uint32_t events; //epoll事件 epoll_data_t data; //联合体,一般表示文件描述符 };
-
demo
下面这段代码,监听标准输入,当标准输入可读时,就打印读取到的信息
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#define MAX_EVENTS 10
int main(int argc, char* argv[])
{
struct epoll_event ev, events[MAX_EVENTS];
int nfds, epollfd, len;
char buf[1024];
int n;
epollfd = epoll_create(10);
if (epollfd == -1)
{
perror("epoll_create");
exit(-1);
}
ev.events = EPOLLIN;
ev.data.fd = 0;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, 0, &ev) == -1)
{
perror("epoll_ctl: listen_sock");
exit(-1);
}
while(1)
{
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1)
{
perror("epoll_pwait");
exit(-1);
}
for (n = 0; n < nfds; ++n)
{
if(events[n].events & EPOLLIN)
{
len = read(events[n].data.fd