pselect() 函数的原型是:int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
它和 select() 函数基本相同,区别在于两个不同的参数,一个是 struct timespec *timeout,另一个是 sigset_t *sigmask 。
struct timespec 结构定义为:
struct timespec {
long tv_sec;
long tv_nsec;
};
其中的时间表示秒和纳秒。和 select() 不同,每次超时后,pselect() 并不会去修改这个时间参数,也就是说,没有必要再次对这个时间参数进行初始化。
对于最后一个参数 sigmask 表示信号屏蔽掩码,设置掩码可以对相应的信号进行屏蔽,这样pselect就一直不会被屏蔽的信号所中断。
select等待期间不想被中断的方法有两个:
其一:pselect 代替select
#include "unp.h"
void
sig_alarm(int signo)
{
printf("%d\n",signo);
if(signo == SIGALRM)
{
printf("SIGALRM\n");
}
else if(signo == SIGVTALRM)
{
printf("SIGVTALRM\n");
}
}
int
main()
{
sigset_t sigmask;
fd_set rset;
ssize_t nread;
char buf[MAXLINE];
int maxfd;
struct itimerval value;
signal1(SIGALRM,sig_alarm);
value.it_interval.tv_sec = 3;
value.it_interval.tv_usec = 0;
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
if(setitimer(ITIMER_REAL,&value,NULL) == -1)
{
printf("setitimer error.\n");
return 0;
}
if(sigemptyset(&sigmask) == -1)
{
printf("sigemptyset error.\n");
return 0;
}
if(sigaddset(&sigmask,SIGALRM) == -1)
{
printf("sigaddset error.\n");
return 0;
}
while(1)
{
FD_ZERO(&rset);
FD_SET(fileno(stdin),&rset);
maxfd = fileno(stdin) + 1;
int nready = pselect(maxfd,&rset,NULL,NULL,NULL,&sigmask);
//printf("select called.%d\n",nready);
if(nready < 0)
{
if(errno == EINTR)
{
printf("interruped.\n");
}
}
else
{
int nread = ReadLine(fileno(stdin),buf,MAXLINE);
if(nread < 0)
{
printf("读取失败!\n");
continue;
}
// printf("nread: %d\n",nread);
//Write(stdin,buf,nread);
printf("%s",buf);
}
}
}
其二:运用sigprocmask函数
#include "unp.h"
void
sig_alarm(int signo)
{
printf("%d\n",signo);
if(signo == SIGALRM)
{
printf("SIGALRM\n");
}
else if(signo == SIGVTALRM)
{
printf("SIGVTALRM\n");
}
}
int
main()
{
sigset_t sigmask;
fd_set rset;
ssize_t nread;
char buf[MAXLINE];
int maxfd;
struct itimerval value;
signal1(SIGALRM,sig_alarm);
value.it_interval.tv_sec = 3;
value.it_interval.tv_usec = 0;
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
if(setitimer(ITIMER_REAL,&value,NULL) == -1)
{
printf("setitimer error.\n");
return 0;
}
if(sigemptyset(&sigmask) == -1)
{
printf("sigemptyset error.\n");
return 0;
}
if(sigaddset(&sigmask,SIGALRM) == -1)
{
printf("sigaddset error.\n");
return 0;
}
sigprocmask(SIG_BLOCK,&sigmask,NULL);
while(1)
{
FD_ZERO(&rset);
FD_SET(fileno(stdin),&rset);
maxfd = fileno(stdin) + 1;
//int nready = pselect(maxfd,&rset,NULL,NULL,NULL,&sigmask);
//printf("select called.%d\n",nready);
int nready = select(maxfd,&rset,NULL,NULL,NULL);
if(nready < 0)
{
if(errno == EINTR)
{
printf("interruped.\n");
}
}
else
{
int nread = ReadLine(fileno(stdin),buf,MAXLINE);
if(nread < 0)
{
printf("读取失败!\n");
continue;
}
// printf("nread: %d\n",nread);
//Write(stdin,buf,nread);
printf("%s",buf);
}
}
}
比较两种方法,都可以有效防止select被信号中断,经我测试,两者还是有区别的,第一种当你在终端输入数据时,时钟信号处理函数是会被执行的,而第二种则彻底屏蔽了时钟信号。