今天遇到一个诡异的问题,一个我们常用的通讯框架不能服务了,每个服务线程干了一次活儿就退出了。问题出在框架里头的select系统调用上。先说前言…
框架中使用了pipe()创建了一个fd pair,对一个管道进行读和写,作为网络线程和工作线程的通讯方式。当有一个请求到来时,网络线程会在写fd上写一个字节,而工作线程则在读fd上select,读到东西了说明有请求分发给自己,则进行相关操作。问题就在这个select上!
1
2
3
| FD_ZERO(&read_set);
FD_SET(fd, &read_set);
int ret = select(fd + 1, read_set, NULL, NULL, timeout); |
运行时,select返回值ret不为零,但是使用FD_ISSET(fd, &read_set)检查的结果却是false!顿时觉得怎么会有尼玛这么坑爹的事情!
后来@joke提醒说,select的fd最大1024。检查一下,果然超过了,因为这个服务却是打开了这么多句柄,然后再启动通讯框架的时候,fd数已经超过1024了。
唉唉,吃一堑长一智啊!以后在使用select的时候一定要注意这个限制!
其一,文件句柄较多的程序在使用select的时候需要小心,此时可以用epoll代替,效率也会有所提升。其二,线程间通讯还是blockingqueue这种方式比较简单直接,使用select这样的事件触发机制固然高效,但一般的场合线程间的通讯还不至于成为瓶颈的。
p.s. 原文地址:http://chunyemen.org/archives/585, 欢迎访问纯爷们的小生活!