下面我们说一下select、pselect和poll函数的具体用法及区别
• select
对于fd_set数据类型,唯一可以进行的处理是:分配一个这种类型的变量,将这种类型的一个变量值赋给同类型的另一个变量,或对这种类型的变量使用下列4个函数中的一个:
具体使用方法;
需要注意:
【1】函数的实现里面返回的话会修改timeval中的值,linux中会用剩余的时间值更新struct timeval结构,所以每次调用select都需要重新设置timeval的值。
【2】文件描述符集合也一样,select返回的话(无论是何种方式返回)会将没准备好的文件描述符从集合中清空,所以每次调用select函数前需要设置其文件描述符集合。
【3】当设置超时检测时,超时了的话select返回0,如果在等待的过程中被信号中断,那么其出错返回-1,并且设置相应的errno而EINTR。
【4】第一个参数为大的文件描述符值(三个文件描述符集中大值)加1。因为需要的参数是文件描述符的个数,而它是从0开始编号的。
【5】所谓“准备好”,也就是说对其进行read或write操作不会阻塞,则认为其实准备好的。
【6】当socket进入select时,另一个线程调用close关掉该socket,select不能退出等待并返回。
这个行为是未指定的,man文档中有说明
Multithreaded applications
If a file descriptor being monitored by select() is closed in another thread, the result is unspecified. On some UNIX systems, select() unblocks and
returns, with an indication that the file descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another the file descriptor
reopened between the time select() returned and the I/O operations was performed). On Linux (and some other systems), closing the file descriptor in
another thread has no effect on select(). In summary, any application that relies on a particular behavior in this scenario must be considered buggy.
• pselect
除下列几点,select与pselect相同
1、select的超时值用timaval结构,成员为秒和微秒;pselect的超时值用timespec结构,成员为秒和纳秒。
2、pselect的超时值被声明为const,这保证了调用pselect返回后不会改变其设定的超时值。
3、pselect的后一个参数可以指定一个信号屏蔽字。如果填NULL则在于信号有关的方面select和pselect是相同的。否则,sigmask指向一有效的信号屏蔽字,在调用pselect时,以原子操作的方式安装该信号屏蔽字,在返回时,恢复以前的信号屏蔽字。
• poll
具体使用方法:
poll不会为每个条件(可读、可写和异常条件)构造一个描述符集,而是构造一个pollfd结构的数组,而每个数组元素指定一个描述符编号以及我们对该描述符该兴趣的条件。
应为每个数组元素的events成员设置为下图中值的一个或几个,通过这些值告诉内核我们关心的是每个描述符的哪些事件。返回时,revents成员由内核设置,用于说明每个描述符发生了哪些事件。注意,poll没有更改events成员,这与select不同。
第三个参数的精度为毫秒,如果系统不提供毫秒级精度,则timeout值取整到近的支持值。