zoukankan      html  css  js  c++  java
  • IO多路转接select和poll

    select

    IO多路复用的设置方法与信号的屏蔽有点相似:
    信号屏蔽需要先设定一个信号集, 初始化信号集, 添加需要屏蔽的信号, 然后用sigprocmask设置
    IO多路转接需要先设定一个文件描述符集, 初始化描述符集, 添加感兴趣的描述符, 然后用select进行轮询检测哪些描述符已经可用

    描述符集相关函数:

    fd_set //描述符集
    int FD_ZERO(fd_set*)// 清空fd_set
    int FD_SET(fd,fd_set*)// 将fd添加到fd_set中
    int FD_CLR(fd,fd_set*)// 从fd_set中删除fd
    int FD_ISSET(fd,fd_set*)// select返回后, 判断fd_set中的fd是否已经可用
    
    int select(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tvptr)
    maxfdp1: 最大文件符编号(fd)+1, 或直接用FD_SETSIZE
    readfds: 感兴趣的输入描述符集
    writefds: 感兴趣的输出描述符集
    exceptfds: 感兴趣的错误输出描述符集
    struct timeval{
        time_t tv_sec; //秒 long int
        suseconds_t tv_usec; //微秒 long int
    }
    select最后一个参数为NULL, 表示无限等待; 为0时(timeval结构成员设置成0), 不等待; 不为0时(timeval指定值)时等待指定的时间后返回
    

    例子: 从STDIN_FILENO读

    #include "apue.c"
    #include <sys/select.h>
     
    int main(){
        int ret, len;
        fd_set set;
        struct timeval time_out={5,0};
        while(1){
            FD_ZERO(&set);
            FD_SET(STDIN_FILENO,&set);
            time_out.tv_sec=5;
            time_out.tv_usec=0; 
     
            ret=select(1,&set,NULL,NULL,&time_out);
            switch(ret){
                case 0:
                    puts("time out, retry");
                    continue;
                case -1:
                    err_quit("select err");
                default:
                    if(FD_ISSET(STDIN_FILENO,&set)){
                        puts("STDIN_FILENO is available");
                        char buf[100]={0};
                        len=read(STDIN_FILENO,buf,100);
                        write(STDOUT_FILENO,buf,len);
                    }
            }
        } 
        return 0;
    }
    

    注意:select 返回后, 传入的fd_set和timeval会改变, 所以当重新调用select时要再次初始化fd_set和timeval
    另外还有一个与select相似的函数叫pselect

    int pselect(int maxfd1, fd_set *readfds, fd_set *writefds, fd_set exceptfds, const struct timespec *tsptr, const sigset_t *sigmask)
    

    与select不同的地方: pselect的等待时间设置结构为timespec, 且被调整为const, pselect还可以设置进程信号屏蔽

    poll

    与select作用相同, 实现不同
    poll第一个参数是一个fd数组集合, 每个fd关联一个pollfd结构, 该结构说明fd的关心状态是读还是写
    poll第二个参数是第一个参数中fd的个数
    poll第三个参数是等待时间, -1表示无限等待, 0表示不等待, 其它正值表示可等待的毫秒数

    int poll(struct pollfd fdarray[], unsigned int nfds, int timeout);
    struct pollfd{
        int fd;
        short events; //常用的读POLLIN/写POLLOUT
        short revents; //可忽略设置
    }
    
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/time.h>
    #include <sys/poll.h>
     
    int main(int argc, char *argv[]){
        char buf[1024];
        int fd;
        int i;
        struct pollfd pfds[2];
        fd=open(argv[1],O_RDONLY);
     
        while(1){
            pfds[0].fd=STDIN_FILENO;
            pfds[0].events=POLLIN;
     
            pfds[1].fd=fd;
            pfds[1].events=POLLIN;
     
            poll(pfds,2,-1);
            if(pfds[0].revents & POLLIN){
                i=read(STDIN_FILENO,buf,1024);
                write(STDOUT_FILENO,buf,i);
            }
     
            if(pfds[1].revents & POLLIN){
                i=read(fd,buf,10);
                write(STDOUT_FILENO,buf,i);
            }
        }
    }
    
  • 相关阅读:
    线程中断总结
    线程的基本协作和生产者消费者
    synchronized总结
    线程基础总结
    Java集合总结(三):堆与优先级队列
    Java集合总结(二):Map和Set
    Java集合总结(一):列表和队列
    java枚举类型总结
    java 内部类简单总结
    java Integer包装类装箱的一个细节
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5701324.html
Copyright © 2011-2022 走看看