在linux实现中,首先为长整形声明别名__fd_mask
1 | typedef long int __fd_mask; |
定义系统长整形的位数__NFDBITS
1 | #define __NFDBITS ( 8 *( int )sizeof(__fd_mask)) |
定义fd_set结构能包含的描述符的最大个数__FD_SETSIZE
1 | #define __FD_SETSIZE 1024 |
然后就可以定义fd_set结构了
1 2 3 4 5 6 7 8 9 10 | typedef struct { #ifdef __USE_XOPEN __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; #define __FDS_BITS( set ) ((s et )->fds_bits) # else __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS]; #define __FDS_BITS( set ) (( set )->__fds_bits) #endif } fd_set ; |
由数组fds_bits[__FD_SETSIZE / __NFDBITS]的定义可以看出,它将数组fds_bits的长度从通常的__FD_SETSIZE缩短到了(__FD_SETSIZE / __NFDBITS),数组的元素的每个位表示一个描述符,那么一个元素就可以表示__NFDBITS个描述符,整个数组就可以表示(__FD_SETSIZE / __NFDBITS)* __NFDBITS = __FD_SETSIZE个描述符了。
__FDS_BITS的定义是为了便于直接引用该结构中的fds_bits,而不用关心内部具体的定义。
关于FD_宏的定义
1 2 3 4 | #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) |
对于__FD_SET宏的定义
1 2 | #define __FD_SET(d, set ) \ (( void ) (__FDS_BITS( set )[__FD_ELT(d)] |= __FD_MASK(d))) |
__FDS_BITS(set)引用了结构set内部的的相应的数组名,如((set) -> fds_bits)
而其中的__FD_ELT的定义
1 | #define __FD_ELT(d) ((d) / __NFDBITS ) |
表示描述符d应该包含在数组fds_bits的第几个元素内;
__FD_MASK宏的定义
1 | #define __FD_MASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) |
表示描述符d在数组相应元素的第几位;
这样看来,在宏__FD_SET中,__FDS_BITS(set)[__FD_ELT(d)] |= __FD_MASK(d) 就把描述符d在结构set的内部数组fd_mask的相应的元素的相应位进行了设置。
对于其他的宏的具体定义如下,分析同上
1 2 3 4 5 6 7 8 9 10 11 | #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 ) #define __FD_ZERO( set ) \ do { unsigned int __i; fd_set * __arr = ( set ); for ( __i = 0 ; __i < sizeof(fd_set) / sizeof (__fd_mask); ++__i) __FDS_BITS (__arr)[__i] = 0 ; } while ( 0 ); |