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编程模式作为参照对象,躁动的心无法被湮灭。
Linux epoll 编程些许浅谈相关推荐
- linux系统pkl,(网摘)Linux新手必看:浅谈如何学习linux
地址:http://www.eimhe.com/bbs/viewthread.php?tid=53256&extra=page=1> Linux新手必看:浅谈如何教习linux 一.起步 ...
- Linux先发送条件变量,浅谈Linux条件变量的使用
Linux线程同步之间存在多种机制,条件变量是一种类似操作系统里提到的生产者-消费者算法的同步机制,允许线程以无竞争的方式等待特定条件的发生. 示例伪代码: void* Thread1(void){ ...
- Linux位置无关代码实现,浅谈位置无关代码
原标题:浅谈位置无关代码 引言 最近参与的一个项目涉及到了二进制重写相关的问题,也因此看了几篇相关工具的论文.与之前曾经一直想做的动态装载有不少重合,因此在此做一个整理. 本文主要整理了动态库装载地址 ...
- linux分区mapper,Linux系统/dev/mapper目录浅谈
Linux系统的一般的文件系统名称类似于/dev/sda1或/dev/hda1,但是今天在进行系统维护的时候,利用df -h 命令敲出了/dev/mapper/VolGroup-lv_root和/de ...
- Linux系统分区和挂载浅谈
好久没有写BLOG了,之前出差了2个月,都没怎么看书,也没有太多时间写.回来后一个月人也有点放松.现在开始还是得继续努力啊.不废话了,下面就介绍下Linux系统的分区和挂载 一 Linux的安装 Li ...
- linux的i o模型,浅谈Linux 网络 I/O 模型简介(图文)
1.介绍 Linux 的内核将所有外部设备都看做一个文件来操作(一切皆文件),对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符).而对一个sock ...
- linux路由信息自动丢失,浅谈用expect实现路由器自动备份数据
在网络界瞎混这么多年,对路由器的认识一直很渣:功能强大的网络设备.支持强大OSPF.BGP.MPLS ×××等网络路由协议,却很少关注对它的日常运维.直到后来接触到linux,发现linux强大的脚本 ...
- linux srelf 加壳代码,浅谈被加壳ELF文件的DUMP修复
前面的文章中,我已经介绍了如何调试被加壳的ELF,这里不在叙述,直接进入正题,以某加固为例,如何DUMP和修复被加壳的ELF,使其能调试加载 我们先来看看被加壳ELF的头和Program Header ...
- 【编程学习】浅谈哈希表及用C语言构建哈希表!
哈希表:通过key-value而直接进行访问的数据结构,不用经过关键值间的比较,从而省去了大量处理时间. 哈希函数:选择的最主要考虑因素--尽可能避免冲突的出现 构造哈希函数的原则是: ①函数本身便于 ...
最新文章
- (原創) 如何將CMOS所擷取的影像傳到PC端? (SOC) (DE2) (TRDB-DC2)
- xshell / xftp家庭/学校免费版官网下载地址
- cpu,内核和逻辑处理器的关系
- Azure SQL Database (23) Azure SQL Database Dynamic Data Masking动态数据掩码
- loj10200. 「一本通 6.2 练习 3」Goldbach's Conjecture
- SAP CRM和Cloud for Customer的UI界面皮肤更改
- git 在ssh情况下提交代码
- 开博第一篇,聊聊 最基本的 “==” 与 “===”区别
- Apache+Php+Mariadb+NFS+discuz
- 文件那些事儿之一(初稿)
- c#类库中使用Session
- 在Java中如何遍历Map对象
- Photoshop插件-黑白(二)-脚本开发-PS插件
- Windows11下安装MongoDB
- flash firefox linux,Linux下安装firefox的flash插件
- 如何阻止事件冒泡和浏览器的默认行为
- ucenter php7.0版,UCenter1.5.0UCenter Home1.5Discuz! 7.0 集成安装包
- 在文章中主标题和副标题的格式问题
- 苹果发布会说明了什么?
- Python 命令行cmd指定颜色设置
热门文章
- 《SQL 入门教程》第01篇 SQL 简介
- Nexus 5刷机无限重启问题解决
- KOOCAN非正常影视排行榜之遗忘的优秀中国动画
- bzoj 2125: 最短路 CH6402 Freda的传呼机
- 2021年电工(初级)考试试卷及电工(初级)模拟试题
- 应用负载均衡之LVS(五):lvs和nginx的wrr加权调度算法规律分析
- oracle纯SQL更新插入clob类型字段
- 反激开关电源MOS温升(损耗)解决措施
- overleaf 推荐
- Python使用列表完成程序的编写:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到m报数),凡是报到m的人退出圈子,问最后留下的是原来第几号的人。