FD_SETSIZE和select(转载)

之前有一个刷 squid 的 purge 程序,大约要刷20台机器,当时采用多线程 + 非阻塞(select)模式,发现一个很奇怪的问题,当线程数多于52时,select 经常返回出错,
22 Invalid argument
Bad file descriptor
不得其解。

最近温习unip,读到select时,终于明白了。select 最多可以检查FD_SETSIZE(通常是1024)个描述符。结合fd_set 的实现(FD_SET 在 描述符(大小)对应的位置1),明白了,select 可以检查的描述符最大为FD_SETSIZE,而不是最多FD_SETSIZE个描述符(虽然通常是这样,因为unix总是先用最小的)。

在 purge 程序中,20台机器,52个线程 52 × 20 = 1020,线程多于52,肯定就有描述符大于1024。虽然每个select 检查的描述符个数小于1024,但是整个进程的描述符个数已经大于1024(个数大于1024,那么描述符的大小肯定大于1024)。对于大于1024的描述符,FD_SET的处理方式是拿描述符对1024取模。假设描述符为1029,FD_SET(1029,&set)相当于FD_SET(5,&set),而 5 可能不是一个有效的描述符,当 select 去检查描述符 5 时,因为 5 不是有效的描述符,所以出 Invalid argument 或 Bad file descriptor 就比较合理了。

select 的正确语义应该时,整个进程中,select 最多可以检查1024个描述符,而不管用了多少 select 函数。更精确的描述是,select 只能检查描述符大小小于1024的描述符,当描述符个数大约1024,描述符大小就肯定大于1024。

可以epoll,或者poll解决这个问题,用libevent库(libevent,用选择平台上最好的I/O多路转接函数),更好。

http://gcoder.blogbus.com/logs/51716260.html

突破select的FD_SETSIZE限制

http://www.cnblogs.com/hnrainll/archive/2011/12/13/2285973.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值