• 关于select函数


        向来是一个比较懒惰的人,但是突然觉得应该整理一些东西,写写博客什么的。只是不知道从何处开始。昨天在看松本行弘的《代码的未来》中关于C10K问题的分析,其中涉及到了slecet函数。select函数之前只是知道,没怎么了解。然后看了一下,整理如下:

    应用场景:

    在很多时候,一个进程要处理很多个文件的读写(包括socket文件),然后对于这些文件的访问经常会因为各种原因导致进程被阻塞。为了使进程不被阻塞在单个文件的访问上,可以使用select函数。首先将多个需要访问的文件描述符设置到相关的fd_set,并设置相应的超时时间,然后调用select函数当这些文件中,有文件可用或者超时时间已到后,select函数就会返回。

    头文件:

    #include <sys/select.h>

    函数原型:

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

    readfds为读文件描述符集的指针,用于监控哪些文件描述符处于可读状态,writefds为写文件描述符集的指针,exceptfds为异常的文件描述符集的指针,以上三个集合中,对于不需要监视的,可以设置为NULL。fd_set本质上是一个bit 数组。对于根据相应的文件描述符映射至相对应的位置。

    timeout为超时时间,如果timeout中对应的秒数和微妙数设置为0,则select不会休眠,立即返回,如果timeout设置为NULL,则会一直休眠,直到有资源处于非阻塞状态(可读、可写或者有异常)。

    需要注意的是linux中,每次调用select都会修改timeout值,因此每次调用都要重新设置timeout的值

    nfds为readfds、writefds和exceptfds三者中描述符最大值加1.

    返回值 为int型。如果为0,则超时返回。如果-1,则有错误,并设置errno,如果大于0,则代表处于可用状态的描述符的数量。

    对于fd_set,对应有四个宏,用于进行相关的控制:

    FD_ZERO(fd_set *fdset):清空fdset中的所有描述符。
    FD_SET(int fd, fd_set *fdset):添加单个描述符至fdset中。
    FD_CLR(int fd, fd_set *fdset):清楚fdset中某个描述符。
    FD_ISSET(int fd, fd_set *fdset):检查某个描述符是否在fdset中。
    值得注意的是:对于调用select返回后,如果想确定某个描述符是否在fdset中,需要使用FD_ISSET判断。由于调用可能会修改,因此每次调用select之前,都应重新设置所要监控的描述符集合。
     
    下面是一段示例代码:
     1 #include <sys/types.h>
     2 #include <unistd.h>
     3 #include <sys/time.h>
     4 #include <stdlib.h>
     5 #include <sys/select.h>
     6 
     7 int main(int argc, char* argv[])
     8 {
     9     char buf[1000];
    10     int32_t reallen;
    11     struct timeval timeout;
    12     fd_set readfds;
    13     int32_t ret;
    14     while(1)
    15     {
    16         FD_ZERO(&readfds);
    17         FD_SET(0, &readfds);
    18         timeout.tv_sec = 1;
    19         timeout.tv_usec = 0;
    20         ret = select(1, &readfds, NULL, NULL, &timeout);
    21         if (-1 == ret)
    22         {
    23             return -1;
    24         }
    25         if(FD_ISSET(0, &readfds))
    26         {
    27             reallen = read(0, buf, 1000);
    28             write(1, buf, reallen);
    29         }
    30     }
    31     return 0;
    32 }

    select常用于socket连接的控制。其缺点主要有:

    1.受制于每个进程管理描述符的数量受制于FD_SETSIZE,一般为1024,因此每次能够控制的连接数量有限

    2.由于fd_set在select中会被修改,每次调用需要对所希望监控的描述符集合中的描述符依次调用FD_ISSET进行判断,影响性能。

  • 相关阅读:
    M-CloneG-DFS-BFS-图
    M-WordB-BFS-DP
    Reverse Linked List II
    OpenCV 第二课 认识图像的存储结构
    Surf特征提取分析
    OpenCV 第一课(安装与配置)
    简单验证码识别(matlab)
    matlab中各种高斯相关函数
    SIFT特征提取分析
    斑点检测(LoG,DoG)(下)
  • 原文地址:https://www.cnblogs.com/xiangyu01/p/3308021.html
Copyright © 2020-2023  润新知