I/O 多路复用:`select`、`poll`、`epoll` 和 `kqueue` 的区别与示例

news2024/12/24 7:29:32

I/O 多路复用是指在一个线程内同时监控多个文件描述符(File Descriptor, FD),以便高效地处理多个 I/O 事件。在 UNIX/Linux 和 BSD 系统中,selectpollepollkqueue 都是实现 I/O 多路复用的系统调用。它们各有特点,适合不同的应用场景。本文将详细介绍它们的用法、优缺点,并附上相应的代码示例。
在这里插入图片描述

1. select

概述

select 是最早的 I/O 多路复用系统调用之一,广泛支持于各类操作系统中。它允许程序同时监视多个文件描述符,但有最大数量的限制(通常是 1024 个文件描述符)。

优点

  • 简单,适用性广泛。
  • 支持几乎所有 UNIX 类操作系统。

缺点

  • 文件描述符数量有限制。
  • 每次调用都需要重新设置文件描述符集合,效率较低。

使用示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <unistd.h>

int main() {
    fd_set readfds;
    struct timeval timeout;
    int ret;

    // 初始化文件描述符集合
    FD_ZERO(&readfds);
    FD_SET(STDIN_FILENO, &readfds);

    // 设置超时时间
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    printf("Waiting for input, timeout in 5 seconds...\n");
    // 调用 select 函数,监控文件描述符
    ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout);

    if (ret == -1) {
        perror("select");
        exit(EXIT_FAILURE);
    } else if (ret == 0) {
        printf("Timeout occurred! No data after 5 seconds.\n");
    } else {
        if (FD_ISSET(STDIN_FILENO, &readfds)) {
            char buffer[1024];
            read(STDIN_FILENO, buffer, sizeof(buffer));
            printf("Data read: %s\n", buffer);
        }
    }

    return 0;
}

解释

在上述代码中,我们使用 select 函数监听标准输入 (STDIN_FILENO) 的可读性。如果用户在 5 秒内没有输入,程序会超时并退出。

2. poll

概述

poll 作为 select 的改进版本,消除了文件描述符数量的限制。它通过一个 pollfd 数组来管理多个文件描述符,解决了 select 的一些局限性。

优点

  • 没有文件描述符数量限制。
  • API 比较简洁,避免了 select 需要重置文件描述符集合的问题。

缺点

  • select 一样,每次调用仍需遍历整个文件描述符集合。

使用示例

#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <unistd.h>

int main() {
    struct pollfd fds[1];
    int ret;

    // 设置文件描述符和事件
    fds[0].fd = STDIN_FILENO;
    fds[0].events = POLLIN;

    printf("Waiting for input, timeout in 5 seconds...\n");
    // 调用 poll 函数,设置 5 秒超时
    ret = poll(fds, 1, 5000);

    if (ret == -1) {
        perror("poll");
        exit(EXIT_FAILURE);
    } else if (ret == 0) {
        printf("Timeout occurred! No data after 5 seconds.\n");
    } else {
        if (fds[0].revents & POLLIN) {
            char buffer[1024];
            read(STDIN_FILENO, buffer, sizeof(buffer));
            printf("Data read: %s\n", buffer);
        }
    }

    return 0;
}

解释

这里的代码使用 poll 来监控标准输入的可读性。与 select 类似,它设置了一个 5 秒的超时时间,但使用 poll 可以处理更多的文件描述符。

3. epoll

概述

epoll 是 Linux 特有的系统调用,它专门为处理大量文件描述符而设计,性能远优于 selectpollepoll 使用一个事件通知机制,避免了每次调用时遍历整个文件描述符集合。

优点

  • 高效,适合处理大量文件描述符。
  • 不需要每次遍历整个文件描述符集合。

缺点

  • 仅支持 Linux 系统。

使用示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>

int main() {
    int epfd = epoll_create1(0);
    struct epoll_event event, events[1];
    int ret;

    if (epfd == -1) {
        perror("epoll_create1");
        exit(EXIT_FAILURE);
    }

    // 设置事件
    event.events = EPOLLIN;
    event.data.fd = STDIN_FILENO;

    if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
        perror("epoll_ctl");
        exit(EXIT_FAILURE);
    }

    printf("Waiting for input, timeout in 5 seconds...\n");
    // 调用 epoll_wait,等待事件
    ret = epoll_wait(epfd, events, 1, 5000);

    if (ret == -1) {
        perror("epoll_wait");
        exit(EXIT_FAILURE);
    } else if (ret == 0) {
        printf("Timeout occurred! No data after 5 seconds.\n");
    } else {
        if (events[0].data.fd == STDIN_FILENO) {
            char buffer[1024];
            read(STDIN_FILENO, buffer, sizeof(buffer));
            printf("Data read: %s\n", buffer);
        }
    }

    close(epfd);
    return 0;
}

