首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux poll使用

poll 是 Linux 系统中的一个系统调用,用于监视多个文件描述符的状态变化,比如是否可读、可写或出现异常条件。它是处理多个 I/O 操作的一种高效方式,相比于传统的 selectpoll 在处理大量文件描述符时有更好的性能。

基本概念

poll 函数允许程序等待多个文件描述符中的任何一个变为可读、可写或有异常条件待处理。其函数原型如下:

代码语言:txt
复制
#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  • fds 是一个指向 pollfd 结构体数组的指针,每个结构体代表一个文件描述符及其关注的事件。
  • nfdsfds 数组中元素的数量。
  • timeout 是等待的超时时间(以毫秒为单位),如果为 -1,则表示无限期等待直到有事件发生;如果为 0,则表示立即返回。

优势

  • poll 不需要像 select 那样重新初始化文件描述符集,因此在处理大量文件描述符时效率更高。
  • poll 返回时,不需要重新设置文件描述符集,可以直接从返回的结构体数组中获取就绪的文件描述符。

类型

pollfd 结构体定义如下:

代码语言:txt
复制
struct pollfd {
    int fd;         // 文件描述符
    short events;   // 关注的事件
    short revents;  // 发生的事件
};

eventsrevents 是位掩码,可以使用以下事件:

  • POLLIN:文件描述符可读。
  • POLLOUT:文件描述符可写。
  • POLLERR:文件描述符发生错误。
  • POLLHUP:文件描述符挂起事件。
  • POLLNVAL:文件描述符非法。

应用场景

poll 常用于网络编程,如服务器端程序,用于同时处理多个客户端连接。它可以有效地等待多个套接字变得可读或可写,从而实现非阻塞的 I/O 多路复用。

示例代码

以下是一个简单的 poll 使用示例,用于监听标准输入和网络套接字的事件:

代码语言:txt
复制
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int sockfd;
    int result;
    struct sockaddr_in serv_addr;
    socklen_t length;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(1);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);

    result = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    if (result < 0) {
        perror("connect");
        exit(1);
    }

    struct pollfd fds[2];
    fds[0].fd = STDIN_FILENO;
    fds[0].events = POLLIN;
    fds[1].fd = sockfd;
    fds[1].events = POLLIN;

    while (1) {
        result = poll(fds, 2, -1);
        if (result < 0) {
            perror("poll");
            exit(1);
        }

        if (fds[0].revents & POLLIN) {
            char buf[1024];
            ssize_t n = read(STDIN_FILENO, buf, sizeof(buf));
            if (n > 0) {
                printf("stdin: %s", buf);
            }
        }

        if (fds[1].revents & POLLIN) {
            char buf[1024];
            ssize_t n = read(sockfd, buf, sizeof(buf));
            if (n > 0) {
                printf("socket: %s", buf);
            }
        }
    }

    close(sockfd);
    return 0;
}

遇到的问题及解决方法

  1. 性能问题:如果 poll 返回的事件数量非常多,处理这些事件可能会成为瓶颈。此时可以考虑使用更高级的 I/O 多路复用技术,如 epoll(Linux 特有)。
  2. 文件描述符泄漏:在使用 poll 时,需要确保在不再需要监视某个文件描述符时关闭它,以避免文件描述符泄漏。
  3. 超时处理poll 的超时参数需要根据实际应用场景合理设置,以避免程序长时间阻塞或频繁轮询导致的 CPU 占用过高。

通过合理使用 poll,可以有效地管理多个 I/O 操作,提高程序的性能和响应速度。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Linux select poll源码剖析

