poll函数详解及原理

2023-05-16

poll函数实现和select极为相似,但是它们的接口并不相同:

int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);
int select(int maxfdp1, fd_set restrict readfds, fd_set *restrict expectfds, struct timeval restrict tvptr);

  其中poll函数中,结构pollfd如下:
  struct pollfd{
    int fd; //file descriptor
    short event;//event of interest on fd
   short revent;//event that occurred on fd

  }
参数说明:
  fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;
  其中events和revents是通过对代表各种事件的标志进行逻辑或运算构建而成的。events包括要监视的事件,poll用已经发生的事件填充revents。poll函数通过在revents中设置标志POLLHUP、POLLERR和POLLNVAL来反映相关条件的存在。不需要在events中对于这些标志符相关的比特位进行设置。如果fd小于0, 则events字段被忽略,而revents被置为0.标准中没有说明如何处理文件结束。文件结束可以通过revents的标识符POLLHUN或返回0字节的常规读操作来传达。即使POLLIN或POLLRDNORM指出还有数据要读,POLLHUP也可能会被设置。因此,应该在错误检验之前处理正常的读操作。
  poll函数的事件标志符值

常量 说明
POLLIN 普通或优先级带数据可读
POLLRDNORM 普通数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级数据可读
POLLOUT 普通数据可写
POLLWRNORM 普通数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件

注意:后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。
这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。使用poll()和select()不一样,你不需要显式地请求异常情况报告。
POLLIN | POLLPRI等价于select()的读事件,POLLOUT |POLLWRBAND等价于select()的写事件。POLLIN等价于POLLRDNORM |POLLRDBAND,而POLLOUT则等价于POLLWRNORM。
例如,要同时监视一个文件描述符是否可读和可写,我们可以设置 events为POLLIN |POLLOUT。在poll返回时,我们可以检查revents中的标志,对应于文件描述符请求的events结构体。如果POLLIN事件被设置,则文件描述符可以被读取而不阻塞。如果POLLOUT被设置,则文件描述符可以写入而不导致阻塞。这些标志并不是互斥的:它们可能被同时设置,表示这个文件描述符的读取和写入操作都会正常返回而不阻塞。

timeout参数指定等待的毫秒数,无论I/O是否准备好,poll都会返回。timeout指定为负数值表示无限超时;timeout为0指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件。这种情况下,poll()就像它的名字那样,一旦选举出来,立即返回。

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

poll用法示例(从用户端读取信息)

#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <poll.h>

int start_up(sockaddr_in &addr){

    int socketi = socket(PF_INET, SOCK_STREAM, 0);

    printf("%d\n", socketi);
    if (socketi < 0){
        printf("%d, %s", errno, strerror(errno));
        exit(1);
    }

    int flag = bind(socketi, (sockaddr*)&addr, sizeof(addr));
    if (flag < 0){
        printf("%d, %s", errno, strerror(errno));
        exit(2);
    }

    flag = listen(socketi, 5);
    if (flag < 0){
        printf("%d, %s", errno, strerror(errno));
        exit(2);
    }    
    return socketi;

}



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

    if (argc < 3){
        printf("can sgu error");
        exit(0);
    }

    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_family = PF_INET;

    int socketi = start_up(addr);
    /
   // printf("%d\n", socketi);
    char fd[100] = {0};
   // memset(&fd, sizeof(fd), -1);

    struct pollfd pfd[100];
    pfd[0].fd = socketi;
    pfd[0].events = POLLIN;

    for (int i = 1; i < 100; i++){

        pfd[i].fd = -1;
    }

    ///
    int flag = 1;
    int max = socketi;
    char buf[100] = {0};
    socklen_t len = sizeof(addr);
    for( ; ; ){

    int timeout = 2000;
        if (false == flag){
           max = 0;
            for (int i = 1; i < 100; i++){
                if (pfd[i].fd > max)
                    max = pfd[i].fd;
            }
        }
        int ret = poll(pfd, max+1,timeout);

           if (pfd[0].revents & POLLIN){

                struct sockaddr_in client;
                socklen_t client_len = sizeof(client);
                int connfd = accept(socketi, (struct sockaddr*)&client, &client_len);
                if (connfd < 0){
                    printf("%d, %s\n", errno, strerror(errno));
                }
               for (int i = 1; i < 100; i++){
                    if (pfd[i].fd < 0){
                        pfd[i].fd = connfd;
                        max++;
                      break;
                    }
                }

                if (connfd > max)
                    max = connfd;
                }

            for (int i = 1; i < 100; i++){
                if (pfd[i].fd > 0 && (pfd[i].revents & POLLIN)){
                    ssize_t size = read( pfd[i].fd, buf, 20);

                    if (size <= 0){
                        printf("client is quit\n");
                        pfd[i].fd = -1;
                        if (pfd[i].fd == max)
                            flag = false;
                        continue;
                    }

                    buf[size-1] = 0;
                    printf("client:%s\n", buf);


              }
            } 
}


    return 0;
}

以上内容参考:
http://blog.csdn.net/djinglan/article/details/8302938
http://www.cnblogs.com/nathan-1988/archive/2012/07/01/2571786.html
http://baike.so.com/doc/6951258-7173659.html
http://blog.csdn.net/hanchaoman/article/details/7444337

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