解释

在这个示例中,我们使用 epoll 来监控标准输入。epoll_create1 创建了一个 epoll 实例,随后通过 epoll_ctl 添加文件描述符。epoll_wait 用来等待事件发生,效率远高于 selectpoll

4. kqueue

概述

kqueue 是 BSD 系统(包括 macOS)中的高效 I/O 事件通知机制。与 epoll 类似,kqueue 使用事件通知的机制来避免每次遍历整个文件描述符集合。

优点

  • 高效,适合处理大量 I/O 事件。
  • 支持 BSD 系统。

缺点

  • 仅支持 BSD 系统(包括 macOS)。

使用示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/event.h>
#include <sys/time.h>
#include <unistd.h>

int main() {
    int kq = kqueue();
    struct kevent change, event;
    int ret;

    if (kq == -1) {
        perror("kqueue");
        exit(EXIT_FAILURE);
    }

    // 设置事件
    EV_SET(&change, STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);

    printf("Waiting for input, timeout in 5 seconds...\n");
    // 调用 kevent,设置 5 秒超时
    struct timespec timeout = {5, 0};
    ret = kevent(kq, &change, 1, &event, 1, &timeout);

    if (ret == -1) {
        perror("kevent");
        exit(EXIT_FAILURE);
    } else if (ret == 0) {
        printf("Timeout occurred! No data after 5 seconds.\n");
    } else {
        if (event.ident == STDIN_FILENO) {
            char buffer[1024];
            read(STDIN_FILENO, buffer, sizeof(buffer));
            printf("Data read: %s\n", buffer);
        }
    }

    close(kq);
    return 0;
}

解释

在 BSD 系统中,kqueue 提供了一种高效的 I/O 事件通知机制。该代码监控标准输入,超时时间为 5 秒,使用 kevent 等待事件发生。

5. 总结

特性selectpollepollkqueue
支持的平台Unix/Linux/BSDUnix/Linux/BSDLinuxBSD/macOS
文件描述符限制有限制(1024)无限制无限制无限制
效率较低较低
扩展性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2136062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MYMPay码支付开源版系统源码

MYMPay码支付开源版系统源码 前言安装环境&#xff1a;首页图片用户中心管理后台 部分源码领取源码下期更新 前言 最新版MYMPay码支付开源版系统源码_个人免签支付_聚合支付系统 安装环境&#xff1a; PHP&#xff1a;7.0-8.2 (推荐使用7.4)需要安装Xload 扩展MySQL&#xf…

Linux基础入门篇

一.Linux概述 我们一般所说的Liunx表示的是Linux的内核部分&#xff0c;Liunx 发行版是在其内核的基础上进行了对其他软件的集成&#xff0c;更加方便了用户的使用 Liunx的结构&#xff1a; 目前市场上使用的Linux大多为CenterOS,一些微型的开发中会使用到Ubuntu,两者在一些指…

【刷题】Day4--密码检查

Hi&#xff01; 今日刷题&#xff0c;小白一枚&#xff0c;欢迎指导 ~ 【链接】 密码检查_牛客题霸_牛客网 【思路】 依次根据规则判断密码是否合格。while里嵌套个for循环&#xff0c;来进行密码的多组输入&#xff0c;for循环进行一次代表判断一个密码串&#xff1b;规则…

STM32+ESP01连接到机智云

机智云,全球领先的智能硬件软件自助开发及物联网(iot)云服务平台。机智云平台为开发者提供了自助式智能硬件开发工具与开放的云端服务。通过傻瓜化的自助工具、完善的SDK与API服务能力最大限度降低了物联网硬件开发的技术门槛&#xff0c;降低开发者的研发成本&#xff0c;提升…

添加选择登录ssh终端

吼吼,这次成了一个小的瑞士军刀了 … …

2.Jmeter安装配置,核心目录详情,组件和作用域

一、Jmeter安装配置以及核心目录详情 Jmeter基于java语言来开发&#xff0c;java需要jdk环境。 1.安装jdk并且配置jdk的环境变量。 2.jmeter只需要解压就可以使用了。 3.在D:\apache-jmeter-5.5\bin目录下双击jmeter.bat文件就可以启动使用了 backups&#xff1a;自动备份的目录…

OpenHarmony(鸿蒙南向开发)——轻量系统STM32F407芯片移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量和小型系统三方库移植指南…

JAVA毕业设计170—基于Java+Springboot+vue3+小程序的房屋租赁小程序系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue3小程序的房屋租赁小程序系统(源代码数据库)170 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为用户、房东、管理员三种角色 1、用户&am…

华为云分布式缓存服务DCS 8月新特性发布

分布式缓存服务&#xff08;Distributed Cache Service&#xff0c;简称DCS&#xff09;是华为云提供的一款兼容Redis的高速内存数据处理引擎&#xff0c;为您提供即开即用、安全可靠、弹性扩容、便捷管理的在线分布式缓存能力&#xff0c;满足用户高并发及数据快速访问的业务诉…

