多路复用IO&select&poll

来源:互联网 发布:什么是云计算的基础 编辑:程序博客网 时间:2024/05/21 06:48

概述

Linux提供了两个函数来实现多路复用IO操作

正文

函数select

函数原型

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

void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);

参数

参数ndfs:select中监视的文件句柄数,一般设为要监视的文件中的最大fd+1。
参数readfds:需要读取的fd_set类型的结构体地址
参数writefds: 需要写入的fd_set类型的结构体地址
参数exceptfds:
参数timeout:select()的超时结束时间。
这个参数它使select处于三种状态,
第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,
一定等到监视文件描述符集合中某个文件描述符发生变化为止;
第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,
都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,
超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

返回值

返回值:
负值:select错误
0:等待超时,没有可读写或错误的文件
正值:某些文件可读可写或出错

测试代码

int main(int argc,char **argv){    int fd = -1,ret = -1;    char buf[100] = {0};    fd_set Myreadfds;    struct timeval  Mytimeout;    fd = open(MOUSE,O_RDONLY );/*鼠标阻塞*/    if(fd<0)    {        perror("open ");        return -1;    }    /*fd -> mouse, 0->keyboard*/    FD_ZERO(&Myreadfds);/*清空内容*/    FD_SET(fd,&Myreadfds);/*添加fd*/    FD_SET(0,&Myreadfds);/*添加fd*/    Mytimeout.tv_sec = 3;/*设置超时时间*/    Mytimeout.tv_usec = 0;    ret = select(fd+1,&Myreadfds,NULL,NULL,&Mytimeout);    if(ret<0)       {        perror("select ");        return -1;    }    else if(ret == 0)        printf("time out.\r\n");    else    {        if(FD_ISSET(0,&Myreadfds))/*keyboard*/        {            memset(buf,0,sizeof(buf));            ret = read(0,buf,100);  /*读取标准输入的值*/            if(ret>0)                printf("keyboard[%d] = %s\r\n",ret,buf);        }        else if(FD_ISSET(fd,&Myreadfds))/*mouse*/        {            memset(buf,0,sizeof(buf));            ret = read(fd,buf,100);/*读取鼠标的值*/            if(ret>0)                printf("mouse[%d] = %s\r\n",ret,buf);        }    }    close(fd);    return 0;}

函数poll

函数原型

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

参数

参数fds为需要操作的struct pollfd 类型的结构体的地址
参数ndfs:select中监视的文件句柄数,一般设为要监视的文件中的最大fd+1。
参数timeout为最大超时时间(单位ms)

返回值

负值:poll错误
0:等待超时,没有可读写或错误的文件
正值:成功

测试代码

int main(int argc,char **argv){    int fd = -1,ret = -1;    char buf[100] = {0};    struct pollfd Myfds[2] = {0};    fd = open(MOUSE,O_RDONLY );/*鼠标阻塞*/    if(fd<0)    {        perror("open ");        return -1;    }    Myfds[0].fd = 0;/*keyboard*/    Myfds[0].events = POLLIN;/*输入方式*/    Myfds[1].fd = fd;/*mouse*/    Myfds[1].events = POLLIN;/*输入方式*/    ret = poll(Myfds,fd+1,3000);/*超时3s*/    if(ret<0)       {        perror("select ");        return -1;    }    else if(ret == 0)        printf("time out.\r\n");    else    {        if(Myfds[0].events == Myfds[0].revents)//keyboard        {            memset(buf,0,sizeof(buf));            ret = read(0,buf,100);  /*读取标准输入的值*/            if(ret>0)                printf("keyboard[%d] = %s\r\n",ret,buf);        }        else if(Myfds[1].events == Myfds[1].revents)//mouse        {            memset(buf,0,sizeof(buf));            ret = read(fd,buf,100);/*读取鼠标的值*/            if(ret>0)                printf("mouse[%d] = %s\r\n",ret,buf);        }    }    close(fd);    return 0;}