Linux编程基础之epoll简析

在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_SIZE		256		// 定义缓冲区的大小

/* 定义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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值