[PICO VR眼镜]眼动追踪串流Unity开发与使用方法,眼动追踪打包报错问题解决(Eye Tracking)

前言 最近在做一个工作需要用到PICO4 Enterprise VR头盔里的眼动追踪功能&#xff0c;但是遇到了如下问题&#xff1a; 在Unity里面没法串流调试眼动追踪功能&#xff0c;根本获取不到Device&#xff0c;只能将整个场景build成APK&#xff0c;安装到头盔里&#xff0c;才能在…

明星代言推广的6种优势,打造品牌巅峰!

在当今的商业社会中&#xff0c;品牌推广成为了企业发展不可或缺的一环。对于许多企业来说&#xff0c;明星代言已经成为了一种常见的推广策略。本文将介绍明星代言推广的六种优势&#xff0c;帮助企业了解并充分利用这一策略&#xff0c;从而打造品牌的巅峰&#xff01; 1. 塑…

java中SPI(服务提供者的接口)

java中SPI&#xff08;服务提供者的接口&#xff09; 一&#xff1a;什么是SPI二&#xff1a;java SPI示例1.SPI服务提供方2.SPI服务应用方开发者 三&#xff1a;JavaSPI 机制的核心-ServiceLoader 一&#xff1a;什么是SPI SPI&#xff1a;“服务提供者的接口”&#xff0c;是…

USART—串口数据包

1.HEX数据包定义 数据包的作用是把一个个单独的数据给打包起来&#xff0c;方便我们进行多字节的数据通信&#xff0c;在实际应用中&#xff0c;我们可能需要把多个字节打包为一个整体进行发送&#xff0c;比如说&#xff0c;我们有个陀螺仪传感器&#xff0c;需要用串口发送数…

git 你要如何打开这个文件

终端输入git命令都会弹出这个框 解决方案&#xff1a; 参考文章&#xff1a;在vscode终端上运行 npm 会询问 “你要如何打开这个文件“_安装 npm脚手架提示你要如何打开-CSDN博客 get-command git后删除对应文件 请注意不要删错了&#xff0c;正常get-command git后对应的是…

微型导轨加工环境需避免的隐患!

微型导轨是一种小巧精密的线性定位解决方案&#xff0c;其高速度、低噪音的特点使得它在现代制造业中扮演着越来越重要的角色。而微型导轨对于加工环境的要求主要体现在以下几个方面&#xff1a; 1、温度控制&#xff1a;加工环境需要保持在适宜的温度范围内&#xff0c;过高或…

【西电电装实习】5. 无人机模块及作用、上位机的操作

文章目录 前言一、硬件结构电源、电源电压测试电路晶振外围陀螺仪信号放大电路及天线空心杯&#xff08;电极&#xff09;驱动电路 软件设置整机装配PID 参数设置公式 参考文献 前言 西电电装实习&#xff0c;无人机原理图、上位机的调节方法 一、硬件结构 电源、电源电压测…

RabbitMQ 基础入门

文章内容是学习过程中的知识总结&#xff0c;如有纰漏&#xff0c;欢迎指正 文章目录 前言 1. 重要概念 1.1 Publisher 1.2 Message 1.3 Exchange 1.4 BindingKey 1.5 Routingkey 1.6 Queue 1.7 Consumer 1.8 Connection 1.9 Channel 1.10 Virtual Host 1.11Broker 2. RabbitMQ…

个人学习笔记7-5:动手学深度学习pytorch版-李沐

#人工智能# #深度学习# #语义分割# #计算机视觉# #神经网络# 计算机视觉 13.10 转置卷积 例如&#xff0c;卷积层和汇聚层&#xff0c;通常会减少下采样输入图像的空间维度&#xff08;高和宽&#xff09;。然而如果输入和输出图像的空间维度相同&#xff0c;在以像素级分类…

手机玩机常识____展讯芯片刷机平台ResearchDownload的一些基本常识与问题解决

展讯ResearchDownload工具 展讯芯片的刷机工具--ResearchDownload下载工具"是一款专为用户设计的高效、便捷的下载管理软件&#xff0c;它能够帮助用户快速、稳定地从互联网上获取各种文件。这款工具以其强大的功能和良好的用户体验&#xff0c;在众多展讯芯片下载工具中脱…

计算机网络30——Linux-gdb调试命令makefile

1、开始调试 编译时带-g为调试&#xff0c;带调试信息编译后的可执行文件更大 2、进入调试 使用gdb 可执行文件名——进入调试 失败版&#xff1a; 成功版&#xff1a; 3、l命令 l什么都不加——列出10行代码 l 行号——行号的行在中间&#xff0c;向上向下展示10行 4、st…