系统提供select函数来实现多路复用输入/输出模型。


作用:select系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变。


函数原型:

I/O多路转接之 select_第1张图片

参数说明:

int nfds:需要监视的最大文件描述符值+1;

fd_set *readfds & *writefds & *exceptfds:指向文件描述符的指针;这三个描述符集说明了我们关心的可读、可写或处于异常条件的各个描述符;

struct timeval *timeout:需要等待的时间,为NULL,则select一直阻塞,知道某个文件描述符发生了事件,为0,仅仅检测描述集合的状态,立即返回,不等待外部事件的发生。

struct timeval{
    long tv_sec;        /* seconds */
    long tv_usec;       /* microseconds */
};

函数返回值:

成功:返回就绪描述符的个数,0表示timeout结束,没有描述符完成就绪;

失败:-1,此时状态描述参数和timeout都变成不可预测的,错误信息存在errno中。



对fd_set数据类型可以进行的处理是:

分配一个这种类型的变量;

将这种类型的一个变量值赋予同类型的另一个变量;或对于这种类型的变量使用下列四个函数中的一个。

void FD_CLR(int fd, fd_set *set);    //清除描述词组set中相关的fd的位
int FD_ISSET(int fd, fd_set *set);   //测试描述词组set中相关fd的位是否为真
void FD_SET(int fd, fd_set *set);    //设置描述词组set中相关的fd位
void FD_ZERO(fd_set *set);           //清除描述词组set的全部位

select的缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持的文件描述符数量太小了,默认是1024

select的优点:

(1)相较于之前多线程的方法,使用select不用创建线程,更方便

(2)select目前几乎在所有的平台上都支持,其良好跨平台支持也是它的一个优点