linux I/0复用函数之 ------ poll()

 

一、函数原型:

#include <poll.h>

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

 

二、函数说明:

        系统调用poll()执行的任务同select()很相似。两者间主要的区别在于我们要如何指定待检查的文件描述符。再select()中,我们提供三个集合,在每个集合中标明我们感兴趣的文件描述符。而在poll()中我们提供了一列文件描述符,并在每个文件描述符上标明我们感兴趣的事件。

 

三、参数说明:

fds:是一个struct pollfd结构类型的数组,列出了我们需要poll()检查的文件描述符,其定义如下:

typedef struct pollfd {
        int fd;           /* 需要被检测或选择的文件描述符*/
        short events;     /* 对文件描述符fd上感兴趣的事件 */
        short revents;    /* 文件描述符fd上当前实际发生的事件*/
} pollfd_t;

pollfd结构体中的events和revents字段都是掩码。调用者初始化events来指定需要为描述符fd做检查的事件。当poll()返回时,revents被设定以此来表示该文件描述符上实际发生的事件。

下表列出了events和revents字段中掩码:

 

位掩码events中的输入返回到revents 

POLLIN

POLLRDNORM

POLLRDBAND

POLLPRI

POLLRDHUB

可读取非高优先级数据

等同于POLLIN

可读取优先级数据(linux中不可用)

可读取高优先级数据

对端套接字关闭

POLLOUT

POLLWRNORM

POLLWRBAND

普通数据可写

等同于POLLOUT

优先级数据可写入

POLLERR

POLLHUP

POLLNVAL

 

有错误发生

出现挂断

文件描述符未打开

POLLMSG  linux中不可用

一般来说,poll()真正关心的标志位是:POLLIN、POLLOUT、POLLPRI、POLLRDHUB、POLLHUP、POLLERR

nfds:指定了fds中元素的个数,nfds_t为无符号整形

timeout:决定阻塞行为,一般如下:

-1:一直阻塞到fds数组中有一个达到就绪态或者捕获到一个信号

0:不会阻塞,立即返回

>0:阻塞时间

和select()一样,timeout的精度收软件时钟粒度的影响,如果不是时间粒度整数倍,向上取整。

返回值:

>0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;

==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时

 

-1:  poll函数调用失败,同时会自动设置全局变量errno为下列值之一:

EBADF:一个或多个结构体中指定的文件描述符无效。
EFAULT:fds指针指向的地址超出进程的地址空间。
EINTR:请求的事件之前产生一个信号,调用可以重新发起。
EINVAL:nfds参数超出PLIMIT_NOFILE值。
ENOMEM:可用内存不足,无法完成请求。

 

 

四、代码举例:

/*********************************************
在/root/pro/fd1 /root/pro/fd2中分别有内容,
1234
5678
和
1122
3344
**********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <stropts.h>
#include <sys/poll.h>
#include <sys/stropts.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>

#define BUFSIZE 1024

int main(int argc, char *argv[])
{
    char buf[BUFSIZE];
    int bytes;
    struct pollfd *pollfd;
    int i=0;
    int nummonitor=0;
    int numready;
    int errno;
    char *str;

    if(argc != 3)
    {
        fprintf(stderr,"Usage:the argc num error\n");
        exit(1);
    }


    if((pollfd = (struct pollfd*)calloc(2, sizeof(struct pollfd))) == NULL)
           exit(1);

    for(i; i<2; i++) //初始化化struct pollfd结构
    {
        str = (char*)malloc(14*sizeof(char));        
        memcpy(str,"/root/pro/",14);
        strcat(str,argv[i+1]);//注意,需要把路径信息放到str中

        printf("str=%s\n",str);

        (pollfd+i)->fd = open(str,O_RDONLY);
        if((pollfd+i)->fd >= 0)
            fprintf(stderr, "open (pollfd+%d)->fd:%s\n", i, argv[i+1]);

        nummonitor++;
        (pollfd+i)->events = POLLIN;
    }

    printf("nummonitor=%d\n",nummonitor);
      
    while(nummonitor > 0)
    {
        numready = poll(pollfd, 2, -1);
        if ((numready == -1) && (errno == EINTR))
            continue;       
        else if (numready == -1)
            break; //poll真正错误,退出

        printf("numready=%d\n",numready);

        for (i=0;nummonitor>0 && numready>0; i++)
        {
            if((pollfd+i)->revents & POLLIN)
            {
                
                bytes = read(pollfd[i].fd, buf, BUFSIZE);
                numready--;

                printf("pollfd[%d]->fd read buf:\n%s \n", i, buf);

                nummonitor--;
            }
        }
    }

    for(i=0; i<nummonitor; i++)
        close(pollfd[i].fd);

    free(pollfd);

    return 0;
}

结果为:

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值