引言:
多路复用模型是五种常见I/O模型之一,使用 select/poll 实现的多路复用 I/O 模型是使用最为广泛的事件驱动 I/O 模型,但是由于 select/poll 实现的不完善,这种 I/O 模型的缺陷也逐渐暴露出来。
select 的工作过程如下:
- 调用者初始化自己关心的可读、可写和异常的描述符集。比如对希望在
可读时接到通知的描述符,就将其加入 readfds。描述符集的结构是
fd_set,在 Linux 中它有如下定义:
typedef struct
{
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
} fd_set;
所谓将描述符加入描述符集就是将描述符所对应的位置位。
- 调用者将描述符集传给 select,如果对某一类描述符不感兴趣,将 NULL传给对应的描述符指针,select函数原型如下:
int select(int max_fd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
第一个参数 max_fd设置为三个描述符集中被置 1 的位中最大的一个的数组索引加 1。
最后一个参数表示当经过一定的时间后,如果没有描述符准备好,select 超时返回。如果需要 select 无限期等待,也传 NULL 即可。
中间三个参数就是我们关心的文件描述符集readset、writeset、exceptset,不关心的我们可以设置为NULL
select函数的返回值:
成功就绪描述符的数目
超时时返