poll函数详解及原理 的相关文章

  • Intel英特尔历代经典 CPU 产品回顾

    悉数历史 英特尔历代经典 CPU 产品回顾 从英特尔于 1971 年推出首款 4004 微处理器到现在 xff0c 英特尔处理器已经走过 了 40 个年头 在告别 13 年传奇品牌奔腾之后 xff0c 我们又迎来新一代酷睿 i 双核处 理器
  • vTaskStartScheduler()分析笔记

    FreeRTOS是通过vTaskStartScheduler 函数来启动运行的 xff0c 通常被封装在osKernelStart 中 xff0c 它的工作内容如下 xff1a xTaskCreate 创建空闲任务 xff0c 其优先级为最
  • 在MES中遇到生产异常是怎么处理的

    MES系统在生产过程中 xff0c 难免会遇到各种异常情况 xff0c 如机器故障 材料不足 工人缺席等 xff0c 这些异常情况会影响生产进度和产品质量 那么 xff0c 在MES中遇到生产异常通常是怎么处理的呢 xff1f 1 实时监控
  • ORB-SLAM3: An Accurate Open-Source Library for Visual, Visual-Inertial and Multi-Map SLAM

    摘要 ORB SLAM3是第一个能够让单目 立体相机和RGB D相机与针孔和鱼眼镜头模型解耦进行视觉 视觉 43 惯性和多地图SLAM的系统 第一个主要的创新是一个基于特征的紧密集成视觉 43 惯性SLAM系统 xff0c 它完全依赖于最大
  • SVN右键不显示

    安装重启试了很多中方法 xff0c SVN右键始终不显示 方法1 xff08 测试没有出现 xff09 xff08 一 xff09 开始 运行 输入 regedit 进入注册表 xff1b xff08 二 xff09 进入目录 xff1a
  • GPS定位频率最高是多少HZ?

    转载 xff1a https www zhihu com question 41257990 answer 90574977 现在普遍常见的芯片10Hz xff0c ublox好像可以配置到100Hz xff0c 具体是10还是100记不清
  • 总结下-ST2.0库的霍尔角度估计

    1 首先明确一个关系等式 xff0c 看软件就很容易理解 F1代表FOC执行频率 xff08 PWM周期频率 xff09 xff0c 单位是HZ xff1b A代表一个PWM周期内霍尔角度变化量 xff1b AC代表一个电角度周期的角度变化
  • matlab timeserise

    1 xff09 产生timeserise数据 方法一 xff1a 通过timeseries xff0c 例如ts 61 timeseries rand 5 1 rand是产生5 1的矩阵随机数 方法二 xff1a simulink中产生的数
  • 自适应滤波器

    1 LMS Filter模块仿真时 xff0c 输出会发散 xff0c 主要是mu值选取不合适 xff0c 选取比较小的值就可以了 2 可以把网上的m文件通过 matlab coder工具直接转为C文件 xff08 不能直接使用 xff0c
  • 步进电机生成S曲线上位机

    参考的 步进电机S SigMoid 曲线加减速 查表法 Renjiankun的博客 CSDN博客 步进电机s曲线 自己用C 花了大半天搞了一个 xff0c 直接copy生成的数组使用 xff1b 源码可下载步进电机生成S曲线上位机 嵌入式文
  • 电解电容的ESR,想说三句话

    电容的ESR是指电容的等效串联电阻 xff08 或阻抗 xff09 理想的电容 xff0c 是没有电阻的 但是实际上 xff0c 任何电容都有电阻 xff0c 这个电阻值和电容的材料 结构有关系 1 那些 贴片电容 选用贴片电容的时候 xf
  • Matlab2012b&Simulink licence失效解决办法(重复激活解决方案)

    光棍节结束 xff0c math公司也对用户端进行调整 xff0c 很多朋友的matlab都被要求重新添加许可文件 然而 xff0c 基本都是激活完成 xff0c 打开 xff0c 继续激活 xff0c 然后激活完成重复 这是因为激活的文件
  • 航模飞机飞行力效和飞行时间的算法

    力效 xff08 g w xff09 总起飞重量 xff08 g 除起飞功率 xff08 w xff09 例 xff1a 有一架飞机 xff0c 总起飞重量是 8KG xff0c 也就是 8000G xff0c 悬停电流是 40A xff0
  • 5脚继电器的接法

    5脚继电器原理图和接法 一般情况 xff0c 三只脚的那一边中间脚是输出触点的公共端子 xff0c 另外两个引脚是线圈 xff0c 即接驱动端 另外2个脚那边分别是常开和常闭触点 如下图 xff1a A B 脚接驱动电路端 要控制的电路接1
  • Python -- argparse :命令行参数解析模块

    Python argparse xff1a 命令行参数解析模块 官网参考文档 文章目录 Python argparse xff1a 命令行参数解析模块1 总述2 96 add argument 96 2 1 name or flags2 2
  • PWM波控制舵机总结

    文章转载自 https www cnblogs com zhoubatuo p 6138033 html 一 关于舵机 xff1a 舵机 xff08 英文叫Servo xff09 xff1a 它由直流电机 减速齿轮组 传感器和控制电路组成的
  • PNP三极管和NPN三极管的开关电路

    一 三极管开关电路设计的可行性及必要性 可行性 xff1a 用过三极管的人都清楚 xff0c 三极管有一个特性 xff0c 就是有饱和状态与截止状态 xff0c 正是因为有了这两种状态 xff0c 使其应用于开关电路成为可能 必要性 xff
  • Clark变换与Park(派克)变换

    转载https blog csdn net chenjianbo88 article details 53027298 clark变换 xff1a 将abc 变换到 静止 的 坐标系下 Park变换 xff1a 将abc 变换到 旋转 的
  • 无感方波和FOC堵转检测策略参考

    http mcu eetrend com content 2017 100007230 html 基于S12ZVM的车用无传感器BLDC堵转检测方法探讨 judy 发布于 xff1a 周一 07 31 2017 11 05 xff0c 关键
  • kubernetes 快速入门

    文章目录 2 kubernetes 快速入门前言一 nameSpace1 简介2 常用命令查看 nameSpace创建 nameSpace删除 nameSpace 二 pod 与 deployment1 简介2 常用命令查看 pod创建 d

随机推荐