Linux编程基础之epoll简析

来源:互联网 发布:淘宝软文范例 编辑:程序博客网 时间:2024/06/06 07:02

在linux系统编程中,通常需要对多个文件的变化同时进行监测(称为多路复用)。传统的poll机制在监测文件数量较大时效率会明显的降低,epoll是对传统poll机制的扩展,不会因为监测文件数量过多而导致监测效率降低。本文通过一个小例子来简单说一下epoll的实现原理,这个小例子实现的功能是让epoll同时检测多个文件,当有任何一个文件可读时就把它的内容打印出来。


一、epoll涉及的常用API

1、创建一个epoll实例

int epoll_create(int size);
size : 在linux kernel2.6 之后,这个参数就不再使用,但必须大于0;

返回值:返回一个epoll的文件描述符

2、epoll设置函数

 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd : 前面创建epoll实例时返回的文件描述符

op : 具体的操作

        EPOLL_CTL_ADD : 向epoll中添加一个要监视的文件

        EPOLL_CTL_DEL : 从epoll中删除一个要监视的文件

        EPOLL_CTL_MOD : 改变要监视文件的相关属性,具体属性改变的设置在第四个参数event当中

fd : 要操作的文件的文件描述符

event:要操作的文件的相关事件属性设置,这个结构体的具体定义如下:

 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 */ };
3、epoll监听文件IO事件的函数
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
epfd :创建epoll实例的文件描述符

events :表示有哪些文件发生了变化,并把相应的信息放入events数组当中

maxevents :表示最大检测的文件的数量

timeout :表示超时时间,单位是毫秒,-1表示一直等待知道指定的文件状态发生变化。

二、测试
编写一个小例子来测试epoll的用法。通过epoll来检测多个文件,当其中有文件可读时就把文件的信息读取并打印出来,具体实现如下:

#include <stdio.h>#include <sys/epoll.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#define BUFFER_SIZE256// 定义缓冲区的大小/* 定义epoll最大监听的文件数量 */#define  EPOLL_MAX_EVENTS  32/* 定义一个epoll事件的数组,用来存放监听文件的信息 */static struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];/* *Usage : epoll <file1> [file2] [file3] ... */int main(int argc, char *argv[]){int epoll_fd;int tmp_fd;int i;int result;char readbuf[BUFFER_SIZE];int readlen;struct epoll_event eventItem;if(argc < 2){printf("Usage : %s <file1> [file2] [file3] ...\n", argv[0]);return -1;}/* 打开一个epoll文件的文件描述符 */epoll_fd = epoll_create(1);// 传入的参数可以随意,只要大于0即可,没有什么具体意思if(-1 == epoll_fd){printf("epoll_create error!\n");return -1;}/* 将传入的文件名作为参数加入到epoll的监听事件当中 */for(i = 1; i < argc; i++){tmp_fd = open(argv[i], O_RDWR);// 以读写方式打开memset(&eventItem, 0, sizeof(eventItem));   eventItem.events = EPOLLIN;// epoll检测相应的文件的读操作将被唤醒    eventItem.data.fd = tmp_fd;    result = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tmp_fd, &eventItem);if(-1 == result){printf("epoll_ctl error!\n");return -1;}}while(1){/* 调用epoll_wait来监听事件 */result = epoll_wait(epoll_fd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);if(-1 == result)// 发生错误{printf("epoll wait error!\n");return -1;}else{for(i = 0; i < result; i++)// 对监听到的事件进行遍历,把读到的信息打印出来{readlen = read(mPendingEventItems[i].data.fd, readbuf, BUFFER_SIZE);readbuf[readlen] = '\0';printf("read data : %s\n", readbuf);}}}return 0;}
编译并运行结果如下:

















0 0