用户态协议中之epoll的实现

1、在网络编程的时候,有以下这些接口,

socket 、listen、 bind、 accept、recv、 send、 close、connect ````
请问有哪些接口,被调用的时候,会给对端发送一个数据呢?

send、connect、close

2、 epoll 需要检测哪些地方?

1)accept队列有了节点,即三次握手成功, 就会回调epoll
2)客户端发送数据到tcp协议栈的时候,且返回了ACK给客户端的时候,回调epoll
3)tcp协议栈调用了send函数, 给客户端发送消息之后 ,tcp协议栈收到了来自客户端的确认。 tcp协议栈把send_buf的空间里面的客户端已经确认收到的消息 对应的空间清空, 回调epoll。
4)客户端调用了close函数,回调了epoll

在这里插入图片描述
在这里epoll只关心哪个fd,status 状态和 epoll_fd(红黑树的代号)。

3、在用户态协议栈里面,为啥自己要实现一个epoll呢?

因为内核epoll是内核协议栈回调的。
既然把写了用户态协议栈TCP/IP的实现, 那么写一个用户态协议栈实现一个epoll。

4、epoll 底层的数据结构

在这里插入图片描述
使用了红黑树和就绪链表

就绪链表中的结点和红黑树的结点共用同一个节点。
红黑树里存储的是所有需要监控的fd,就绪队列里面存储的是所有待处理的fd.
红黑树里的小结点的内容包含了fd和event.

5、epoll 的接口实现

epoll_create(1);
–创建红黑树中的参数最早的时候是要创建这个长度的就绪队列有多长,代表一次最多检测多少个,之后把这个队列变成链式存储了,这个长度自然也就没有必要了.也就是说之前epoll中对应的就绪队列是顺序存储的队列,现在的就绪队列改成是链式存储的队列了。
为了兼容之前的版本,我们现在也加上了这个参数,哪个版本改的呢?应该是3.0版本以后改的,可以查实一下.

经查实,这个说法是错误的,内核在2.6.9版本中更改了eventpoll的存储结构,将其由原来的的hash
表存储改成现在的红黑树的存储,原来的那个size的存储是哈希表的长度.

epoll_ctl(epfd,op,fd,ev);
–增删改查红黑树上的结点

epoll_wait(epfd,events,length,time)
循环loop,把就绪队列里面的数据copy出来(select是拷贝就
绪的).
time的作用是预防就绪队列为空,等待time时间不为空.
0 —不阻塞
-1—一直阻塞

就绪队列是怎么管理的?如何进行增删改查的?
通过回调函数将对绪队列中的结点做相关操作,epoll_wait则去将队列里面的结点拷贝到events参数中,

回调和epoll是两个流程,回调是协议栈实现的,回调函数操作的就绪队列.

5、LT 与 ET如何实现?

et(边沿触发)模式下:
触发完一次后,设置一个flag,即使recvbuf不为空,也不会被触发;

lt(水平触发)模式下:
触发完一次后,如果recvbuf不为空,就会一直触发;

et和lt是通过回调函数次数实现的:
if(触发过一次)
{
if(buf不为空 && lt模式 )
{
继续触发;
}
}

LT 如何做到一直回调?在这里插入图片描述
LT模式下,
有另外一个线程,while(1), 将有数据的buffer的io,放到就绪队列中去。

当send的时候,
et模式下,如果sendbuf中有剩余空间只触发一次,即使后面有剩余空间,也不会触发.
lt模式下,如果sendbuf中有剩余空间,就会一直触发.

epoll 对文件的描述符的操作有两种模式 : LT(Level Trigger, 电平触发)模式 和 ET(Edge Trigger ,边沿触发)模式。

LT模式是默认的工作模式,这个模式下epoll相当于一个效率较高的poll。当往epoll中内核事件表中注册EPOLLET事件时,epoll将以ET模式来操作该文件描述符。ET是epoll的高效模式。

对于采用LT工作的文件描述符,当epolll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件。这样当应用程序下次调用epoll_wait时,epolll_wait还会再次向应用程序通知此事件,直到有该事件被处理。而对于采用ET模式的文件描述符,当epoll_wait检测当其上有事件发生时并将此事件通知应用程序后,应用程序必须立即处理该事件,因为后序的epolll_wait调用不再讲此事件通知应用程序,可见,ET模式在很大程度上降底了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。

6、epoll有哪些地方需要加锁

1、rbtree —》1、 对红黑树进行加锁
2、就绪队列 queue —》 spinlock
3、就绪队列为空的,需要 条件变量 还有单独配合了一个mutex

7 、啥时候用spinlock,啥时候用mutex?

spinlock 针对于等待时间很少,操作很少
mutex 用于操作比较多的 加锁
比线程切换的指令时间多的,用mutex.
比线程切换的指令时间少的,用spinlock加锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值