不涉及原理的Epoll使用笔记(一)

本文详细介绍了Epoll的基本概念,包括其作为文件管理者的角色,以及如何通过epoll_create、epoll_ctl和epoll_wait等函数实现Socket事件的高效监控。重点讲解了epoll_event结构和事件类型,帮助理解Epoll在Linux网络编程中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是Epoll

        Epoll的角色有点像一个管理员。Epoll被创建后,用户可以把关注的文件注册给Epoll,Epoll就开始监控这些文件的状态,文件出现了用户关心的事件时,用户程序可以获取到这些事件并处理。

        万物在linux上都是文件,Socket也是文件,因此,Epoll可以管理Socket的文件句柄。具体来讲,用户可以把socket句柄注册到Epoll上去,然后关注socket的建立、读写事件。Epoll的好处是,无论多少客户端来连接,都会体现为socket句柄上发生某些特定事件,这些事件只要注册了epoll就会发现,返回给我们的程序,实现高并发的通信。

二、Epoll函数

Epoll一共有三个函数:

1. 使用epoll_create创建Epoll

int epfd = epoll_create(int size);
// size : 在这个epoll上能关注的最大文件个数
// epdf : epoll 句柄  

 2. 使用epoll_ctl注册/删除/修改想关注的文件和事件

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// epfd:  epoll句柄
// op:    要对文件做什么操作,
//        EPOLL_CTL_ADD:注册新的fd到epfd中;
//        EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
//        EPOLL_CTL_DEL:从epfd中删除fd;
// fd:   被Epoll管理的文件句柄
// event:内核需要监听什么事件

3. 使用epoll_wait等待事件发生,并把事件详情返回给用户程序。

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
// epfd:        Epoll句柄
// events:       事件的集合
// maxevents:    每次接收的最大事件数;
// timeout:      等待I/O事件发生的超时值
// 返回值:       事件个数

使用epoll_wait需要注意的是: 

epoll_wait等待注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中。同时,将注册在epfd上的socket fd的事件类型给清空,所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设置关注的socket fd的事件类型。这时不用EPOLL_CTL_ADD,因为socket fd还在Epoll的管理中,只是Epoll关注fd的事件类型被清空了。

引用自(66条消息) epoll机制:epoll_create、epoll_ctl、epoll_wait、close_鱼思故渊的专栏-优快云博客_epoll_createhttps://blog.youkuaiyun.com/yusiguyuan/article/details/15027821

三、Epoll的事件 epoll_event

简单来讲,epollevent这个结构体里,保存了两样东西:发生了什么事和哪个文件出事了。epoll_event定义为:

struct epoll_event {
__uint32_t events; /* 事件描述,出了什么事 */
epoll_data_t data; /* 文件句柄,哪个文件出事了 */
};

到底发生哪些事能被Epoll监控到呢?Epoll定义了一些宏。根据数值和可以分为以下类型,也就是说events可以取以下数值:

EPOLLIN触发该事件,表示对应的文件描述符上有可读数据。(包括对端SOCKET正常关闭)
EPOLLOUT触发该事件,表示对应的文件描述符上可以写数据。
EPOLLPRI表示对应的文件描述符有紧急的数据可读
EPOLLERR表示对应的文件描述符发生错误
EPOLLHUP表示对应的文件描述符被挂断
EPOLLET将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的
EPOLLONESHOT只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里。

那么怎么描述是哪个文件出事了呢?epoll_data_t定义为:

typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

epoll_data是一个联合体。 联合体的意思就是,这个epoll_data可以是void*型、可以是int型,也可以是__uint32_t,还可以是__uint64_t。但是它只能是其中一种类型。

联合体,就是将几种数据类型联合起来的一种数据结构,但是它们共用一个空间。

怎么理解呢?川剧变脸见过没,就是来来回回的变来变去,给人看的眼花缭乱的,但是不管你怎么变,面具下的脸却始终不变。同样的道理,各种数据类型就是各种脸谱,对外展现了不同的形象,唯一不变的就是它的内存空间的二进制数据始终都是一样的,它们占用的空间也是同一个地方,只是这些二进制数据当你把它看成浮点型的时候,它是浮点数;当你把它看成无符号整数的时候,就是无符号数,或者你把这些数据看成有符号的数据,那么它就是有符号数据。

转自C语言之联合体(union) (baidu.com)https://baijiahao.baidu.com/s?id=1623457037181175751&wfr=spider&for=pc

epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到于这个client对应的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。

下一篇文章分析一段具体的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值