asterisk中自定义fd_set扩展select能处理的文件描述符个数的研究 |
发布: 2011-03-30 22:44 |
asterisk中自定义fd_set与FD_ZERO,FD_SET几个量扩展select能处理的文件描述符个数的研究 在asterisk中,仍旧使用select处理socket文件描述符的读写事件驱动,虽然有点老套,但这种方式的移植性更好,现在几乎所有的平台都支持这个函数。如果使用一些特定平台的功能,像linux的epoll或者BSD的kqueue,还有solaris的什么 方式,都需要做一个核心兼容这几种不同操作系统上的方式。 由于进程可使用的文件描述符可使用ulimit -n 32768来设置,而系统自带的FD_SETSIZE却是固定的值,在/usr/include/bits/typesizes.h,目前我在使用的linux服务器系统上,这个值都定义为1024。对于像asterisk这样的服务,当然这个值太小了,不足以完全发挥asterisk和服务器硬件的功能。 现在我们研究下它如何,在include/asterisk/select.h文件开头,有这么一个定义, typedef struct { TYPEOF_FD_SET_FDS_BITS fds_bits[4096 / SIZEOF_FD_SET_FDS_BITS]; /* 32768 bits */ } ast_fdset; 这里有两个宏TYPEOF_FD_SET_FDS_BITS, SIZEOF_FD_SET_FDS_BITS,都是在configure一步检测出来的,这个检测结果,必须保证sizeof(ast_fdset)=32768/8,也就是asterisk希望select能支持32768个文件描述符。 系统自的/usr/include/sys/select.h中定义的fd_set如下, typedef long int __fd_mask; #define __NFDBITS (8 * sizeof (__fd_mask)) #define __FDELT(d) ((d) / __NFDBITS) #define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) typedef struct { __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS]; # define __FDS_BITS(set) ((set)->__fds_bits) } fd_set; 根据这几个宏的值,可以计算出系统自带的fd_set正好是1024位。 现在来configure文件看是怎么检测出来的这两上宏的值,因为在不同的CPU上,不同的系统上,不同的架构上,这两个值都有所不同,需要十分小心,否则有可能导致在使用FD_SET,FD_ISSET是,可能覆盖某些fd使用的位,或者检测到错误的文件描述符状态。 首先计算SIZEOF_FD_SET_FDS_BITS的值,方法如下, fd_set foo; SIZEOF_FD_SET_FDS_BITS = sizeof(foo.__fds_bits[0]); 然后再推导TYPEOF_FD_SET_FDS_BITS if (sizeof(long) == SIZEOF_FD_SET_FDS_BITS) 则#define TYPEOF_FD_SET_FDS_BITS long if (sizeof(long long) == SIZEOF_FD_SET_FDS_BITS) 则#define TYPEOF_FD_SET_FDS_BITS long long ...... 就这样实际上根据所要的size逆向推导出单位来罢了。 实际测试,在x86和amd这种little-endian的CPU架构上, 这几个固定的,例如,在x86 Linux系统上, SIZEOF_FD_SET_FDS_BITS = 4 = sizeof(long) #define TYPEOF_FD_SET_FDS_BITS long 则ast_fdset定义在预处理时生成这么一条语句, typedef struct { long fds_bits[4096 / 4]; /* 32768 bits */ } ast_fdset; 在x86_64 Linux系统上, SIZEOF_FD_SET_FDS_BITS = 8 = sizeof(long) #define TYPEOF_FD_SET_FDS_BITS long 则ast_fdset定义在预处理时生成这么一条语句, typedef struct { long fds_bits[4096 / 8]; /* 32768 bits */ } ast_fdset; 这样有了一个固定的能实现asterisk需要的32768位数据结构,再结合asterisk中自定义的FD_ZERO, FD_SET, FD_CLR, FD_ISSET宏,在其内部使用select时,就能够处理32768个文件描述符了,达到扩展系统select所能支持的功能的目的。 当然,在自己的项目中,也可以使用这种方式改进系统负载容量。 不过,如果可能,还是使用先进一些的epoll,kqueue这些,因为select在处理这么大的文件描述符时,效率上相比前者还是小一点。 |
原文: http://qtchina.tk/?q=node/564 |
Powered by zexport
|