Bootstrap

select、poll、epoll函数详解

1.select 函数

该函数允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历一段指定的时间后才唤醒它。

1.1 概念

#include <select.h>
int select(int maxfdp1,  fd_set *readset,  fd_set *writeset,  
		   	fd_set *exceptset,  const struct timeval *timeout);

返回值:若有就绪描述符则为其数目,若超时则返回0,出错返回-1。
参数1: maxfdp1 指定待测试的描述符个数。 它的值是待测试的最大描述符加1,描述符从0开始。//命名的来由max fd plus 1,最大的fd+1
PS:存在这个参数纯粹是为了效率原因。每个fd_set都有表示大量描述符(典型值1024)的空间,但是一个普通的进程所用的数量确少很多。所以内核通过在进程和内核之间不复制描述符集中不必要的部分,从而不测试总为0的那些位来提高效率。
参数2: readset、writeset、exceptset 是指定让内核测试读、写、异常条件的描述符,如果对其中某个描述符不感兴趣可以设为空指针。
参数3: timeout 告知内核等待所指定描述符中的任何一个就绪可花多长时间。

struct timeval {
long tv_sec; /* seconds /
long tv_usec; /
microseconds */
} 该参数有三种可能:
1.永远等待下去:仅在有一个描述符准备好I/O时才返回,将其设为空指针;
2.等待一段固定时间:在有一个描述符准备好I/O时返回,但是不超过由该参数所指向的timeval结构中指定的秒数和微秒数;
3.根本不等待:检查描述符后立即返回,这就是轮询。为此,该参数必须指向一个timeval结构,但是其中的值必须设置为0。

1.2 描述符集

主要关注的是中间的三个参数,这里引入一个问题:怎么给它们仨指定一个或者多个描述符值?
select使用描述符集,通常是一个整数数组,其中每个整数中的每一位对应一个描述符。

举例说明:

使用32位整数,则数组第一个元素a[0]对应描述符0~31位,第二个元素a[1]对应描述符32 ~ 63位,以此类推……

具体的代码实现:
使用以下select提供的四个函数。

void FD_ZERO(fd_set *fdset);	//clear all bits in fdset ---清空fdset中的所有位
void FD_SET(int fd, fd_set *fdset);	//turn on the bit for fd in fdset ---在fdset中打开fd的对应位 
void FD_CLR(fd_set *fdset

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;