在读select、poll源码前,需要先了解的知识点: 等待队列 文件系统(主要是进程的打开文件描述符表以及struct file) poll机制 资源注册监听poll() -> poll_wait(...实际linux内核设计: * 每个wait_queue_t的private字段指向同一个poll_wqueues,然后 * 共用的poll_wqueues中保存了指向调用进程...使用 */ new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL); if (!...* 我们先在栈上分配一块缓冲区,用于缓存输入集以及结果集,如果缓存的 * 空间大小不够,那么再使用kmalloc()动态分配,优先使用栈缓存而不用动态 * 内存可以加快访问......allocate memory in units of * long-words. */ /* * n个bits至少需要size个long才能装下(之后我们使用

3.2K20

linux poll机制《Rice linux 学习笔记》

2、如果使用阻塞方式,两个read都会阻塞,但第一个read时阻塞了。而在这时,第二个设备返回,进程也不会醒来及时处理。直到第一个设备返回后,才可以读取第二个设备。...3、如果使用非阻塞方式,就会不断的轮询,CPU又变得很忙。 4、为了解决不能同时操作多个设备的方法:①使用poll、select方法。②使用多线程方法。...poll机制的解析:其中poll()函数和select()函数的功能同等。...poll函数的解析: 使用poll函数,需要包含头文件:#include poll.h> int poll(structpollfd fds[], nfds_t nfds, int timeout);...系统调用分析: poll系统调用在内核中的入口函数是sys_poll(); 分析内核源码,可以看出它的调用关系: sys_poll() do_sys_poll() do_poll() for (;;

1.2K10
  • 【Linux】从零开始使用多路转接IO --- poll

    --- 中岛敦 《山月记》------- 1 前言 上一篇文章我们学习了多路转接中的Select,其操作很简单,但有一些缺陷: 每次调用 select,都需要手动设置 fd 集合, 从接口使用角度来说也非常不便...select每次调用接口都需要手动设置fd集合,poll不需要! 那么接下来我们就来看poll是怎样实现的。 1 poll接口介绍 首先poll的作用与select一模一样:等待多个文件描述符!...我们来看看poll接口: OLL(2) Linux Programmer's...timeout:输入性参数,这里直接采用的是毫秒,不使用结构体!等于0时是非阻塞IO,等于-1时是阻塞IO! 返回值表示是否成功:大于0 即有n个就绪了;等于0表示超时了;小于0就是poll出错了!...而poll使用一个结构体,对于这个文件描述符有两种事件:requested events 与 returned events!输入输出并不互相干扰!那么就解决了select需要不断初始化的问题。

    9710

    使用 poll 检测管道断开

    一般使用 poll 检测 socket 或标准输入时,只要指定 POLLIN 标志位,就可以检测是否有数据到达,或者连接断开: 1 struct pollfd fds[3]; 2 fds[0].fd...sock_fd; 5 fds[1].events = POLLIN; 6 fds[2].fd = pipe_fd; 7 fds[2].events = POLLIN; 8 ret = poll...一个已经关闭的句柄时(句柄号 >=0 有效),poll 本身并不返回错误,而是给对应的句柄事件中设置  POLLNVAL 标志位: 1 if (pfd[2].revents & POLLNVAL) {...2 // handle pipe close 3 ... 4 } 若 poll 一个无效句柄时(句柄号为-1),poll 本身仍不返回错误,但该句柄一定没有任何事件可供检测与返回...当然如果传入 poll 的句柄数组中所有句柄都为无效句柄时,poll仍不返回错误,此时若提供超时,可当成sleep使用; 若不提供超时,则会进入无限期等待…… 测试代码

    78720

    【Linux】高级IO --- 多路转接,select,poll,epoll

    pollServer.hpp主要的接口和select一样,只是把接口里面select部分替换成了poll接口的使用,在初始化服务器时,需要开辟一个结构体数组,这个数组开辟在堆上,这个数组其实比较标准的写法是搞成扩容版本的...虽然说epoll是作了改进的poll,但在接口的使用和底层实现上,epoll和poll天差地别,在linux内核2.5.44版本时,就引入了epoll接口,而现在主流的linux内核版本已经是3点几了。...同时红黑树对于平衡的要求并没有AVL高,所以在旋转调平衡的次数上,红黑树要比AVL树少很多,在整体效率上是要比AVL树高的,这也是使用红黑树,不使用AVL树的原因。...(3)select poll在使用的时候,都需要程序员自己维护一个第三方数组来存储用户关心的fd及事件,但epoll不需要,因为内核为epoll在底层维护了一棵红黑树,用户直接通过epoll_ctl来对红黑树的节点进行增删改即可...其实我个人认为,内核是可以做到让select和poll在使用时,程序员也按需遍历就绪的fd的,而不用每次都全部遍历存放fd的数组或位图。

    36930

    linux 网络编程 IO复用 select,poll ,epoll

    核心思想:I/O复用 ---- 使用情景: 客户端程序要同时处理多个socket 客户端程序要同时处理用户输入和网络连接 TCP服务器要同时处理监听socket和连接socket,这是使用最多的场合...对写操作被关闭的socket执行写操作将出发一个SIGPIPE信号 socket使用非阻塞connect连接成功或者失败之后 socket上有未处理的错误,此时我们可以使用getsockopt来读取和清除该错误...与poll的区别(见下面的demo) poll和epoll在使用上的差别: [cpp] view plaincopy /* 索引poll返回的就绪文件描述符 */ /* 方式:遍历,检查标志位...可以使用epoll的EPOLLONESHOT事件实现一个socket连接在任一时刻都被一个线程处理。...---- 参考资料: 《Linux高性能服务器编程》

    2.6K20

    POLL机制

    即如果第一次访问可以使用直接返回,若不能访问,则先将应用层休眠,在到了设定的时间,再访问一次,此时可以访问则返回成功标志,若不能访问则返回失败。...Poll机制的实现需要等待队列的支撑。 03 3.代码应用 在驱动里若要使用poll机制,只需要初始化一个等待队列,实例化file_operations中.poll成员即可。...app: poll | drv:sys_poll | — do_sys_poll(struct pollfd __user * ufds, unsigned int...当然,另一个角度来讲,linux的实现很伟大,每一个细节都值得学习,所以当时间足够富裕时,建议多看看每一个流程的细节的衔接。...参考资料: https://www.cnblogs.com/amanlikethis/p/6915485.html     《嵌入式linux应用开发完全手册V2.3_韦东山》

    1.2K00

    Linux中的sleep、usleep、nanosleep、poll和select

    在进行Linux C/C++编程时,可调用的sleep函数有好多个,那么究竟应当调用哪一个了?...下表列出了这几个函数间的异同点,可作为参考: 性质 精准度 线程安全 信号安全 sleep libc库函数 秒 是 不能和alarm同时使用 有些是基于alarm实现的,所以不能和alarm同时使用...poll 系统调用 毫秒 是 是 在协程库libco中可安全使用,如被信号中断,则实际睡眠时长会小于参数指定的时长 ppoll 系统调用 纳秒 是 是 如被信号中断,则实际睡眠时长会小于参数指定的时长...microseconds % 1000000) * 1000 }; while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno)); } 3) 基于poll...的秒级封装 // 可libco协程库中安全使用 void pollsleep(int milliseconds) { (void)poll(NULL, 0, milliseconds); } 4

    7.6K20

    Linux中的sleep、usleep、nanosleep、poll和select

    在进行Linux C/C++编程时,可调用的sleep函数有好多个,那么究竟应当调用哪一个了?...下表列出了这几个函数间的异同点,可作为参考: 性质 精准度 线程安全 信号安全 sleep libc库函数 秒 是 不能和alarm同时使用 有些是基于alarm实现的,所以不能和alarm同时使用...poll 系统调用 毫秒 是 是 在协程库libco中可安全使用,如被信号中断,则实际睡眠时长会小于参数指定的时长 ppoll 系统调用 纳秒 是 是 如被信号中断,则实际睡眠时长会小于参数指定的时长...microseconds % 1000000) * 1000 }; while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno)); } 3) 基于poll...的秒级封装 // 可libco协程库中安全使用 void pollsleep(int milliseconds) { (void)poll(NULL, 0, milliseconds); } 4)

    5.1K40

    select、poll、epoll

    poll技术与select技术实现逻辑基本一致,重要区别在于其使用链表的方式存储描述符fd,没有最大连接数的限制,但是对于select存在的性能问题并没有解决。...struct epoll_event 结构体定义事件 // 创建保存epoll文件描述符的空间,该空间也称为“epoll例程” int epoll_create(int flag); // 使用红黑树的数据结构...epoll通过在Linux内核中申请一个简易的文件系统来管理多个文件描述符。...当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,红黑树方便快速找到与文件描述符相关的epitem结构。...对比 select缺点: 最大并发数限制:使用32个整数的32位,即32*32=1024来标识fd,虽然可修改,但是有以下第二点的瓶颈; 效率低:每次都会线性扫描整个fd_set,集合越大速度越慢; 内核

    1.2K30

    select poll epoll

    poll poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间 它没有最大连接数的限制,原因是它是基于链表来存储的。...poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。...epoll epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。...epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。...3、内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。

    1.1K90

    【Linux高级IO】Linux多路转接:深入探索poll与epoll的奥秘

    ❀ Linux高级IO 多路转接:poll poll函数接口 poll优缺点 多路转接:epoll epoll的相关系统调用 epoll工作原理 epoll的优点 epoll工作方式 理解ET模式和非阻塞文件描述符...为了应对这一挑战,Linux操作系统提供了多种I/O多路复用技术,其中poll和epoll作为两种重要的机制,在提升系统资源利用率和处理效率方面发挥着关键作用。...多路转接:poll 在Linux系统中,多路转接技术是一种重要的I/O处理机制,它允许单个线程同时监控多个文件描述符(例如套接字)上的事件,从而有效地管理多个并发连接。...在内核层面,遍历检测,关心的fd是否有对应的事件就绪 poll作为Linux中的多路转接技术之一,在处理多个并发连接时具有一定的优势。...多路转接:epoll epoll是Linux下多路复用I/O接口select/poll的增强版本,旨在提高程序在大量并发连接中只有少量活跃情况下的系统CPU利用率。

    11310

    大话 Select、Poll、Epoll

    遗憾的是,linux的网络IO中是不存在异步IO的,linux的网络IO处理的第二阶段总是阻塞等待数据copy完成的。真正意义上的网络异步IO是Windows下的IOCP(IO完成端口)模型。...2 Linux的socket 事件wakeup callback机制 言归正传,在介绍select、poll、epoll前,有必要说说linux(2.6+)内核的事件wakeup callback机制,...下面是poll的函数原型,poll改变了fds集合的描述方式,使用了pollfd结构而不是select的fd_set结构,使得poll支持的fds集合限制远大于select的1024。...在linux 2.6.8之前的内核,epoll使用hash来组织fds集合,于是在创建epoll fd的时候,epoll需要初始化hash的大小。...在linux 2.6.8以后的内核中,epoll使用红黑树来组织监控的fds集合,于是epoll_create(int size)的参数size实际上已经没有意义了。

    26K4921

    select,poll,epoll区别

    、epoll了解得不多,下面是从《构建高性能Web站点》摘录下来的介绍,等以后真正接触到select、poll和epoll方面的开发再详细写一下使用上的区别。...它解决了select()的几个不足,尽管select()仍然经常使用(多数还是出于习惯,或者打着可移植的名义): #include poll.h>int poll (struct pollfd...使用poll()和select()不一样,你不需要显式地请求异常情况报告。...但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。 3.使用mmap加速内核与用户空间的消息传递。    ...4.内核微调     这一点其实不算epoll的优点了,而是整个linux平台的优点。也许你可以怀疑linux平台,但是你无法回避linux平台赋予你微调内核的能力。

    1.4K21
    领券