首页 > 其他分享 >非阻塞sokcet和epoll

非阻塞sokcet和epoll

时间:2024-05-24 18:54:25浏览次数:28  
标签:调用 socket epoll 阻塞 应用程序 sokcet IO

在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的阻塞和非阻塞浅析】细看。

标签:调用,socket,epoll,阻塞,应用程序,sokcet,IO
From: https://blog.csdn.net/qq_20756957/article/details/139182261

相关文章

  • 【Muduo】三大核心之Poller、EPollPoller
    Poller在Muduo中,Poller负责基于IO多路复用机制进行IO事件监听和处理的组件,作为EPollPoller的基类,为后者提供了与PollPoller统一的IO复用接口,并且声明了一个关键的创建派生类的成员函数:staticPoller*newDefaultPoller(EventLoop*loop);此函数可以通过判断`::getenv("MUD......
  • 4/7一文讲透网络传输流程 epoll内核模型 reactor用户空间处理模型
    epoll是内核如何将由层层协议栈去除tcp头,根据四元组查socket文件,将sk_buffer放到socket接受队列的 reactor  五种IO模型,三种线程处理模型     回溯算法之全排列 将所有需要用到的数组包括路径数组状态数组都初始化好然后都放进dfs参数里面 这......
  • epoll_event
    epoll_event是Linux内核提供的一个数据结构,用于在epoll机制中表示事件。epoll是一种高效的I/O事件通知机制,通常用于处理大量并发连接。epoll_event结构体定义在<sys/epoll.h>头文件中,主要用于传递文件描述符及其相关的事件类型。epoll_event结构体的定义如下:struct......
  • QT使用串口通信点击主界面通信阻塞
    1.问题导入在使用QT进行串口上位机开发时遇到鼠标点击主界面导致串口接收数据阻塞,无法继续在QT控件中更新接收到的数据。2.解决办法使用多线程:将串口通信放入子线程中。`QSerialPort*UARTDevide;//串口UART*newUART;//串口类QThreadUARTThred;//串口线程newUART->mo......
  • IO多路复用:Select, Poll与Epoll
    IO多路复用:Select,Poll与Epoll参考:EPOLL原理详解(图文并茂)一、网络数据是如何被接收的网卡接收到网络数据将网络数据暂存到内存当中(DMA传输技术)网卡向CPU发起硬件中断CPU执行中断处理函数,将内存中的数据存储到socket文件描述符中,并唤醒相关进程Q1:如何知道要将网络数据......
  • 一个Java基于阻塞的定时消费内存队列
     @Getter@AllArgsConstructorpublicenumInsertQueueEnum{A(30000,10,TimeUnit.SECONDS,2,1000),;privatefinalintcapacity;//队列长度privatefinalinttime;//最长阻塞时间privatefinalTimeUnittimeUnit;//最长阻塞时间单位privatefi......
  • epoll、poll、select
    `epoll`、`select`和`poll`都是在Linux系统中用于实现I/O多路复用的机制,它们都能够实现在多个文件描述符上进行非阻塞的I/O操作,并在有I/O事件发生时通知应用程序。以下是它们的一些比较:1.**`select`**:-`select`是Unix系统最早的一种多路复用机制之一。-它......
  • openGauss 分析查询语句是否被阻塞
    分析查询语句是否被阻塞问题现象数据库系统运行时,在某些业务场景下,查询语句会被阻塞,导致语句运行时间过长。原因分析查询语句需要通过加锁来保护其要访问的数据对象。当要进行加锁时发现要访问的数据对象已经被其他会话加锁,则查询语句会被阻塞,等待其他会话完成操作并释放锁资......
  • 详解Redis持久化(持久化高危漏洞利用与多种对抗方案、RDB、AOF、同步手动持久化、异步
    谨防持久化+未授权访问漏洞入侵服务器CVE编号找不到,CNVD有一个:CNVD-2015-07557(国家信息安全漏洞共享平台漏洞编号)。这是我之前写过的文章,漏洞成因、影响范围、POC与对抗方案有详解:谨防利用Redis未授权访问漏洞入侵服务器RDB(RedisDatabase、全量保存,默认方式)极简概括:通过符......
  • fastapi - 同步接口也不会有IO阻塞!
    之前一直以为FastAPI对于同步IO会发生服务阻塞,直到今天看到了这一块代码,原来同步的函数会开线程去处理fastapi/routing.pyasyncdefrun_endpoint_function(*,dependant:Dependant,values:Dict[str,Any],is_coroutine:bool)->Any:#Onlycalledbyget_re......