|
pselect() 函数的原型是:
[C++] 纯文本查看 复制代码 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 。
关于 select() 函数可参考:http://www.groad.net/bbs/read.php?tid-1064.html
struct timespec 结构定义为:
[C++] 纯文本查看 复制代码 struct timespec {
long tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
其中的时间表示秒和纳秒。和 select() 不同,每次超时后,pselect() 并不会去修改这个时间参数,也就是说,没有必要再次对这个时间参数进行初始化。
对于最后一个参数 sigmask 表示信号屏蔽掩码,关于信号屏蔽掩码以及操作函数参考(http://www.groad.net/bbs/read.php?tid-922.html)。
当使用该参数时,也就相当于将 select() 函数写成下列的形式:
[C++] 纯文本查看 复制代码
sigset_t origmask;
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
使用 pselect() 函数一个最大的原因正是它可以防止信号的干扰。比如说,如果你只是使用 select() 函数,在超时时间内很可能还会受到时钟信号(SIGALARM)
的打断,从而影响 select() 的正常使用。
下面引用网上的一篇博文以更具体的说明此函数的应用:
很久以来,同事写的一个模块,与串口收发数据的时候,SELECT()函数等待的时间长点,就会被模块里设置的时钟信号打断,最近看到了一个新的函数pselect(),研究了一把,收获不小!!
现在发现,SELECT()函数等待的这段时间内不想被别的信号打断的方法有两
其一:
用pselect()函数
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/select.h>
#define BUFFSIZE 80
void sig_int(int signo);
void err_sys(const char *p_error);
void sig_alrm(int signo)
{
char s[] ="receive";
psignal(signo, s);
return;
}
int
main(int argc, char **argv)
{
int maxfdp1;
fd_set rset;
sigset_t sigmask;
ssize_t nread;
char buf[BUFFSIZE];
sigset_t sigset;
structsigaction act;
//set SIGALRM signal handler
act.sa_handler= sig_alrm;
if(sigemptyset(&act.sa_mask) ==-1)
err_sys("sigemptyset");
act.sa_flags= 0;
if(sigaction(SIGALRM, &act, NULL) == -1)
err_sys("sigaction");
//initialize signal set and addition SIGALRM into sigset
if(sigemptyset(&sigset) == -1)
err_sys("sigemptyet");
if(sigaddset(&sigset, SIGALRM) == -1)
err_sys("sigaddset");
alarm(1);
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
maxfdp1 = STDIN_FILENO + 1;
if (pselect(maxfdp1, &rset, NULL, NULL, NULL,&sigset) <= 0)
err_sys("pselect error");
if (FD_ISSET(STDIN_FILENO, &rset))
{
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) == -1)
err_sys("read error");
if (write(STDOUT_FILENO, buf, nread) != nread)
err_sys("write error");
}
exit(0);
}
void
sig_int(int signo)
{
char s[] ="received";
psignal(signo, s);
return;
}
void
err_sys(const char *p_error)
{
perror(p_error);
exit(1);
}
上段代码如果没有CTRL+C送上一个SIGINT信号,将永远阻塞在与用户的交互上,ALARM产生的SIGALRM信号永远打断不了PSELECT,ALARM信号被成功屏蔽
方法2:sigprocmask()
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/select.h>
#define BUFFSIZE 80
void sig_int(int signo);
void err_sys(const char *p_error);
void sig_alrm(int signo)
{
char s[] ="receive";
psignal(signo, s);
return;
}
int
main(int argc, char **argv)
{
int maxfdp1;
fd_set rset;
sigset_t sigmask;
ssize_t nread;
char buf[BUFFSIZE];
sigset_t sigset;
structsigaction act;
//set SIGALRM signal handler
act.sa_handler= sig_alrm;
if(sigemptyset(&act.sa_mask) ==-1)
err_sys("sigemptyset");
act.sa_flags= 0;
if(sigaction(SIGALRM, &act, NULL) == -1)
err_sys("sigaction");
//initialize signal set and addition SIGALRM into sigset
if(sigemptyset(&sigset) == -1)
err_sys("sigemptyet");
if(sigaddset(&sigset, SIGALRM) == -1)
err_sys("sigaddset");
//block SIGALRMsignal
if(sigprocmask(SIG_BLOCK, &sigset, NULL) == -1)
err_sys("sigprocmask");
//generate SIGALRM signal
alarm(1);
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
maxfdp1 = STDIN_FILENO + 1;
if (select(maxfdp1, &rset, NULL, NULL, NULL)<= 0)
err_sys("pselect error");
if (FD_ISSET(STDIN_FILENO, &rset))
{
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) == -1)
err_sys("read error");
if (write(STDOUT_FILENO, buf, nread) != nread)
err_sys("write error");
}
exit(0);
}
void
sig_int(int signo)
{
char s[] ="received";
psignal(signo, s);
return;
}
void
err_sys(const char *p_error)
{
perror(p_error);
exit(1);
}
同样,上段代码如果没有CTRL+C送上一个SIGINT信号,将永远阻塞在与用户的交互上,ALARM产生的SIGALRM信号永远打断不了SELECT,ALARM信号被成功屏蔽.
|
|