pselect函数是由POSIX发明的,如今有许多Unix变种支持他。
#include <sys/select.h>
#include<signal.h>
#include<time.h>
int pselect(int maxfdpl, fd_set* readset, fd_set* writeset,fd_set * execptset, const struct timespec* timeout,const sigset_t* sigmask);
返回:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
pselect相对于通常的select有两个变化。
1) pselect使用timespec结构,而不使用timeval结构。timespec结构是POSIX的又一个发明。
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
这两个结构的区别在于第二个成员:新结构的该成员tv_nsec指定纳秒数,而旧结构的该成员tv_usec指定微妙数。
2) pselect函数增加了第六个参数:一个指向信号掩码的指针。该参数允许先禁止递交某些信号,再测试由这些当前被禁止的信号处理函数设置全局变量,然后调用pselect,告诉他重新设置信号掩码。
关于第二点,考虑下面的例子,这个程序的SIGINT信号处理函数仅仅设置全局变量intr_flag并返回。如果我们的进程阻塞于select调用,那么从信号处理函数的返回将导致select返回EINTR错误。代码看起来大体如下:
问题是,在测试intr_flag和调用select之间如果有信号发生,那么若select永远阻塞,该信号将丢失。有了pselect后,我们可以按以下方式可靠的编写这个例子的代码:
在测试intr_flag变量之前,我们阻塞SIGINT。当pselect被调用时,他先以空集(即zeromask)代替进程的信号掩码,再检查描述符,并可能进入睡眠。然而当pselect函数返回时,进程的信号掩码又被重置为调用pselect之前的值(即SIGINT被阻塞)。