当前位置: 首页 > news >正文

非阻塞sokcet和epoll

在Muduo网络库中同时使用了非阻塞socket与epoll,在此简单梳理下。

非阻塞sokcet和epoll共同工作的过程主要涉及网络编程中的非阻塞I/O和事件驱动机制。下面将详细解释这两者如何协同工作:

非阻塞socket简介

  • 在传统的阻塞socket编程中,当调用如readwriteaccept等函数时,如果当前没有数据可读或没有空间可写,线程或进程会被挂起,等待数据到来或空间可用。这可能导致资源(如CPU时间)的浪费。
  • 非阻塞socket则不同,它允许socket调用立即返回,即使当前没有数据可读或没有空间可写。这意味着线程或进程不会被挂起,可以继续执行其他任务。
  • 非阻塞socket通过设置socket的选项(如使用fcntl函数设置O_NONBLOCK标志)来实现。

epoll简介

  • epoll是Linux内核提供的一种高效的事件通知机制,用于监控多个文件描述符(如socket)的状态变化。
  • 与传统的select/poll机制相比,epoll具有更高的效率和可扩展性。它使用一种称为“事件驱动”的方式工作,即当某个文件描述符的状态发生变化时,内核会主动通知应用程序。
  • epoll有两种触发模式:水平触发(Level Triggered, LT)和边缘触发(Edge Triggered, ET)。在LT模式下,只要文件描述符的状态未改变,应用程序每次调用epoll_wait都会收到通知;而在ET模式下,应用程序只会收到一次通知,需要在状态改变后主动读取或写入数据。

非阻塞socket与epoll共同工作过程

  • 当使用非阻塞socket编程时,为了避免线程或进程被挂起,通常会结合使用epoll来监控socket的状态变化。
  • 具体而言,应用程序首先会将socket设置为非阻塞模式,并将其注册到epoll的监控列表中。
  • 当socket的状态发生变化(如有数据可读或可写)时,内核会通过epoll通知应用程序。此时,应用程序可以调用相应的socket函数(如readwrite)来处理数据,而不用担心被挂起。
  • 由于socket处于非阻塞模式,因此这些函数会立即返回。如果当前没有数据可读或没有空间可写,函数会返回一个错误码(如-1),并设置相应的errno值(如EWOULDBLOCK)。应用程序可以根据这些错误码来判断是否需要继续等待数据或执行其他任务。
  • 通过这种方式,非阻塞socket与epoll共同实现了高效的网络编程模型,使得应用程序能够充分利用系统资源,提高程序的性能和响应速度。

 

此图是IO复用(IO multiplexing)模型图。epoll属于IO复用的一种。图中下方的read可以是阻塞IO,也可是本文讲的非阻塞IO。

需要注意的是,当使用非阻塞socket和epoll的ET模式结合进行编程时,需要特别注意数据的完整性和连接的稳定性。

例如,在读取数据时,可能需要循环调用read函数以确保读取到完整的数据包,在Muduo库中Buffer的readFd方法封装了readv系统调用,可以最多一次读取64kbyte的数据。在关闭连接时,也需要确保对方已经接收到了所有的数据并关闭了连接。这些都需要在应用程序中进行适当的处理。

非阻塞+epoll是异步IO吗

在这种情况下,虽然非阻塞socket和epoll允许应用程序在等待I/O操作完成时不被阻塞,但它们本身并不直接等同于异步I/O(Asynchronous I/O)。澄清一下这两个概念:

  1. 非阻塞I/O:非阻塞I/O意味着当应用程序尝试执行一个I/O操作时,如果操作不能立即完成(例如,没有数据可读或缓冲区已满),则调用会立即返回一个错误(通常是EWOULDBLOCK),而不是将调用线程挂起。这样,应用程序可以继续执行其他任务,稍后再次尝试该I/O操作。

  2. 异步I/O:异步I/O更进一步。它允许应用程序启动一个I/O操作,然后立即继续执行其他任务,而不必等待该操作完成。当I/O操作完成时,系统会通知应用程序(通常是通过一个回调函数或信号)。这样,应用程序可以真正并行地执行多个任务,而不仅仅是轮询I/O操作的状态。

就如Muduo库中,使用非阻塞socket和epoll实现的是基于事件驱动的反应式编程模型,而不是真正的异步I/O。应用程序需要定期调用epoll_wait来检查是否有任何已注册的文件描述符(如socket)的状态发生了变化。当检测到变化时,应用程序会执行相应的处理逻辑。

然而,有些系统调用(如Windows的IOCP或Linux的aio系列函数)提供了真正的异步I/O支持。应用程序可以提交一个I/O请求,并提供一个回调函数,当I/O操作完成时,系统会调用该回调函数。这样,应用程序可以完全避免轮询,从而实现更高的效率和更好的响应性。

相关概念也可移步另一篇博客【IO的阻塞和非阻塞浅析】细看。

相关文章:

  • 【pdb的使用方法】
  • AI预测福彩3D采取888=3策略+杀断组+杀和尾缩水测试5月24日预测第1弹
  • LoadBalancer
  • DockerK8s
  • 【深度学习】与【PyTorch实战】
  • 大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例
  • Kubernetes常用命令
  • 【C++风云录】领略嵌入式世界:嵌入式系统与实时操作系统
  • Ai指令-公众号内训课:学会ai指令+公众号的底层逻辑(7节课)
  • Python流感常微分方程房室数学模型
  • JVM运行时内存:垃圾回收器(Serial ParNew Parallel )详解
  • React里面useMemo和useCallBack的区别
  • Hsql每日一题 | day02
  • 【simple-admin】simple-admin-core 首次服务启动 如何配置mysql数据库表 | 如何docker启动core
  • Linux安装Mysql
  • (三)从jvm层面了解线程的启动和停止
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 2017 前端面试准备 - 收藏集 - 掘金
  • DataBase in Android
  • Java 网络编程(2):UDP 的使用
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • Protobuf3语言指南
  • scrapy学习之路4(itemloder的使用)
  • vue 配置sass、scss全局变量
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 订阅Forge Viewer所有的事件
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 前端面试总结(at, md)
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 移动端 h5开发相关内容总结(三)
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (160)时序收敛--->(10)时序收敛十
  • (办公)springboot配置aop处理请求.
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)80c52学习之旅-起始篇
  • (一)插入排序
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)ORM
  • (转)创业的注意事项
  • .net core + vue 搭建前后端分离的框架
  • .net core 6 redis操作类
  • .Net Memory Profiler的使用举例
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • [ MSF使用实例 ] 利用永恒之蓝(MS17-010)漏洞导致windows靶机蓝屏并获取靶机权限
  • [100天算法】-不同路径 III(day 73)