I/O多路复用之poll

【Linux】多路转接 -- poll函数 poll函数原型如下: 阅读详情

由于poll是对select的改进,poll的功能和select的功能一样,只不过是参数稍微不同,poll的底层原理也和select差不多。
对多路复用select()不太熟悉的可以参考这篇博文:I/O多路复用之select

我们首先回忆一下 select接口 :

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

select需要我们指定文件描述符的最大值,然后取[0,nfds)这个范围内的值查看是在集合readfds,writefds或execptfds中,也就是说这个范围内存在一些不是我们感兴趣的文件描述符,cpu做了一些无用功,poll对它进行了改进,下面就看看poll是怎么做的。


poll函数原型:

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);


函数参数:

1. fds参数:

fds参数是一个pollfd结构类型的数组,它指定所有我们感兴趣的文件描述符上发生的可读,可写和异常等事件。

pollfd结构体定义如下:

struct pollfd {

  int fd; /*文件描述符 */
  short events; /* 注册的事件*/
  short revents; /* 实际发生的事件,由内核填充 */
};

其中,fd成员指定文件描述符;events成员告诉poll监听fd上的哪些事件,它是一系列事件的按位或;revents成员则由内核修改,以通知应用程序的fd上实际发生了哪些事件。

events 和 revents能够设置的值都定义在<poll.h>头中,有以下几种可能:

事件描述
POLLIN普通或优先级带数据可读
POLLRDNORM普通数据可读
POLLRDBAND优先级带数据可读
POLLPRI高优先级数据可读
POLLOUT普通数据或优先级带数据可写
POLLWRNORM普通数据可写
POLLWRBAND优先级带数据可写
POLLERR发生错误
POLLHUP发生挂起
POLLNVAL文件描述符没有打开

