select使用涉及四个宏,通过glibc把他们实现找出来说一说:
typedef long int __fd_mask;
#define __NFDBITS (8 * (int) sizeof (__fd_mask))//32位,就是32,64位这就是64,后面以32位为例;
#define __FD_ELT(d) ((d) / __NFDBITS)//对应的fd除以32的商
#define __FD_MASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))//将1向左移动fd除以32的余数(假设余数为a)个 位数;即,将第a位置1;
综上,假如fd为5,则__FD_ELT为0;__FD_MASK为5,就是把1左移5位,即第(fd)5位置1(从0开始数);
假如fd为33,则__FD_ELT为1;__FD_MASK为1,就是把1左移1位,即第(fd)32*1+1位置1;
/* fd_set for select and pselect. */ fd_set结构体的定义:
typedef struct
{
/* XPG4.2 requires this member name. Otherwise avoid the name
from the global namespace. */
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];//包含32个long整型数的数组;
# define __FDS_BITS(set) ((set)->fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
} fd_set;
/* Maximum number of file descriptors in `fd_set'. */
#define FD_SETSIZE __FD_SETSIZE //内核中定义的,一般为1024
#ifdef __USE_MISC
/* Sometimes the fd_set member is assumed to have this type. */
typedef __fd_mask fd_mask;
/* Number of bits per word of `fd_set' (some code assumes this is 32). */
# define NFDBITS __NFDBITS
#endif
/* Access macros for `fd_set'. */
#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp)
#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp)
#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp)
#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp)
#define __FD_SET(d, set) \
((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))
以下几个类似,就说明这一个,__FD_SET的作用就是用个32位整型数的每一位代表一个需要监控的fd;fd_set结构是一个包含有32个整型数的数组,所以可以加入fd0-1023用于监控;同样接上,说明他的具体实现:
假如fd为5,则__FD_ELT为0,就表示数组第1个元素(数组下标从0开始);__FD_MASK为5,就是把1左移5位,即把第1个元素第5位置1;
假如fd为33,则__FD_ELT为1,就表示数组第2个元素;__FD_MASK为1,就是把1左移1位,即把第2个整型数的第1为置1;
综上,可以理解要监控fd,就是将1024个位的相应fd位置1,只是内核将1024分割为32份用一个整型数表示了;
#define __FD_CLR(d, set) \
((void) (__FDS_BITS (set)[__FD_ELT (d)] &= ~__FD_MASK (d)))
#define __FD_ISSET(d, set) \
((__FDS_BITS (set)[__FD_ELT (d)] & __FD_MASK (d)) != 0)