zoukankan      html  css  js  c++  java
  • I/O多路复用select()系统调用

    select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()就返回。

       1: #include <sys/select.h>
       2: #include <sys/time.h>
       3:  
       4: int select(int maxfd, 
       5:     fd_set *readfds,     
       6:     fd_set *writefds,
       7:     fe_set *exceptfds,
       8:     const struct timeval *timeout);
       9:  

    select的第一个参数是文件描述符集中要被检测的比特数,这个值必须至少比待检测的最大文件描述符大1;参数readfds指定了被读监控的文件描述符集;参数writefds指定了被写监控的文件描述符集;而参数exceptfds指定了被例外条件监控的文件描述符集。参数timeout起了定时器的作用:到了指定的时间,无论是否有设备准备好,都返回调用。

    timeval的结构定义如下:
    struct timeval{
        long tv_sec; //表示几秒
        long tv_usec; //表示几微妙
    }

    timeout取不同的值,该调用就表现不同的性质:

    1.timeout为0,调用立即返回;
    2.timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;
    3.timeout为正整数,就是一般的定时器。

    select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。select的返回值有如下情况:

    1.正常情况下返回就绪的文件描述符个数;
    2.经过了timeout时长后仍无设备准备好,返回值为0;
    3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
    4.如果出错,返回-1并设置相应的errno。

    系统提供了4个宏对描述符集进行操作:

       1: #include <sys/select.h>
       2: #include <sys/time.h>
       3: void FD_SET(int fd, fd_set *fdset);
       4: void FD_CLR(int fd, fd_set *fdset);
       5: void FD_ISSET(int fd, fd_set *fdset);
       6: void FD_ZERO(fd_set *fdset);

    宏FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1),宏FD_CLR清除文件描述符集 fdset中对应于文件描述符fd的位(设置为0),宏FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。

    select的使用方法:

    1. 将要监控的文件添加到文件描述符集
    2. 调用Select开始监控
    3. 判断文件是否发生变化

    如下:

    FD_ZERO(&fds); //清空集合
    FD_SET(fd1,&fds); //设置描述符
    FD_SET(fd2,&fds); //设置描述符
    maxfdp=fd1+1; //描述符最大值加1,假设fd1>fd2
    switch(select(maxfdp,&fds,NULL,NULL,&timeout))
    case -1: exit(-1);break; //select错误,退出程序
    case 0:break;
    default:if(FD_ISSET(fd1,&fds)).... //测试fd1是否可读

    可运行源代码:

       1: /**
       2: * select()系统调用提供一种实现同步I/O多路复用机制
       3: **/
       4:  
       5: /**
       6: #include <unistd.h>
       7: #include <sys/time.h>
       8: #include <sys/types.h>
       9: 
      10: 
      11: int select (int n,
      12:             fd_set *readfds,
      13:             fd_set *writefds,
      14:             fd_set *exceptfds,
      15:             struct timeval *timeout);
      16:             
      17: FD_CLR(int fd, fd_set *set);
      18: FD_ISSET(int fd, fd_set *set);
      19: FD_SET(int fd, fd_set *set);
      20: FD_ZERO(fd_set *set);
      21: 
      22: **/
      23:  
      24: /** 
      25: timeval
      26: #include <sys/time.h>
      27: struct timeval {
      28: long tv_sec; /* seconds 
      29: long tv_usec; /* microseconds 
      30: };
      31: 
      32: */
      33:  
      34:  
      35: /**
      36: * select()示例程序
      37: **/
      38:  
      39:  
      40: #include <stdio.h>
      41: #include <sys/time.h>
      42: #include <sys/types.h>
      43: #include <unistd.h>
      44: #include <fcntl.h>
      45:  
      46: #define TIMEOUT 5         /* select timeout in seconds */
      47: #define BUF_LEN 1024     /* read buffer in bytes */
      48:  
      49: int max(int a,int b)
      50: {
      51:     return (a>b)?a:b;
      52: }
      53:  
      54: int main (void)
      55: {    
      56:     struct timeval tv;
      57:     fd_set readfds;
      58:     int fd_open, fd ,maxfdp1;
      59:     int ret;
      60:     /* Wait on stdin for input. */
      61:  
      62:     fd_open = open("select_test.c" ,O_RDONLY);
      63:     FD_ZERO(&readfds);
      64:     FD_SET(STDIN_FILENO, &readfds);
      65:     FD_SET(fd_open, &readfds);
      66:     /* Wait up to five seconds. */
      67:     tv.tv_sec = TIMEOUT;
      68:     tv.tv_usec = 0;
      69:     
      70:     /* All right, now block! */
      71:     maxfdp1 = max(STDIN_FILENO  , fd_open) + 1;
      72:     ret = select(maxfdp1,&readfds,NULL,NULL,    &tv);
      73:  
      74:     if(ret == -1){
      75:         perror("select");
      76:         return 1;
      77:     }else if(!ret){
      78:         printf("%d seconds elapsed.\n", TIMEOUT);
      79:         return 0;
      80:     }
      81:     
      82: /*
      83: * Is our file descriptor ready to read?
      84: * (It must be, as it was the only fd that
      85: * we provided and the call returned
      86: * nonzero, but we will humor ourselves.)
      87: */
      88:  
      89:  
      90:     if (FD_ISSET(STDIN_FILENO, &readfds)){
      91:         char buf[BUF_LEN+1];
      92:         int len;
      93:         
      94:         /* guaranteed to not block */
      95:         len = read (STDIN_FILENO, buf, BUF_LEN);
      96:         if (len == -1){
      97:             perror("read");
      98:         //    return 1;
      99:         }
     100:         if (len){
     101:             buf[len] = '\0';
     102:             printf("read: %s\n", buf);
     103:         }
     104:         //return 0;
     105:     }
     106:  
     107:     if (FD_ISSET(fd_open, &readfds)){
     108:         char buf[BUF_LEN+1];
     109:         int len;
     110:         
     111:         /* guaranteed to not block */
     112:         len = read (fd_open, buf, BUF_LEN);
     113:         if (len == -1){
     114:             perror("read");
     115:         //    return 1;
     116:         }
     117:         if (len){
     118:             buf[len] = '\0';
     119:             printf("read: %s\n", buf);
     120:         }
     121:         //    return 0;
     122:     }
     123:  
     124:     
     125:     fprintf (stderr, "This should not happen!\n");
     126:     return 1;
     127: }
     128:  
     129:  

    GCC编译通过,可以自行测试运行,本程序测试了两个描述符,一个标准输入,一个是文件描述符。

  • 相关阅读:
    数据库更改自增和主键
    修改MySQL的默认数据存储引擎
    tomcat密码的坑
    通过System.getProperties()获取系统参数
    Java语言开发的,直接解压即可使用软件
    一个javascript面试题
    为什么学习差
    IDEA设置
    java关键字
    IDEA快捷键
  • 原文地址:https://www.cnblogs.com/xuddong/p/3075861.html
Copyright © 2011-2022 走看看