关于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进行判断,影响性能。

原文地址:https://www.cnblogs.com/xiangyu01/p/3308021.html