fd_set结构体
fd_set的定义
typedef struct
{
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
} fd_set;
可简化为
typedef struct{
long int __fds_bits[1024/(8*sizeof(int long))];
};
即其中只有一个字段为__fds_bits,它的类型是long int的数组,数组元素个数为1024/(8本机long的字节数),
而(8本机long的字节数)是本机long占用的bit数,这样就保证了
__fds_bits的字节数必为1024(select可以监听的最大描述符数),而且用long存储
FD_SET宏
FD_SET宏
#define __FD_SET(d, set) \
((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))
其展开为
((void)((set)->__fds_bits)[((d)/8 * (int) sizeof (long int))] |= ((long int) (1UL << ((d) % (8 * (int) sizeof (long int))))))
其中的宏都可以在sys/select.h中找到
这个宏操作如下:
- 获取到传入fd_set指针的__fds_bits的第(d/当前主机long的字节数)个元素,也就是第d个bit所在的那个long元素
- 计算出将1UL(即longint的1)左移(d%当前主机long的字节数)
- 最后将第一步的数字与第二步的数字进行或操作,得到结果
比如在64位机器上FG_SET(rset, 73)
假设原来rset的第二个long元素是
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
- 73/64 = 第二个元素
- 73/64 = 1UL左移9位,得到
00000000 00000000 00000000 00000000 00000000 00000000 00000010 00000000 - 进行或操作,得到
00000000 00000000 00000000 00000000 00000000 00000000 00000010 00000000
这样就可以把第73位置的bit置为1(注意不是从低内存到高内存直接数的73)
对结果进行打印
运行程序
#include "stdio.h"
#include "sys/select.h"
int main(){
fd_set rset;
FD_ZERO(&rset);
// 打印下此时的rset
int fortimes = 1024/(int)(8*sizeof(long int));
printf("now FD_ZERO the fd_set:\n");
for (int i=0;i<fortimes;i++){
printf("rset [%d] %lu\n", i, rset.__fds_bits[i]);
}
// 使用FD_SET
FD_SET(0, &rset);
FD_SET(73, &rset);
FD_SET(1023, &rset);
// 打印下此时的rset
printf("now r_set after fd_set:\n");
for (int i=0;i<fortimes;i++){
printf("rset [%d] %lu\n", i, rset.__fds_bits[i]);
}
}
得到结果
结果分析
1.在内存中,一个字节中bit的保存是按我们可读的方式进行保存的
如 1UL在小端机器保存为
00000001 00000000 00000000 00000000
我们可以通过这个程序证实
#include <stdio.h>
union ic{
int a;
char b[4];
};
int main(){
union ic ic_obj;
ic_obj.a = 1;
for (int i=0;i<4;i++){
printf("%d\n", ic_obj.b[i]);
}
// 对int左移
ic_obj.b[0]<<=1;
for (int i=0;i<4;i++){
printf("%d\n", ic_obj.b[i]);
}
}
2.对于与操作,无论大端序还是小端序,最后或出来的结果是一样的,因为一个机器的字节读取顺序是不变的.
比如int类型的1或上int类型的2
对于大端序机器
00000000 00000000 00000000 00000001 或
00000000 00000000 00000000 00000010 得
00000000 00000000 00000000 00000011 机器转为int是3
对于小端序机器
00000001 00000000 00000000 00000000 或
00000010 00000000 00000000 00000000 得
00000011 00000000 00000000 00000000 机器转int也是3