select 1024限制

文章主要来自彻底解释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 +