使用select+blocked socketpair模拟新版本内核才支持的nonblock socketpair |
发布: 2011-01-12 23:41 |
话说服务器系统太老真是不爽,现在使用大多数服务器系统都是debian5,而这个系统的内核版本2.6.26,glibc 2.7,一些很方便的函数像pipe2, nonblock socketpair恰好从内核2.6.27开始支持,需要用到这个功能,又不能不兼容这要部署的服务器版本,真郁闷。 现在要实现一个线程间的非阻塞通信,本来在使用的桌面系统上找到pipe2,从man手册上看完全符合使用要求,没想到在服务器上先测试了一下,直接没有这个函数,查了一下手册,这个原来从glibc 2.9加入的。 后面又找到了socketpair函数,这个也非常方便,这回还先看了一下服务器,有这个函数,可谁知系统又没有定义一个叫SOCK_NONBLOCK的宏,无法使用它的nonblock模式。 苦苦思索一番,找到一种解决办法,完整的方法是, 使用#ifdef编译指令,加select block模式的socketpair,这样即能在新系统上使用,也可在比较旧的系统上运行。 大概步骤如下, 首先使用socketpair创建一对已经连接的socket, #ifdef HAVE_SOCK_NONBLOCK socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, sv); #else socketpair(AF_LOCAL, SOCK_STREAM, 0, sv); #endif 现在读取, #ifdef HAVE_SOCK_NONBLOCK // here will not block of couse read(sv[0], rbuf, 1000); #else fd_set rd_fds; FD_ZERO(&rd_fds); struct timeval timev; timev.tv_sec = 0; timev.tv_usec = 1000; // 1ms FD_SET(sv[0], &rd_fds); if (select(sv[0]+1, &rd_fds, 0, 0, &timev) == 1) { assert(FD_ISSET(sv[0], &rd_fds); // has data, can read, so here also will not be block read(sv[0], rbuf, 1000); } 如果把timev.tv_use设置为0,则会立即返回,就像真正的读取一个nonblock socket一样,这里还可选择地block几个ms时间,也算非常灵活。 不过现在debian6快发了,以后新安装的服务器应试能用上debian6了,这些新功能就直接可用了。 |
原文: http://qtchina.tk/?q=node/546 |
Powered by zexport
|