一、 使用时钟和定时器(alarm系统调用)
#include <unistd.h>
unsigned alarm(unsigned secs);
/*returns secs left on previous alarm or zero if none */
alarm也称为闹钟函数,它可以在进程中设置一个定时器,当指定的时间到时,它向进程发送SIGALRM信号。需要注意的是,一个进程只能有一个定时器。当报警开始时,会发送一个SIGALRM,子进程继承其父进程的报警时钟值,但实际的时钟并不共享。执行exec后,报警时钟仍然保持其设置。
alarm按照secs指定的秒数来设置时钟,如果secs为0,则关闭报警时钟,这样做是很有必要的,如果recvfrom函数读到数据,没到设定时钟值时就返回了,而你又忘记关闭报警时钟的话,那么它将在不久后报警,在计算机看来,1秒都是一个很漫长的时间,1秒后的报警可能会造成本进程中其他函数执行的中断,因为一个进程只有一个定时器,所以使用完定时器后,一定要关闭定时器。
实例代码:
int n;
char recvbuf[1024];
static void dealSigAlarm(int signo)
{
n = -1;
return; /* just interrupt the recvfrom() */
}
struct sigaction alrmact;
bzero(&alrmact,sizeof(alrmact));
alrmact.sa_handler = dealSigAlarm;
alrmact.sa_flags = SA_NOMASK;//使用SA_RESTART将会阻塞在recvfrom函数,与直接使用signal效果相同
alrmact.sa_restorer = NULL;
sigaction(SIGALRM,&alrmact,NULL);
while (1) {
alarm(5);
n = recvfrom(peerSocket,recvbuf,1420,0,(struct sockaddr *)&peer_Addr,(socklen_t*)&peer_len)
if (n < 0) {
if (errno == EINTR) {
printf("recvfrom timeout.\n");
} else {
printf("recvfrom error.\n");
}
} else {
alarm(0);//很重要
}
}
附:signal与sigaction函数区别,signal是重启动函数,超时以后会自动启动已阻塞的函数,而不是中断它的执行,比如recvfrom,给人的感觉就是使用了alarm,程序依然阻塞在了recvfrom上,不往下执行,如果在信号处理函数中使用printf可以看到超时后输出了一条超时信息,然后signal又启动了recvfrom,继续阻塞。。。
sigaction可以自己设置是否重启动函数,即上面例子中的alrmact.sa_flags = SA_NOMASK选项,SA_NOMASK为不重启动,中断已阻塞的函数recvfrom,使程序继续往下执行,SA_RESTART为重启动函数,与signal相同,继续阻塞在recvfrom上。。。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。