Linux epoll 编程些许浅谈

Linux 内核提供 EPOLL 的网络编程模型,它是一套 reactor 同步IO多路复用编程模型,即当某个或多个网络事件发生改变时操作系统会通知正在关注的 epoll_wait 的线程进行处理,但它其本身是存在技术上的缺点的,我讨厌直接适用 epoll,更喜欢适用 boost::asio 跨平台封装的 Proactor 异步IO多路复用模式的基础网络框架类库(FCL)。

先说明本人几年前琢磨捣鼓过 epoll,但现在已不会再用其API,但如何用某个API应该不能成为衡量技术人员对于某个技术理解的理由,仅仅会用没有意义,类似 epoll API 怎么用这种事情,随便一个中小学生看点教学视频/博客/教科书就会的事情,不是一个值得骄傲的事情。

原因为:

当我们采用 epoll ET(边缘事件触发)模式时,操作系统内核只会通知应用线程一次,但人们并不知道,应当读入多少字节可以读入系统当前整个分段缓冲,那么也就是说会存在以下两个情况

recv 从操作系统内核 socket/tcp 协议栈分段缓冲区读入 tcp_segment 数据到应用程序内存缓冲区,如果应用层读入的缓冲区大小很大,大过当前操作系统内核缓存的 tcp_segment 字节数的情况下,那么IO的读入不会出现任何问题,反之没有读入所有的字节,而 epoll ET 边缘事件触发模式为:当 epoll 已触发过一次事件后,开发人员必须处理完本次事件的所需要全部 Actions,否则边缘触发事件模式下的 epoll 不会通知下个 Event Trigger。

当我们采用 epoll LT(水平事件触发)模式时,这个看上去就稍微正常了一点,当 epoll 关注的 FD(文件描述符句柄)可读状态未被重置(recv/read 未读完全部内核缓冲的 tcp_segment)那么会一直触发事件,请求应用层处理相应IO事件。

似看上去 epoll 简直完美?两套IO异步处理通知模式,让人愉悦???

ET模式带来的优势仅仅只不过 “多个分片到达,TCP控制协议堆栈诱发 epoll 触发事件一次”,即相同事件不会在重复触发,那么在人们不知道某个TCP socket,当前内核已缓冲的 tcp_segment 大小的前提下,那么只有一个解决办法:

把TCP socket设置为NBIO(非阻塞IO),当边缘事件触发人们尝试循环一直recv,直到操作系统告诉人们错误代码:EAGIN(等待重试)时才表示当前事件 Action 所需要处理的行为已经完成。

如果人们要通过操作系统BSD风格API提供的内核接口来确定当前内核协议堆栈内该 tcp_socket 可以被 Available Size(可用大小)那么每次 recv 之前都至少需要一次内核函数调用。

ioctl(sockfd, FIONREAD, ....)  # Linux

ioctlsocket(socket, FIONREAD, ....) # Windows 

ERR:WSAEWOULDBLOCK ≈ EGAIN

上述两行代码分别为两个操作系统开发平台获取当前操作系统内核TCP协议堆栈已堆积的可读入数据量,当然如果测量 socket 可否写入,那么则是依赖于 select/poll 来测量,但每个 socket 可以一次性放入内核发送缓冲区的大小是不确定的,那么要确定就需要测量 “FIONWRITE” 的大小,否则人们应把 socket 置为NBIO非阻塞,不停的循环尝试 send/write,直到操作系统返回错误提示代码:“EAGIN”。

LT水平触发模式处理上面就会简单些许,因为ET边缘触发模式的处理效率并不意味着一定可以高过LT水平触发模式,只是理论上的ET边缘触发模式,应用层处理IO的吞吐量大于LT水平触发模式,但只是相对而言,我不喜欢绝对这个术语,哪有那么多的绝对,1+1都不一定等于2。

例:

ET/LT模式下的 tcp-socket 都采用NBIO非阻塞模式下,两者都采用循环 recv/read、send/write,那么ET边缘触发模式的效率优于LT水平触发模式(内核开销更低)

LT水平触发模式因为其特性会产生一些,奇奇怪怪的BUG,例:accept 函数发生死循环,发生的原因也是些许奇奇怪怪把,本可避免的无价值软件故障。

boost::asio::ip::tcp::acceptor::async_accept 一直被死循环调用(无错误)问题的处理。_liulilittle的博客-CSDN博客

从我个人的心声来说,本应该操作系统实现的事情,让开发人员去实现,实在是有些奇怪的,当有了其它操作系统提供的IO编程模式作为参照对象,躁动的心无法被湮灭。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值