linux下定时器的使用--alarm()&setitimer():
1、alarm
-------------------------------------------
若果不要求很精确的话,用alarm()和signal()就够了
unsignedintalarm(unsignedintseconds)
函数说明:alarm()拿来设置讯号SIGALRM在经过参数seconds指定的秒数后传献给目前的进程。假如参数seconds为0,则之前设置的闹铃会被取消,并将剩下的时间返回。
返回值:返回之前闹铃的剩余秒数,假若之前未设闹铃则返回0。
alarm()执行后,进程将继续执行linux rar,在后期(alarm之后)的执行过程上将会在seconds秒后收到讯号SIGALRM并执行其处理函数。
#include
#include
#include
voidsigalrm_fn(intsig)
printf("alarm!/n");
alarm(2);
return;
intmain(void)
signal(SIGALRM,sigalrm_fn);
alarm(1);
while(1)pause();
2、setitimer()
-------------------------------------------
intsetitimer(intwhich,conststructitimerval*value,structitimerval*ovalue));
setitimer()比alarm功能强悍linux 使用定时器,支持3种类型的定时器:
ITIMER_REAL:以系统真实的时间来估算,它送出SIGALRM讯号。
ITIMER_VIRTUAL:-以该进程在用户态下耗费的时间来估算,它送出SIGVTALRM讯号。
ITIMER_PROF:以该进程在用户态下和内核态下所费的时间来估算,它送出SIGPROF讯号。
setitimer()第一个参数which指定定时器类型(前面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1。
下边是关于setitimer调用的一个简单示范,在该事例中,每隔1秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM讯号:
#include
#include
#include
#include
#include
#include
intsec;
voidsigroutine(intsigno){
switch(signo){
caseSIGALRM:
printf("Catchasignal--SIGALRM/n");
signal(SIGALRM,sigroutine);
break;
caseSIGVTALRM:
printf("Catchasignal--SIGVTALRM/n");
signal(SIGVTALRM,sigroutine);
break;
return;
intmain()
structitimervalvalue,ovalue,value2;//(1)
sec=5;
printf("processidis%d/n",getpid());
signal(SIGALRM,sigroutine);
signal(SIGVTALRM,sigroutine);
_sec=1;
_usec=0;
_sec=1;
_usec=0;
setitimer(ITIMER_REAL,&value,&ovalue);//(2)
_sec=0;
_usec=500000;
_sec=0;
_usec=500000;
setitimer(ITIMER_VIRTUAL,&value2,&ovalue);
for(;;)
(1)structitimerval
structitimerval{
structtimevalit_interval;/*timerinterval*/
structtimevalit_value;/*currentvalue*/
};
itimerval:i-->interval
val-->value
itimerval结构中的it_value是降低的时间,当这个值为0的时侯就发出相应的讯号了.之后再将it_value设置为it_interval值.
(2)setitimer()
setitimer()为其所在进程设置一个定时器,假如itimerval.it_interval不为0(it_interval的两个域都不为0),则该定时器将持续有效(每隔一段时间才会发送一个讯号)
注意:Linux讯号机制基本上是从Unix系统中继承过来的。初期Unix系统中的讯号机制比较简单和原始,后来在实践中曝露出一些问题,因而,把这些构建在初期机制上的讯号称作"不可靠讯号",讯号值大于SIGRTMIN(SIGRTMIN=32,SIGRTMAX=63)的讯号都是不可靠讯号。这就是"不可靠讯号"的来源。它的主要问题是:进程每次处理讯号后,就将对讯号的响应设置为默认动作。在个别情况下,将造成对讯号的错误处理;因而,用户倘若不希望这样的操作,这么就要在讯号处理函数结尾再一次调用signal(),重新安装该讯号。
***********************************
Linux下怎样实现秒以下精确定时与休眠
linux中提供的休眠函数是sleep和alarm,而且她们仅仅提供以秒为单位的休眠,这中休眠有些进程也许太长了linux 使用定时器,这么如何能够使进程以更小的时间帧率休眠呢?
我晓得的方式有2种,下边就做分别介绍。
第一种方式是使用定时器,Linux提供的定时器函数是:
intsetitimer(intwhich,conststructitimerval*value,struct
itimerval*ovalue);
which指定那个定时器。Linux提供3种定时器:
TIMER_REAL:确切定时器,超时会发出SIGALRM讯号;
TIMER_VIRTUAL:虚拟定时器,只记进程时间,所以会依照进程执行时间而变化,不能实现确切定时,超时发出SIGVTALRM讯号;
TIMER_PROF:梗概计时器,它会依照进程时间和系统时间而变化,不能实现确切定时,超时发出SIGPROF讯号;
在进程中应当捕捉所设定时器会发出的讯号,由于进程收到定时器超时发出的讯号后,默认动作是中止。
value是设置定时器时间,相关结构如下:
structitimerval{
structtimevalit_interval;
structtimevalit_value;
};
structtimeval{
longtv_sec;
longtv_usec;
};
it_interval指定间隔时间,it_value指定初始定时时间。假如只指定it_value,就是实现一次定时;假如同时指定it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;二者都清零,则会消除定时器。
tv_sec提供秒级精度,tv_usec提供毫秒级精度,以值大的为先,注意1s=1000000ms。
ovalue拿来保存以前的值,常设为NULL。
若果是以setitimer提供的定时器来休眠,只需阻塞等待定时器讯号就可以了。
第二种方式是使用select来提供精确定时和休眠:
intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,
structtimeval*timeout);
n指监视的文件描述符范围,一般设为所要select的fd+1,readfds,writefds和exceptfds分别是读,写和异常文件描述符集,timeout为超时时间。
可能用到的关于文件描述符集操作的宏有:
FD_CLR(intfd,fd_set*set);消除fd
FD_ISSET(intfd,fd_set*set);测试fd是否设置
FD_SET(intfd,fd_set*set);设置fd
FD_ZERO(fd_set*set);清空描述符集
我们此时用不到这种宏,由于我们并不关心文件描述符的状态,我们关心的是select超时。所以我们须要把readfds,writefds和exceptfds都设为NULL,只指定timeout时间就行了。至于n我们可以不关心,所以你可以把它设为任何非负值。实现代码如下:
intmsSleep(longms){
structtimevaltv;
_sec=0;
_usec=ms;
returnselect(0,NULL,NULL,NULL,&tv);
呵呵,如何样,是不是很简单?
结语:
setitimer和select都能实现进程的精确休眠,本文分别对她们进行了简单介绍,并给出了一个简单的给与select的实现。我不推荐使用setitimer,由于一者Linux系统提供的timer有限(每位进程至多能设3个不同类型的timer)红旗linux安装,此外ssetitimer实现上去没有select简单。