Linux event poll
首先使用一个东西之前至少要了解为什么要使用它,为什么需要poll这个操作,通常网络部分需要监听多个套接字,又要处理套接字,而在监听的过程中程序已经阻塞就不能去执行其他程序,所以需要引入IO复用
struct epoll_event数据结构
The struct epoll_event is defined as:
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t; //保存某个触发事件相关的数据
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
/*
其中events表示感兴趣的事件和被触发的事件,可能的取值为:
EPOLLIN:表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数可读;
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: ET的epoll工作模式;
*/
epoll_create函数
创建epoll文件描述符,成功返回文件句柄,否返回-1 设置errno
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_create1(int flags);
epoll_wait函数
轮询IO事件的产生
@epfd:由epoll_create生成的epoll专用的文件描述符;
@epoll_event:用于回传代处理事件的数组;
@maxevents:每次能处理的事件数;
@timeout:等待I/O事件发生的超时值;
返回值:success:发生的事件数
fail: 0
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
epoll_ctl函数
操作epoll文件描述符事件, 成功返回0 失败返回-1 设置errno
@epfd: epoll_create创建的文件句柄
@op:事件操作
@fd:需要监听的文件句柄
@event:指向epll event指针
操作事件:
EPOLL_CTL_ADD:在文件描述符epfd引用的epoll实例上注册目标文件描述符fd,并将事件事件与链接到fd的内部文件关联起来。
EPOLL_CTL_MOD:更改与目标文件描述符fd关联的事件事件。
EPOLL_CTL_DEL:从epfd引用的epoll实例中删除(取消注册)目标文件描述符fd。该事件将被忽略
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
例子:
#define MAX_NUM 40
typedef struct Event_data {
struct epoll_event event;
char path[1024];
}Event_data_s; *Event_data_p;
static int event_fd = 0;
static int fd[MAX_NUM] = {0};
pthread_t event_pthread;
pthread_t data_pthread;
Event_data_s Event_group[MAX_NUM];
void *event_process(void *arg)
{
struct epoll_event epoll_data;
char path_buf[1024] = {0};
int ret;
event_fd = epoll_create(MAX_NUMM);
if(event_fd < 0)
{
printf("create epoll fd fail %d%s\n", errno, strerror(errno));
return -1;
}
while(1)
{
sleep(1);
for(i = 0; i < MAX_NUM; i++)
{
snprintf(path_buf, sizeof(path_buf), "/dev/input/event%d", i);
fd[i] = open(path_buf, O_RDWR | O_NONBLOCK);
if(fd[i] < 0)
{
printf("open fd fail %s\n", strerror(errno));
continue;
}
ret = epoll_ctl(event_fd, EPOLL_CTL_ADD, fd[i], &epoll_data);
if(ret != 0)
{
close(fd[i]);
fd[i] = -1;
continue;
}
memcpy( Event_group[i].path, path_buf, sizeof(path_buf));
}
}
}
void *data_process(void *arg)
{
int ret = 0;
int i = 0;
char buf[1024] = {0};
struct epoll_event events[MAX_NUM];
while(1)
{
sleep(1)
ret = epoll_wait(event_fd, events, MAX_NUM, 100);
if(ret <= 0)
{
for(i; i<= MAX_NUM; i++)
{
if(access(Event_group[i].path, F_OK) != 0)
{
epoll_ctl(event_fd, EPOLL_CTL_DEL, event[i], NULL);
close(event[i]);
event[i] = -1;
}
}
continue;
}
}
}
int Event_init()
{
pthread_create(&event_pthread, NULL, event_process, NULL);
pthread_create(&data_pthread, NULL, data_process, NULL);
pthread_detach(event_pthread);
pthread_detach(data_pthread);
}