文章主要来自彻底解释Linux select的1024限制(select真的受1024限制吗?不!),原作者通过源码和实验解释select真的是受1024限制吗,但是原作者的代码似乎有些问题(好像跑不通,但是思想表达的很明晰),这篇文章主要是对那篇文章的一个简单的解释,以及遇到的奇怪问题的记录。
一、源码
// include/uapi/linux/posix_types.h
#define __FD_SETSIZE 1024
typedef struct {
unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))];
} __kernel_fd_set;
这是linux源码,从源码上看确实限制为1024(看完源码真的以为是这里限制select为1024,但是那片文章的作者,给了新的解释,确实很有道理。)
二、FD_SET是否限制1024
首先作者分析FD_SET是否会对1024进行越界检查,或者限制在1024 bit。但是原作者的代码表述的逻辑没什么问题,似乎是g++编译过程中对内存分布作了一定的改变,导致原作值的代码无法复线结果,下面代码作了一点修改,可以得到原作者的结果。
// 原作者代码
#include
#include
int main(int argc, char **argv)
{
int i = 2000, j;
unsigned char gap = 0x12; // 该值作为锚点,被位运算覆盖。
fd_set readfds;
unsigned char *addr = ⪆
int sd[2500];
unsigned long dist;
unsigned total;
printf("gap value is :0x%x\n", gap);
// dist的含义就是readfds和附近gap之间的空间大小,即readfds最大的可用空间。
dist = (unsigned long)&gap - (unsigned long)&readfds;
FD_ZERO(&readfds);
// dist*8 + 1即让readfds越界1个bit。
// 由于gap为0x12,二进制10010,越界1个bit,可以预期FD_SET会置位0x12的最低位。
// 结果就是0x13
for (j = 0; j < dist*8 +