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

Linux—I/O复用---select、poll、epoll

目录

1. select

2. poll

3. epoll

4、数据复制情况分析

(1)select 和 poll

(2)epoll

5、代码示例: 

(1)select 函数的简单 TCP 服务器,用于处理多个客户端的连接和数据收发代码:

代码功能概述

代码结构分析

1. 函数定义

2. main 函数

(2)poll实现代码:

(3)epoll代码示例:

不理解的代码: 

epoll_ctl 函数概述

函数原型:

参数说明

工作模式(面试问区别): 

水平触发(Level Triggered,LT)

定义

特点

示例场景

边缘触发(Edge Triggered,ET)

定义

特点

示例场景


 (1)I/O复用是什么?

I/O 复用是一种同步 I/O 模型,它允许应用程序在多个 I/O 事件(如读、写事件)上进行监听,并在这些事件发生时得到通知,从而能够高效地处理多个 I/O 操作,而无需为每个 I/O 操作创建一个单独的线程或进程。

有数据的优先处理。 

Linux中如何处理I/O服用:

select、poll、epoll 

  • select 和 poll 是比较传统的 I/O 复用机制,具有较好的跨平台性,但在处理大量文件描述符时性能较差。
  • epoll 是 Linux 特有的高效 I/O 复用机制,适用于处理大量并发连接的场景,性能优于 select 和 poll

1. select

  • 原理select 函数会监视多个文件描述符的集合,程序会将需要监视的文件描述符添加到对应的集合(读集合、写集合、异常集合)中,然后调用 select 函数进行阻塞等待。当集合中的某个文件描述符上有对应的事件发生(如可读、可写、异常),select 函数会返回,同时修改集合以指示哪些文件描述符上有事件发生。
  • 优点:具有良好的跨平台性,几乎所有的类 Unix 系统都支持。
  • 缺点
    • 支持的文件描述符数量有限,通常默认最大为 1024。
    • 每次调用 select 时都需要将文件描述符集合从用户空间复制到内核空间,开销较大。
    • 需要遍历整个文件描述符集合来确定哪些文件描述符上有事件发生,时间复杂度为 O(n)

2. poll

  • 原理poll 函数与 select 类似,也是用于监视多个文件描述符的事件。它使用一个 pollfd 结构体数组来指定要监视的文件描述符和对应的事件,然后调用 poll 函数进行阻塞等待。当有事件发生时,poll 函数会返回,并在 pollfd 结构体中标记哪些文件描述符上有事件发生。
  • 优点
    • 没有文件描述符数量的限制。
    • 不需要像 select 那样每次调用都重新设置文件描述符集合,使用起来相对方便。
  • 缺点
    • 仍然需要将 pollfd 结构体数组从用户空间复制到内核空间,有一定的开销。
    • 同样需要遍历 pollfd 结构体数组来确定哪些文件描述符上有事件发生,时间复杂度为 O(n)

3. epoll

  • 原理epoll 是 Linux 特有的 I/O 复用机制,它通过 epoll_create 创建一个 epoll 实例,然后使用 epoll_ctl 函数向该实例中添加、修改或删除要监视的文件描述符和对应的事件。最后,使用 epoll_wait 函数进行阻塞等待,当有事件发生时,epoll_wait 函数会返回,并将有事件发生的文件描述符信息存放在一个数组中。
  • 优点
    • 采用事件驱动机制,只返回有事件发生的文件描述符,避免了遍历整个文件描述符集合,时间复杂度为 O(1)
    • 内核和用户空间之间的数据传输采用了内存映射的方式,减少了数据复制的开销。
    • 支持水平触发(LT)和边缘触发(ET)两种模式,边缘触发模式可以进一步提高效率。
  • 缺点
    • 只在 Linux 系统上可用,不具备跨平台性。

poll和select 实现都是以轮询的方式,时间复杂度是O(n);

epoll :内核实现以 注册回调函数实现,时间复杂度O(1); 

epoll_create : 创建内核事件表-----收集描述符------本质是红黑树

epoll_ctl:向内核事件表中添加、移除、修改描述符(加、删、改红黑树节点)

epoll_wait:获取就绪描述符-------从就绪队列中获取

epoll:相当于直接告诉程序取谁的数据,谁的数据就绪,select、poll要进行遍历,看谁的事件就绪了。

