Linux下select调用引发的血案

Select函数使用简单,其工作原理大家通常也知道,但是在实际的使用过程中可能并没有严格遵守,而且确实也比较难以完全遵守,除非不使用它。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Select采用一个bit表,每个fd对应表中的一个bit位,宏FD_SETSIZE为表的大小,添加到fd_set中的fd值必须小于FD_SETSIZE,否则就会越界,假设有如下一段代码:

fd_set  readfds;

FD_ZERO(&readfds);

FD_SET(fd,  &readfds);

那么,这里的fd必须满足:fd 

通过ulimit命令和setrlimit函数来修改进程内句柄数的限制,并不会影响FD_SETSIZE的值,所以即使通过ulimit命令或setrlimit函数将进程允许的句柄改成很大了,但如果FD_SETSIZE值没有修改,则仍可能发生crash。

在什么情况下最容易遇到这个问题?

较容易发生在服务端程序中,因为服务端程序同一时刻的连接数很容易超过默认的FD_SETSIZE值,而服务端的代码可能是使用epoll使用的,所以它本身并不会存在问题,但是程序中可能还有个客户端,比如使用了select来实现超时连接,这个时候问题就来了,当连接数超过FD_SETSIZE时,超时连接处的select调用就发生了越界,进程就会在某个可能完全不相干的地方crash,要定位这个问题的成本是很高的,不具备一定经验,很难在短时间内定位出来。

如何去避免这个问题了?那就是尽量不使用select,而应当使用更安全的poll函数来替代,因为poll使用的数组是调用者自己维护的,完全可以保证不越界。

上一篇:2019阿里云服务器双11活动1折起购,现在可以购买啦!


下一篇:罗鑫:让精准的制冷驱动机房高效运行