epoll的一些需要注意的地方

epoll注册网络事件的流程

1.初始化epoll。epoll内部是红黑树和就绪队列(双向链表),所有被注册的fd都是红黑树的一个结点,当监听的事件发生时,会触发回调,这时该节点会被加入到队列中等待处理。

2.将监听socket加入epoll,注册读事件(不应该注册写事件)。使用listen实际上是维护了一个全连接队列,每次accept从这个全连接队列中取出一个连接即可,这里要注意如果全连接队列已满会拒绝客户端发起的连接。

3.新到来的连接加入epoll注册事件,监听其读事件(写事件在需要写入时才进行注册,在LT模式下写入结束的时候需要进行删除注册)。

为什么要使用非阻塞io

1.非阻塞io可以让主线程做其他事情。

2.在触发可读事件时,可能读缓冲区中并没有数据(阅读手册发现可能是因为校验和导致读事件被出发,但此时读缓冲区无数据)。这时如果使用阻塞io会导致一直阻塞。使用非阻塞io可以通过获取epoll事件类型来判断当前如何处理。

epoll的一些事件的注意事项

EPOLLRDHUP->读端关闭。收到这个事件可以选择关闭读端。

EPOLLHUP->读写端同时关闭。需要关闭fd。

EPOLLIN->可读事件,需要调用read读缓冲区,这时如果读失败(返回值<0),需要判断errno,如果errno==EINTR,也就是被信号中断,那么需要继续读。如果errno==EWOULDBLOCK,则说明读缓冲区为空(对应上面的2.),这时直接忽略这次事件即可。

EPOLLOUT->可写事件,这时需要写缓冲区。如果写成功,这时需要在事件中删除写事件的注册,因为如果不删除,在LT模式下会一直触发可写事件,而实际上需要写的数据已经写完。如果写失败,则同样判断errno。如果是EWOULDBLOCK,说明写缓存已满,这时需要继续写(如果是ET模式下则需要再次注册写事件,在可写的情况下继续尝试写入数据)。

单reactor下的一般步骤

1.写事件是可以多线程操作的,因为线程在使用锁拿到对应的缓冲之后,只需要在一次写完数据的情况下再返回即可,不会出现多个线程同时写的情况。

2.读事件需要在主线程操作,因为客户端发过来的数据可能分多个包,所以可能出现多个线程读同一个socket的一次发送数据但是不同分包的情况。

多reactor(one eventloop per thread)

使用1个reactor来监听其他reactor,根据监听事件类型(或者其他方案)的不同来将连接派发到不同的reactor中,这些reactor循环使用epoll处理相应的事件。

多reactor是否一定更好? 不一定,当临界资源访问频繁的时候,多reactor方案会出现大量锁的请求和释放导致的开销,从而导致性能下降。而在业务隔离的情况下(多个reactor之间相对独立),这种情况性能更优。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值