事件轮询接口

epoll使得时间监听器的注册与实际的事件监视工作脱钩,有三种系统调用:

  1. 初始化epoll的上下文;
  2. 将要查看的文件描述符加入上下文(或移除);
  3. 实际执行时间等待。
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/epoll.h>
#include <memory.h>
#include <stdlib.h>

int main(){
//创建epoll,epfd为可用控制的句柄
int epfd = epoll_create(2);

struct epoll_event event1[2];
struct epoll_event event2[2];

event1[0].events = EPOLLIN;
event1[0].data.fd = STDIN_FILENO;
event1[1].events = EPOLLOUT;
event1[1].data.fd = STDOUT_FILENO;

int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event1[0]);
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, STDOUT_FILENO, &event1[1]);

struct epoll_event* events = (epoll_event*)malloc(sizeof(struct epoll_event)*2);
sleep(2);
int nr_events = epoll_wait(epfd, events, 2, -1);

int i;
for(i = 0; i < nr_events; i++){
printf("event=%d on fd=%d\n", events[i].events, events[i].data.fd);
}
free(events);

close(epfd);
return 0;
}

epoll最简单的程序就是这样吧。

关于ET、LT两种工作模式:

  1. ET模式仅当状态发生变化的时候才得到通知,这里的状态变化并不包括缓冲区还有未处理的数据,也就是即使没有把数据读完还有剩余的,下次wait的时候不会发现这个变化;
  2. LT模式下只要有数据就会一直通知下去。

用下面的程序可以看到这两种模式的区别:

int main(){
int epfd = epoll_create(2);

struct epoll_event event1[2];

event1[0].events = EPOLLIN|EPOLLET;//设置为边缘触发模式
event1[0].data.fd = STDIN_FILENO;

int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event1[0]);

struct epoll_event* events = (epoll_event*)malloc(sizeof(struct epoll_event));

sleep(2);//输入ab
int nr_events = epoll_wait(epfd, events, 1, 10);

char ch;
read(STDIN_FILENO, &ch, 1);//注意这里和scanf的区别
printf("%d %c\n", nr_events, ch);

nr_events = epoll_wait(epfd, events, 1, 10);

read(STDIN_FILENO, &ch, 1);
printf("%d %c\n", nr_events, ch);

free(events);

close(epfd);
return 0;
}
原文地址:https://www.cnblogs.com/ggzwtj/p/2207222.html