需要注意的是,后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中,POLLERR,POLLHUP,POLLNVAL在events属性中是没有意义的。
常用的是POLLIN和POLLOUT。
POLLRDHUP (since Linux 2.6.17),在socket的一端关闭了连接,或者是写端关闭了连接时触发。但使用POLLRDHUP事件时,我们需要在代码最开始处定义_GNU_SOURCE。
poll返回时,我们只需要将fds数组中的每个元素中的revents成员与关心的事件进行&操作,如果值大于0,则代表该事件已就绪。例如:if(fds[0].revents & POLLIN ){//文件描述符可读}

2. nfds参数:
nfds参数指定被监听事件集合fds的大小。其类型nfds_t的定义如下:
typedef unsigned long int nfds_t;

3. timeout参数:
timeout参数指定poll的超时值,单位是毫秒。当timeout值为 0 时,poll() 函数立即返回。当timeout的值为 -1 时,则使 poll() 一直阻塞直到一个指定事件发生。


函数返回值:

成功时,poll() 返回结构体中 revents 域不为 0 的文件描述符个数;如果在超时前没有任何事件发生,poll()返回 0;
失败时,poll() 返回 -1,并设置 errno 为下列值之一:
EBADF:一个或多个结构体中指定的文件描述符无效。
EFAULT:fds 指针指向的地址超出进程的地址空间。
EINTR:请求的事件之前产生一个信号,调用可以重新发起。
EINVAL:nfds 参数超出 PLIMIT_NOFILE 值。
ENOMEM:可用内存不足,无法完成请求。


代码示例:

下面是一个使用poll同时监听一个有名管道和标准输入的代码。

#include <poll.h>  
#include <stdio.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <unistd.h>  

int main(int argc, char *argv[])  
{  

    int ret;  
    int fd;  
    struct pollfd fds[2]; // 监视文件描述符结构体,2 个元素  

    ret = mkfifo("test_fifo", 0666); // 创建有名管道  
    if(ret != 0){  
        perror("mkfifo:");  
    }  

    fd = open("test_fifo", O_RDWR); // 读写方式打开管道  
    if(fd < 0){  
        perror("open fifo");  
        return -1;  
    }  

    ret = 0;  

    fds[0].fd = 0;   // 标准输入  
    fds[1].fd = fd;  // 有名管道  

    fds[0].events = POLLIN; // 普通或优先级带数据可读  
    fds[1].events = POLLIN; // 普通或优先级带数据可读  

    fds[0].revents=0;  //初始化
    fds[1].revents=0;

    while(1){  

        // 监视并等待多个文件(标准输入,有名管道)描述符的属性变化(是否可读)  
        // 没有属性变化,这个函数会阻塞,直到有变化才往下执行,这里没有设置超时  
        ret = poll(fds, 2, -1);  
        //ret = poll(&fd, 2, 1000);  

        if(ret == -1){ // 出错  
            perror("poll()");  
        }else if(ret > 0){ // 准备就绪的文件描述符  

            char buf[100] = {0};  
            if( ( fds[0].revents & POLLIN ) ==  POLLIN ){ // 标准输入  
                read(0, buf, sizeof(buf));  
                printf("stdin buf = %s\n", buf);  

            }else if( ( fds[1].revents & POLLIN ) ==  POLLIN ){ // 有名管道  
                read(fd, buf, sizeof(buf));  
                printf("fifo buf = %s\n", buf);  
            }  

        }else if(0 == ret){ // 超时  
            printf("time out\n");  
        }  

    }  

    return 0;  
}  


poll()的特点:

select() 和 poll() 系统调用的本质一样,前者在 BSD UNIX 中引入的,后者在 System V 中引入的。相比select(),poll()性能改进了很多,但是也还是存在一些缺点。

  1. poll的优点:

    • poll与select不同,通过一个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别用于标示关注的事件和发生的事件,故pollfd数组只需要被初始化一次。
    • poll的实现机制与select类似,其对应内核中的sys_poll,只不过poll向内核传递pollfd数组,然后对pollfd中的每个描述符进行poll,相比处理fdset来说,poll效率更高。
    • poll() 没有最大文件描述符数量的限制。
  2. poll的缺点:

    • 虽然fd没有限制,但是事实上,同时连接的客户端在有些时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
    • poll() 和 select() 同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间
    • 每次调用poll,都要轮询检测events数组中fd的revents是不是和其events相同,开销大

推荐文章:I/O多路复用之epoll

I/O 多路复用之select()、poll()、epoll()详解 I/O 多路复用select==>时间复杂度O(n)poll==>时间复杂度O(n)epoll==>时间复杂度O(1)epoll的接口介绍epoll的工作模式epoll和select/poll的对比epoll的优点 select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件 阅读详情

相关推荐

I/O多路复用(select,poll)函数及示例程序

I/O多路复用 在网络编程中,不得不提的一个概念就是I/O多路复用机制,采用I/O多路复用机制,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,能够同时处理多个描述符。 目前Linux上的I/O多路复用机制主要有三种select,poll,epoll,因为select与poll比较相似,因此这篇文章先讲select和poll函数。 接下来分别从函数、结构、注意点分别进行说明...

wefang的博客 1108

Linux高级IO ------ poll ,epoll(重要)

Linux高级IO ------ poll ,epoll(重要)

向未来❀去探索 的博客 2444

Linux系统编程——I/O多路复用select、poll、epoll

参考:https://segmentfault.com/a/1190000003063859 Linux下的I/O复用与epoll详解:https://www.cnblogs.com/lojunren/p/3856290.html 彻底学会 epoll 系列:http://blog.chinaunix.net/uid/28541347/sid-1931...

墨鱼菜鸡 894

简单理解poll

前期知识: 在开始接触select之前,你需要先对IO的同步,异步,阻塞,非阻塞有个基本的了解,知道什么是IO多路复用。下面这篇文章可以帮助你快速区分这几种模型:[IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇)](https://blog.youkuaiyun.com/historyasamirror/article/details/5778378). poll的系统调用: poll系统调用和select类似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。 poll的函数格式: #incl

Lavender的博客 1001

I/O多路复用之select/poll/epoll

1、基本概念  IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:   (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。   (2)当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。   (3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。

yangrujing的专栏 713

ADS软件操作(10)——DAC控件使用

该控件可以用于为元件定义随频率变换的参数,如放大器的最佳负载阻抗或者源阻抗,需要双频匹配时的优化等,下图是ADS中该控件的模型。

Zhuanzhuyan的博客 4387

kafka poll timeout

Kafka Poll超时是指在消费者从Kafka集群中拉取消息时,如果在规定的时间内未能收到任何消息,就会触发超时。这个超时时间是可以配置的,它的作用是避免消费者长时间阻塞等待消息,导致整个系统的性能问题。 在Kafka消费者API中,poll超时是通过在poll()方法调用中传递超时值来实现的。消费者在调用poll()方法时,如果在规定的时间内没有收到任何消息,它就会立即返回,并且没有任何消息被...

weixin_42584586的博客 2442

华硕ROG幻16笔记本电脑模式切换管理工具完美替代华硕奥创中心管理工具

参考文档1这个工具可以完美替代华硕奥创中心工具,可以定制化不同模式下的CPU、GPU、风扇转速、电池计划等。是由华硕开发人员开发的一个纯绿色的系统管理工具。直接展示启动后的工具界面效果图:这个工具也可以一键式停止正在运行的华硕ASUS服务,减少不必要的资源消耗。

追梦&天空的博客 1万+

IO多路转接 —— 认识 poll 函数

简单认识poll接口函数,以及对应的使用方法

challenglistic的博客 1317

spring boot 集成cas(一) 服务端搭建

简单点就是统一服务认证,多个系统一次登录。俗称单点登录。

慕孑晨的博客 1955

倍福TC3 PLC高速采集实战:如何用PLC-Recorder实现0.24ms级时间戳同步

本文详细介绍了倍福TC3 PLC与PLC-Recorder实现0.24ms级时间戳同步的工程实践方案。通过硬件拓扑设计、时间源选择优化、报文结构封装及同步验证方法,为工业自动化领域的高精度数据采集提供了可靠解决方案,特别适用于精密装配、激光切割等微秒级同步要求的场景。

weixin_29193359的博客 372

深入理解网络 I/O 多路复用:SELECT、POLL

该篇博文主要介绍的是 I/O 模型中的多路复用:SELECT、POLL,简要分析了 I/O 多路复用的模型,通过图解分析的方式告知多路复用所带来的好处「介绍了 SELECT、POLL 函数以及它们的区别」,通过实践代码的方式来分析 I/O 多路复用在系统调用中所涉及到的内核流程代码,同时也当代码编写不当时会给 TCP 挥手带来的问题,最后介绍了上篇 NIO 博文与 I/O 多路复用之间的区别,希望能够得到你的支持

vnjohn 博主 > 主线分享后端领域业务设计知识、源码思想、架构设计 5682

西门子 S7-1200 G2 高速计数器的使用方法介绍

西门子 S7-1200 G2 高速计数器的使用方法介绍

Robot_PLC_HMI_Automation 1688

I/O 多路复用select,poll

select 是最早出现也是最通用的 I/O 多路复用机制,几乎所有操作系统都支持它。工作原理你提供三组文件描述符集合(一个用于读事件,一个用于写事件,一个用于异常事件)。select 会阻塞等待,直到这些集合中的任何一个文件描述符准备好进行 I/O 操作(比如有数据可读、可写或者发生错误)。当 select 返回时,它会修改这三个集合,只留下那些已经就绪的文件描述符。你需要遍历所有文件描述符,才能知道具体是哪些就绪了。优点可移植性好:几乎所有 Unix-like 系统都支持。

cyz322649的博客 1401

【云原生进阶之容器】第六章容器网络6.6.2--Cilium部署

部署Cilium非常简单,可以通过单独的yaml文件部署全部组件(目前我使用了这个方式部署了1.7.1版本),也可以通过Helm Chart一键完成。重要的是部署环境和时机:官方建议所有部署节点都使用Linux最新稳定内核版本,这样所有的功能都能启用。作为一个Kubernetes网络组件,它应该在部署Kubernetes其他基础组件之后,才进行部署。

junbaozi的专栏 791

Proxmox VE 9 更换源

创建一键更换Proxmox VE 9.0源的Bash脚本,实现快速替换软件源。脚本需包含订阅提醒关闭功能,兼容Proxmox VE 9.0系统,执行命令为bash /proxmox_9.0_Repo.sh。该工具可简化源配置过程,自动处理系统更新源替换及订阅提示屏蔽,适合需要快速配置Proxmox环境的用户使用。

极致,细节 4982

I/O模型:用poll实现多路复用I/O(linux下C语言版)

本文介绍了UNIX/Linux下的I/O多路复用技术,重点讲解了poll函数的使用。文章首先分析了四种I/O模型的优缺点,说明多路复用I/O能有效解决多路输入输出流处理的效率问题。详细介绍了poll函数的参数、返回值和使用步骤,包括创建文件描述符集合、事件监测和处理流程。通过两个实例演示了poll函数的实际应用:监测键盘鼠标输入和服务器端同时处理多个客户端连接。最后总结了poll函数的优势(无数量限制、高效)和不足(仍需遍历检查),并提到select、epoll等其他多路复用方法。

2301_82019104的博客 1310

SKUA-GOCAD入门教程-第二节

软件启动及项目设置

江洋大葱的博客 1146

I/O多路复用之select、poll、epoll实例

1、select /* Access macros for `fd_set'. */ #define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) #define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) #define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) #define FD_ZERO(fdsetp) __FD_ZERO (fds

李白 8154

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

I/O多路复用select/poll/epoll的区别

I/O多路复用是一种同步的I/O模型,它允许一个进程监视多个文件描述符,并在一个线程中高效地处理来自多个文件描述符的I/O事件。I/O多路复用通过轮询或事件驱动的方式来监视文件描述符。I/O多路复用广泛应用于网络编程、服务器端编程等领域,例如:Linux内核提供了三种I/O多路复用机制:select、poll和epoll都是I/O多路复用技术,用于同时监听多个文件描述符的事件,以便在事件发生时及时响应。它们的主要区别如下:selectC pollC epollC 总结select、poll和ep

byteinit的专栏 1767

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

I/O多路复用 select 、poll

套接字通信并发如果我们服务器端想实现并发,有两种处理方式,第一种是通过多进程的方式来处理并发,第二种是通过多线程的方式来处理服务器端的并发。【问题】如果服务器端的程序只有一个线程,或者说只有一个进程,怎么能够实现并发呢?【回答】需要使用IO多路复用方式了。这种方式的解决方案一共有三种,第一种是select,第二种是poll,第三种是epoll。select可以跨平台,poll和epoll只能在Linux平台使用。从效率上考虑,epoll的底层是一棵红黑树。

呵呵哒!的博客 604

I/O多路复用(select/poll/epoll)

通过一个进程来维护多个Socket,也就是I/O多路复用,是一种常见的并发编程技术,它允许单个线程或进程同时监视多个输入/输出(I/O)流(例如网络连接、文件描述符)。

guaiguaiyalj的博客 1020

poll,I/O多路复用

select的I/O 多路复用技术,通过描述符集合来表示检测的 I/O 对象,通过三个不同的描述符集合来描述 I/O 事件 :可读、可写和异常。缺点是:所支持的文件描述符个数有限,linux系统,select默认最大值为1024。 poll函数介绍 普遍使用的 I/O 多路复用技术,和select 相比,它和内核交互的数据结构有所变化,另外,也突破了文件描述符的个数限制。 int poll(str...

lwj的博客 246

I/O多路复用:select、poll和epoll详解

I/O多路复用 I/O复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要。通常,网络程序在下列情况下需要使用I/O复用技术: 客户端程序要同事处理多个socket。比如将讨论的非阻塞connect技术。 客户端程序要同时处理用户输入和网络连接。 TCP服务器要同时处理监听socket和连接socket。这是I/O复用使用最多的场合。 I/O复用虽然能同时监听多个文件描述...

Tyler_Zx的博客 1万+

I/O 多路复用机制的演进:select → poll → epoll

NIO模型不用像BIO那样,每次要启用一个线程去处理一个连接了,而是可以对某个IO事件进行监听,并继续执行其他任务,不需要阻塞等待。的逐步演进和优化,它们在功能上相似(都用于同时监控多个文件描述符的 I/O 事件),但在性能、可扩展性和使用方式上有显著差异。在传统的BIO模型中(同步阻塞型I/O),每一个连接都要对要对应一个线程进行处理,到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,,一次是在内核态里,一个次是在用户态里 ,而且还会发生。所以,对于 select 这种方式,需要进行。

SoulruiA的博客 2456

I/O多路复用(select、poll、epoll)

I/O多路复用模型

PM26000的博客 820
上一篇: I/O多路复用之select
下一篇: I/O多路复用之水平触发和边沿触发模式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值