epoll:存放描述符的数据结构定义在内核空间,描述符从用户空间往内核空间只需要copy一次,而select、poll,是每一轮循环都要把描述符从用户空间往内核空间copy一次。

4、数据复制情况分析

(1)select 和 poll
  • 工作原理:在使用 select 或 poll 时,每次调用 select 或 poll 函数时,都需要将需要监听的文件描述符集合从用户空间复制到内核空间。这是因为 select 和 poll 函数是通过将文件描述符集合传递给内核,让内核去检查这些描述符上的事件状态。
  • 复制次数:由于每次调用 select 或 poll 函数都需要传递文件描述符集合,因此在每一轮循环中,都需要将描述符从用户空间复制到内核空间。这种频繁的数据复制会带来一定的性能开销,尤其是当需要监听的文件描述符数量较多时,性能问题会更加明显。
(2)epoll
  • 工作原理epoll 使用 epoll_ctl 函数来管理文件描述符,该函数会将文件描述符添加到内核中的红黑树中。红黑树是一种自平衡的二叉搜索树,用于高效地存储和查找文件描述符。一旦文件描述符被添加到红黑树中,就不需要再次复制到内核空间。当有事件发生时,内核会将就绪的文件描述符添加到就绪队列中,应用程序通过 epoll_wait 函数从就绪队列中获取就绪的文件描述符。
  • 复制次数epoll 只需要在使用 epoll_ctl 函数添加文件描述符时,将描述符从用户空间复制到内核空间一次。后续的 epoll_wait 函数调用不需要再次复制描述符,因为内核已经在红黑树中存储了这些描述符。这种设计减少了数据复制的次数,提高了性能。

5、代码示例: 

(1)select 函数的简单 TCP 服务器,用于处理多个客户端的连接和数据收发代码:

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<time.h>
#include<sys/select.h>#define MAXFD 10
int socket_init();void fds_init(int fds[])
{for(int i= 0; i < MAXFD ;i++){fds[i] = -1; //-1 reset为空}
}void fds_add(int fds[],int fd)
{
http://www.xdnf.cn/news/27091.html

相关文章:

  • 学习笔记十八——Rust 封装
  • mysql8.0.17以下驱动导致mybatis blob映射String乱码问题分析与解决
  • 实现AWS Lambda函数安全地请求企业内部API返回数据
  • 嵌入式单片机开发 - 嵌入式系统中 Flash(闪存)与 RAM(随机存储器)
  • 《JVM考古现场(二十三):归零者·重启奇点的终极奥义》
  • 【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化 - 2025-04-19详解 - 3-5年Java开发必备知识
  • JVM 系列:JVM 内存结构深度解析
  • 基础数学知识-线性代数
  • 蓝桥杯之递归二
  • 洛谷题目:P8624 [蓝桥杯 2015 省 AB] 垒骰子 题解 (本题简)
  • 纯FPGA实现AD9361控制的思路和实现 UART实现AXI_MASTER
  • 实现Azure Synapse Analytics安全地请求企业内部API返回数据
  • @EnableAsync+@Async源码学习笔记之二
  • @EnableAsync+@Async源码学习笔记之三
  • 系统思考:危机中的转型机遇
  • STM32单片机入门学习——第43节: [12-3] 读写备份寄存器实时时钟
  • STM32 外部中断EXTI
  • 爬虫入门与requests库的使用——python爬虫
  • XCVU13P-2FHGA2104I Xilinx Virtex UltraScale+ FPGA
  • 额外篇 非递归之美:归并排序与快速排序的创新实现
  • 解决 IntelliJ IDEA 项目启动时端口冲突问题
  • Linux网络编程——基于ET模式下的Reactor
  • 使用 Vite 快速搭建现代化 React 开发环境
  • 考公:数字推理
  • 新能源汽车动力电池热管理方案全解析:开启电车续航与安全的密码
  • 『Linux_网络』 第二章 UDP_Socket编程
  • 可发1区的超级创新思路(python 、MATLAB实现):基于多尺度注意力TCN-KAN与小波变换的时间序列预测模型
  • webpack 中 chunks详解
  • MATLAB 控制系统设计与仿真 - 38
  • C++问题,忘记为类添加拷贝构造函数和赋值运算符重载