select系统调用可以实现一个进程同时监听多个文件描述符的状态变化,但select 对于一个进程所打开的FD是有一定限制的,最大的文件描述符需小于1024,即文件描述符的范围【0-1023】。
select支持的描述符为什么会有限制呢?能不能修改呢?
select支持的文件描述符是在#include <sys/select.h>的宏定义定死的,所以有局限性,但并不是说文件描述符一定就不能超过1024,因为宏定义的值是可以人为修改的,但比较麻烦,修改宏定义的值,需要重新编译内核。但为什么文件描述符要限定在1024呢?而不是其他的值。
从两个方面分析
1、一个进程所打开的最大文件描述符也是小于1024,设置为小于1024是比较合理的
2、select采用的是轮询处理的方式,处理过多的描述符开销比较大,会大大降低性能。
define FD_SETSIZE 1024
文件描述符是如何存储的?
select之文件描述符是由d_set类型管理的,d_set类型实际是是一个unsigned long型、大小为32的数组。一共有32位字节、32*32=1024位(bit),每一位都可以表示一个描述符,共支持1023个文件描述符。比如:将文件描述符4加载到readfds中,实际4文件描述符的存储方式就是fds_bits[0] = 0b0000000000001000。
fd_set readfds;
FD_SET(4,readfds);
fds_bits[0] = 0b0000000000001000
select之文件描述符的组织实现代码:
define FD_SETSIZE 1024
typedef unsigned long fd_mask;
#define NBBY 8 /* number of bits in a byte */
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
typedef struct fd_set
{
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} fd_set;
#define _fdset_mask(n) ((fd_mask)1 << ((n) % NFDBITS))
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= _fdset_mask(n))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~_fdset_mask(n))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & _fdset_mask(n))
#define FD_COPY(f, t) bcopy(f, t, sizeof(*(f)))
#define FD_ZERO(p) bzero(p, sizeof(*(p)))
测试select支持的最大描述符例程:
#include<stdio.h>
#include <sys/select.h>
int main()
{
printf("size of fd_set = %d\n",sizeof(fd_set)*8);
return 0;
}
int main()
{
printf("size of fd_set = %d\n",sizeof(fd_set)*8);
return 0;
}
注:一般select支持的最大描述符例程都是1024.