【网络】多路转接模型epoll

目录

1. 历史定位

2. 接口

2.1 创建epoll句柄

int epoll_create(int size);

2.2 操作epoll

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

2.3 获取就绪事件结构

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

3. epoll监控的内部工作原理

4. epoll简单服务端多路转接服务器

5. epoll的工作模式


 

1. 历史定位

迄今为止,linux平台性能最好的IO多路转接模型。没有之一。

2. 接口

2.1 创建epoll句柄

int epoll_create(int size);

参数:

size:目前没有含义了,但是需要大于0,兼容旧内核返回值:返回的epoll操作句柄;

ecdd8ae57fd10d6d7775fa871d454040.jpeg

2.2 操作epoll

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

参数:

epfd :

        epoll操作句柄

op :当前要执行的行为

  • EPOLL_CTL_ADD
  • 添加一个文件描述符对应的事件结构到epoll当中
  • EPOLL_CTL_MOD
  • 修改一个文件描述符的事件结构
  • EPOLL_CTL_DEL
  • 从epoll当中删除一个文件描述符对应的事件结构

fd:

        待处理(添加,修改,删除)的文件描述。

event:

        文件描述符对应的事件结构event中events是我们要关心的事件,这里如果同时多个事件那么我们也用或的方式连接。

ca968bcf0418475a8dcf169007a350bf.jpeg

返回值:

        0正常。

        -1失败。

2.3 获取就绪事件结构

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

参数:

epfd :

        epoll的操作句柄

events :

        事件结构数组(集合),从epoll当中获取就绪的事件结构

maxevents :

        最多一次获取多少个事件结构

timeout :

  • >0 :带有超时事件
  • ==O:非阻塞
  • <0:阻塞

返回值:

        就绪的文件描述符个数

3. epoll监控的内部工作原理

        这里epoll监控的内部工作原理:整个epoll的工作原理就是调用epoll_create创建红黑树和双向链表这两个数据结构,然后我们用epollctr将要监控的文件描述符添加到红黑树中,添加到红黑树中,然后epoll就再内核中帮我们一直监控遍历红黑树,有就绪事件发送就添加到双向链表中,然后通过epoll_wait从双向链表当中获取就绪事件。

3c0ee6e29795584e3a6c75b63e659f12.jpeg

4. epoll简单服务端多路转接服务器

这里我们可以先封装一个对于服务端的tcp类,来为服务端提供tcp服务。

de0a20b58654c55097235f6d5afa0730.jpeg

然后我们来实现一个epoll的监控

d26b40e717f4729976588156e2bed21d.jpeg

我们运行代码可以看到多个客户端连接服务端并向其发送消息服务端都可以接收到。

76f3be1cd2b3b2b5ea7667ecce19509e.jpeg

5. epoll的工作模式

默认工作模式:LT水平触发

LT︰水平触发(“亲妈”模式:只要达到触发事件的条件,则一定乐此不疲的触法。);友好

换个说法:当读就绪或者写就绪的时候,则一定乐此不疲的通知。举个例子当我们用epoll监听新连接套接字的时候,当就新连接套接字就绪的时候也就是接收缓冲区中有消息的时候那么这时epoll会一直通知处理。直到接收缓冲区中消息都被读出。

ET∶边缘触发(“后妈”模式:当到达触发事件的条件后,只会触发一次);

要求程序员一次将数据全部读回来换个说法:当读就绪或者写就绪的时候,只会通知一次。举个例子当我们用epoll监听新连接套接字的时候,当就新连接套接字就绪的时候也就是接收缓冲区中有消息的时候那么这时epoll只通知一次,也就是当我们用epoll_wait来获取就绪事件的数组的时候只有这一次会将就绪事件的获取到。之后就无法获取。所以这就要求我要一次性将数据全部都读取回来。

这里的水平触发和边缘触发是针对某个文件描述符来说的。这里在设置某个事件是水平触发还是边缘触发只需要将文件描述符的关心事件events或一个EPOLLET就可以了。

94fa142077d551add741956c29dd7041.jpeg

 

这里验证边缘触发,将新连接套接字的工作方式换为非阻塞和边缘触发方式。非阻塞是因为这里如果当接收缓冲区中刚好没有数据了,但是此时还要接收那么recv就会进入阻塞状态。

a8d54e214cdce350e99b15e5ad1433ff.jpeg

tcp服务端:

09cee218b4920b16a06681736c5ae531.jpeg

 

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月半木斤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值