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编程模式作为参照对象,躁动的心无法被湮灭。

Linux epoll 编程些许浅谈相关推荐

  1. linux系统pkl,(网摘)Linux新手必看:浅谈如何学习linux

    地址:http://www.eimhe.com/bbs/viewthread.php?tid=53256&extra=page=1> Linux新手必看:浅谈如何教习linux 一.起步 ...

  2. Linux先发送条件变量,浅谈Linux条件变量的使用

    Linux线程同步之间存在多种机制,条件变量是一种类似操作系统里提到的生产者-消费者算法的同步机制,允许线程以无竞争的方式等待特定条件的发生. 示例伪代码: void* Thread1(void){ ...

  3. Linux位置无关代码实现,浅谈位置无关代码

    原标题:浅谈位置无关代码 引言 最近参与的一个项目涉及到了二进制重写相关的问题,也因此看了几篇相关工具的论文.与之前曾经一直想做的动态装载有不少重合,因此在此做一个整理. 本文主要整理了动态库装载地址 ...

  4. linux分区mapper,Linux系统/dev/mapper目录浅谈

    Linux系统的一般的文件系统名称类似于/dev/sda1或/dev/hda1,但是今天在进行系统维护的时候,利用df -h 命令敲出了/dev/mapper/VolGroup-lv_root和/de ...

  5. Linux系统分区和挂载浅谈

    好久没有写BLOG了,之前出差了2个月,都没怎么看书,也没有太多时间写.回来后一个月人也有点放松.现在开始还是得继续努力啊.不废话了,下面就介绍下Linux系统的分区和挂载 一 Linux的安装 Li ...

  6. linux的i o模型,浅谈Linux 网络 I/O 模型简介(图文)

    1.介绍 Linux 的内核将所有外部设备都看做一个文件来操作(一切皆文件),对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符).而对一个sock ...

  7. linux路由信息自动丢失,浅谈用expect实现路由器自动备份数据

    在网络界瞎混这么多年,对路由器的认识一直很渣:功能强大的网络设备.支持强大OSPF.BGP.MPLS ×××等网络路由协议,却很少关注对它的日常运维.直到后来接触到linux,发现linux强大的脚本 ...

  8. linux srelf 加壳代码,浅谈被加壳ELF文件的DUMP修复

    前面的文章中,我已经介绍了如何调试被加壳的ELF,这里不在叙述,直接进入正题,以某加固为例,如何DUMP和修复被加壳的ELF,使其能调试加载 我们先来看看被加壳ELF的头和Program Header ...

  9. 【编程学习】浅谈哈希表及用C语言构建哈希表!

    哈希表:通过key-value而直接进行访问的数据结构,不用经过关键值间的比较,从而省去了大量处理时间. 哈希函数:选择的最主要考虑因素--尽可能避免冲突的出现 构造哈希函数的原则是: ①函数本身便于 ...

最新文章

  1. (原創) 如何將CMOS所擷取的影像傳到PC端? (SOC) (DE2) (TRDB-DC2)
  2. xshell / xftp家庭/学校免费版官网下载地址
  3. cpu,内核和逻辑处理器的关系
  4. Azure SQL Database (23) Azure SQL Database Dynamic Data Masking动态数据掩码
  5. loj10200. 「一本通 6.2 练习 3」Goldbach's Conjecture
  6. SAP CRM和Cloud for Customer的UI界面皮肤更改
  7. git 在ssh情况下提交代码
  8. 开博第一篇,聊聊 最基本的 “==” 与 “===”区别
  9. Apache+Php+Mariadb+NFS+discuz
  10. 文件那些事儿之一(初稿)
  11. c#类库中使用Session
  12. 在Java中如何遍历Map对象
  13. Photoshop插件-黑白(二)-脚本开发-PS插件
  14. Windows11下安装MongoDB
  15. flash firefox linux,Linux下安装firefox的flash插件
  16. 如何阻止事件冒泡和浏览器的默认行为
  17. ucenter php7.0版,UCenter1.5.0UCenter Home1.5Discuz! 7.0 集成安装包
  18. 在文章中主标题和副标题的格式问题
  19. 苹果发布会说明了什么?
  20. Python 命令行cmd指定颜色设置

热门文章

  1. 《SQL 入门教程》第01篇 SQL 简介
  2. Nexus 5刷机无限重启问题解决
  3. KOOCAN非正常影视排行榜之遗忘的优秀中国动画
  4. bzoj 2125: 最短路 CH6402 Freda的传呼机
  5. 2021年电工(初级)考试试卷及电工(初级)模拟试题
  6. 应用负载均衡之LVS(五):lvs和nginx的wrr加权调度算法规律分析
  7. oracle纯SQL更新插入clob类型字段
  8. 反激开关电源MOS温升(损耗)解决措施
  9. overleaf 推荐
  10. Python使用列表完成程序的编写:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到m报数),凡是报到m的人退出圈子,问最后留下的是原来第几号的人。