多路io之poll

多路io 之 poll机制
poll函数
(1)函数原型
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

int poll(struct pollfd fds[], nfds_t nfds, int timeout);
(2)功能
监听集合有没有动静,如果没有动静就阻塞
如果有动静就成功返回,返回值为集合中有动静的fd的数量。
(3)参数
  1)fds:这个参数写为struct pollfd fds[]更好理解些,第一个参数要求传递一个struct pollfd结构体数组
  这个数组就相当于select的文件描述符集合,只不过select是使用fd_set来定义的,而poll的集合是一个数组。

struct pollfd的成员:
    struct pollfd {
    int fd; :文件描述符
    short events; :设置我们希望发生的事件,比如读事件,这个需要我们自己设置
    short revents; :实际发生的事件,比如读事件,由poll机制自己设置
};

struct pollfd fds[2];
fds[0].fd = 0;
fds[0].events = POLLIN;//读事件(输入事件)

fds[1].fd = 3;
fds[1].events = POLLIN;//读事件(输入事件)

poll监听时如果没有动静就阻塞,有动静就不再阻塞,返回有动静的fd的数量。

如何知道是那些fd有动静
  如果文件描述符“发生的事件”==“实际事件”,就说明希望的事件来了,就是对fd进行相应的“读或写”操作
使用举例:
if(fds[1].events == fds[1].revents)//如果相等,就说明fds[1].fd有动静。
{
  //读写fds[1].fd
}

2)nfds:数组的元素个数。
3)timeout:超时时间,如果写的是
(a)-1:不设置超时,如果集合没有动静就一直阻塞下去,直到poll函数被信号中断(唤醒)或者集合有动静为止
(b)非-1值:比如3000(3000微妙),表示将超时时间设置为3秒也就是说poll超时时间的单位时微妙。

4)返回值
(a)返回-1:说明函数调失败,errno被设置。
  · 如果是被信号中断从而导致出错返回-1时,errno被设置为EINTR,
  · 如果不想被中断,要么重启poll的调用,要么忽略或者屏蔽这些信号。
(b)0:超时时间到,而且没有文件描述符有动静
(c)>0:返回有响应的文件描述符的数量
poll.c

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




void print_err(char *str,int line,int err_no){
    printf("%d,%s:%s\n",line,str,strerror(err_no) );
    exit(-1);
}

int main(int argc, char const *argv[])
{
    int coord=0;
    int mousefd =-1;
    fd_set readfds;

    char buf[100]={0};
    int ret= 0;

    struct timeval timeover;
    struct pollfd fds[2];
    
    

    mousefd =open("/dev/input/mouse1",O_RDONLY); //可能Mouse0或2
    if(mousefd == -1) print_err("open mouse0 fail",__LINE__,errno);

     fds[0].fd=0;
     fds[0].events=POLLIN;
     fds[1].fd=mousefd;
     fds[1].events=POLLIN;
    
    while(1){
         label:ret =poll(fds,2,3000);
                if(ret == -1 && errno == EINTR) goto label;
                else if(ret == -1) printf("poll fail",__LINE__,errno);
                else if(ret>0){
                        if(fds[0].events == fds[0].revents){
                            bzero(buf,sizeof(buf));
                            ret = read(fds[0].fd,buf,sizeof(buf));
                            if(ret>0) printf("%s\n",buf);
                        }
                        if(fds[1].events == fds[1].revents){
                            bzero(&coord,sizeof(coord));
                            ret = read(fds[1].fd,&coord,sizeof(coord));
                            if(ret>0) printf("%u\n",coord);
                        }
                }else if(ret ==0){
                        printf("time out\n");
                }


    }
    return 0;
}