深入理解epoll

概述

在网络编程中,高效地处理大量并发连接是一个关键问题。而Linux提供的epoll机制成为了解决这个问题的重要工具。epoll是一种I/O事件通知机制,通过三个主要函数,即epoll_create、epoll_ctl和epoll_wait,实现了高性能的事件驱动并发编程。让我们深入了解这三个函数以及它们的使用方法。

1. epoll_create - 创建一个epoll实例

int epoll_create(int size);

size:创建的红黑树的监听节点数量。(仅供内核参考。)
返回值:指向新创建的红黑树的根节点的 fd。
-1:代表错误

2. epoll_ctl - 控制epoll实例的事件

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epfd:epoll_create 函数的返回值。 epfd
op:对该监听红黑数所做的操作。
EPOLL_CTL_ADD 添加fd到 监听红黑树
EPOLL_CTL_MOD 修改fd在 监听红黑树上的监听事件。
EPOLL_CTL_DEL 将一个fd 从监听红黑树上摘下(取消监听)
fd:待监听的fd
event: 本质 struct epoll_event 结构体指针
返回值:成功 0; 失败: -1 errno

结构体介绍

struct epoll_event {
		__uint32_t events; /* Epoll events */
		epoll_data_t data; /* User data variable */
	};
	typedef union epoll_data {
		void *ptr;
		int fd;
		uint32_t u32;
		uint64_t u64;
	} epoll_data_t;

events取值:

EPOLLIN : 表示对应的文件描述符可以读(包括对端SOCKET正常关闭)
EPOLLOUT: 表示对应的文件描述符可以写
EPOLLERR: 表示对应的文件描述符发生错误
等等(不重要)

data: 联合体(共用体):

int fd; 对应监听事件的 fd
void *ptr; 回调函数
uint32_t u32;
uint64_t u64;

3. epoll_wait - 等待事件发生

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

epoll_wait函数用于等待事件发生,当事件发生时将返回就绪的文件描述符以及对应的事件类型。参数包括:

epfd:epoll_create 函数的返回值。 epfd

events:传出参数,【数组】, 满足监听条件的 那些 fd 结构体。

maxevents:上面数组元素的总个数。 eg:struct epoll_event evnets[1024]->1024

timeout:
-1: 阻塞
0: 不阻塞
大于0: 超时时间 (毫秒)
返回值:
大于0: 满足监听的 总个数。 可以用作循环上限。
0: 没有fd满足监听事件
-1:失败。 errno

在这里插入图片描述

伪代码

关于代码实现可以参考:链接
epoll实现多路IO转接思路:

lfd = socket();			监听连接事件lfd
bind();
listen();

int epfd = epoll_create(1024);				epfd, 监听红黑树的树根。

struct epoll_event tep, ep[1024];			tep, 用来设置单个fd属性, ep 是 epoll_wait() 传出的满足监听事件的数组。

tep.events = EPOLLIN;					初始化  lfd的监听属性。
tep.data.fd = lfd

epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &tep);		将 lfd 添加到监听红黑树上。

while (1) {

	ret = epoll_wait(epfd, ep,1024-1);			实施监听

	for (i = 0; i < ret; i++) {
		
		if (ep[i].data.fd == lfd) {				// lfd 满足读事件,有新的客户端发起连接请求

			cfd = Accept();

			tep.events = EPOLLIN;				初始化  cfd的监听属性。
			tep.data.fd = cfd;

			epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &tep);

		} else {						cfd 们 满足读事件, 有客户端写数据来。

			n = read(ep[i].data.fd, buf, sizeof(buf));

			if ( n == 0) {

				close(ep[i].data.fd);

				epoll_ctl(epfd, EPOLL_CTL_DEL, ep[i].data.fd , NULL);	// 将关闭的cfd,从监听树上摘下。

			} else if (n > 0{--write(ep[i].data.fd, buf, n);
			}
		}
	}

总结

通过使用epoll_create、epoll_ctl和epoll_wait这三个主要函数,我们可以充分利用Linux的epoll机制来实现高效的事件驱动并发编程。首先,通过创建epoll实例,我们能够监控多个文件描述符。然后,使用epoll_ctl函数来添加、修改和删除需要监控的事件。最后,通过调用epoll_wait函数来等待事件的发生并处理就绪的文件描述符。

这些函数的合理使用可以帮助我们有效地管理大量并发连接,提高系统的性能和响应能力。当然,在实际应用中,我们还需要结合其他的网络编程知识和技巧,以实现更加稳定和高效的网络应用程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值