epoll使用总结

前言

  最近学习了epoll,虽然封装好的epoll只有简单的几个api,但是还是有很多需要注意的细节。

简介

  编程中往往需要一些IO操作,IO操作最耗时的其实是线程等待IO处理的时间。你如果不知道对面什么时候要写/读,你就只能阻塞在那里等待,无法执行后续事件。或者是说,你同时有很多IO操作,很多IO操作都是在等待的过程,这样的等待,实在是很浪费CPU。这个时候我们可以设计一个对象,让他帮我们管理这些需要进行IO操作的句柄,让他去帮其他线程等待,等到IO操作就绪,再提醒相应线程去处理。这个技术叫做IO多路复用技术,前面提到的帮我们管理的对象,现在被实现出来的有select,poll,epoll。

  那么,这些帮我们管理的对象又是如何实现的呢?假设你现在有10个句柄,然后句柄A进入就绪态,那我怎么就知道句柄A进入就绪态了呢?最粗暴的方法就是,我每一个句柄都检查一遍,然后看下有没有已经就绪的句柄。这是是select、poll中的实现方式,这样的效率可想而知不会太高,如果句柄很多,那你大部分时间都会花费在查找上。

  epoll提出了一个思想,利用函数回调的思想,我不需要去找哪个句柄进入就绪态了,让进入就绪态的句柄自动来找我。底层实现涉及到中断机制,这里暂时不细讲。简单点理解epoll就是,有一个红黑树负责管理句柄和事件,然后当句柄就绪,这个事件会被拷贝一份放到一个双链表中,这个双链表放着所有就绪事件。如果我想取就绪事件,可以去链表中取。

epoll结构类型和方法

 

typedef union epoll_data 
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t; /* 提供多种数据类型,如果需要自己定义事件,可以使用ptr指针,不需要的话直接使用fd */

struct epoll_event 
{
uint32_t events;    /* 定义epoll发生事件类型,比如EPOLLIN,当发生读事件时,下面的data会被放入双链表中。ET和LT模式也是在此设置 */
epoll_data_t data;    /* 用户自己定义的事件类型,事件发生时被送到双链表上 */
};

/* 
 * @brief 创建一个epoll
 * @param __size 最大处理事件数量
 * @return 创建成功返回__epfd
 */
int epoll_create (int __size); 

/* 
 * @brief 在epoll上添加/删除/修改事件
 * @param __epfd epoll标识
 * @param __op epoll发生事件类型,比如EPOLLIN,EPOLLOUT,EPOLLET
 * @param __fd 需要监听的句柄
 * @param __event 用户自定义数据,用于发生事件后的处理
 * @return 正常返回0,异常返回-1
 */
   
int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event); 

/*
 * @brief 用于获取就绪事件
 * @param __epfd epoll标识
 * @param __events 用于接收就绪事件的数组
 * @param __maxevents 设置最大接收数量,一般是__events数组大小
 * @param __timeout 设置超时事件,设置为0是非阻塞,设置为-1为永久阻塞
 * @return 返回就绪事件数量
 */

int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);

epoll常见问题

1、epoll如何封装?

  一开始我把epoll当作一个事件提醒器,也就是每次有读/写事件时,我接收到提醒,然后执行对应方法。所以起初我在epoll_data中是直接存入句柄,事实上网上很多博客都是这个版本。可是在实践中发现,这种方法很不方便,如果可以把做什么(回调函数)和句柄绑定起来就好了。可以发现epoll_data有个ptr指针成员,那我可以自己封装个结构体,里面存入回调函数,这样事件发生后,我直接执行对应的回调函数不就好了吗?同时结构体可以存入其他变量,用于函数调用。后来发现可以再抽象一波,可以把epoll封装成一个线程,run方法中去等待epoll,获取事件,调用回调函数。这样我只需要考虑外部怎么实现回调函数,然后注册上去就好了。

2、epoll如何支持多个回调函数?

3、如果同时有两个事件,会不会冲突?

转载于:https://www.cnblogs.com/scaugsh/p/9454708.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值