select 效率问题大家都知道,但是 select 正确性问题,很少有人讨论,特地点出来。
linux 下 fd_set 是个 1024 位的位图,每个位代表一个 fd 的值,这也是效率低的原因。
性能问题且不提,正确性问题则更值得重视。
因为这是一个 1024 位的位图,因此当进程内的 fd 值 >= 1024 时,就会越界,可能会造成崩溃。对于服务器程序,fd >= 1024 很容易达到,只要连接数 + 打开的文件数足够大即可发生。
这么多连接的时候,估计没人在用 select 等待所有连接,但是通常用 select 实现的 wait_readable 就容易被忽视了。
比如这个实现:
inline static int wait_readable(int filedes, struct timeval *timeout)
{
fd_set rset;
FD_ZERO(&rset);
FD_SET(filedes, &rset);
return select(filedes + 1, &rset, NULL, NULL, timeout);
}
这 样的代码如果在库里使用,安全就没有保证。
这种用途,建议改用 poll 调用。