Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Linux下的定时器:alarm()与setitimer()

Posted on 2008-10-30 18:47 Prayer 阅读(903) 评论(0)  编辑 收藏 引用 所属分类: LINUX/UNIX/AIX

Linux下的定时器有两种,以下分别介绍:

1、alarm

如果不要求很精确的话,用alarm()和signal()就够了

unsigned int alarm(unsigned int seconds)

函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。

返回值: 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0。

alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。

#include 

#include

#include

void sigalrm_fn(int sig)

{

printf("alarm!\n");

alarm(2);

return;

}

int main(void)

{

signal(SIGALRM, sigalrm_fn);

alarm(1);

while(1) pause();

}

2、setitimer()

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

setitimer()比alarm功能强大,支持3种类型的定时器:

ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。

ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。

ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。

setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。

setitimer()调用成功返回0,否则返回-1。

下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:

#include 

#include

#include

#include

#include

#include

int sec;

void sigroutine(int signo){

switch (signo){

case SIGALRM:

printf("Catch a signal -- SIGALRM \n");

signal(SIGALRM, sigroutine);

break;

case SIGVTALRM:

printf("Catch a signal -- SIGVTALRM \n");

signal(SIGVTALRM, sigroutine);

break;

}

return;

}

int main()

{

struct itimerval value, ovalue, value2; //(1)

sec = 5;

printf("process id is %d\n", getpid());

signal(SIGALRM, sigroutine);

signal(SIGVTALRM, sigroutine);

value.it_value.tv_sec = 1;

value.it_value.tv_usec = 0;

value.it_interval.tv_sec = 1;

value.it_interval.tv_usec = 0;

setitimer(ITIMER_REAL, &value, &ovalue); //(2)

value2.it_value.tv_sec = 0;

value2.it_value.tv_usec = 500000;

value2.it_interval.tv_sec = 0;

value2.it_interval.tv_usec = 500000;

setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

for(;;)

;

}

(1) struct itimerval

struct itimerval {

struct timeval it_interval; /* timer interval */

struct timeval it_value; /* current value */

};

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(),重新安装该信号。

http://tech.ccidnet.com/art/302/20071226/1322683_1.html

-------------------------------

linux中的信号处理(signal和alarm)

信号是unix中所使用的进程通信的一种最古老的方法.系统使用它来同志一个或多个进程异步事件的发生.

linux系统库bits/signum.h对信号名作了定义:
linux的大多数信号是提供给内核的,仅有少数几种信号可以在信号间发送.

.SIGHUP 当终止一个终端时,内核就把这种信号发送给该终端所控制的所有进程.
.SIGINT 当一个用户按下中断键(ctrl+c)后,内核就向该终端用关联的所有进程发送这个信号.
.SIGQUIT 当用户按下(ctrl+),内核就向该终端用关联的所有进程发送这个信号.
.SIGILL 当一个进程企图执行一条非法指令时,内核就发送这个信号.
.SIGFPE 当产生浮点错误时,内核就发送这个信号.
.SIGKILL 这是一个非常特殊的信号,他可以从一个进程发送到另一个进程,使接收到该信号的进程终止.内核偶然也发送这种信号.
.SIGALRM 当一个定时器到时的时候,内核就发送这个信号.
.SIGSTOP 子进程结束信号.UNIX用它来实现系统调用exit(),wait();

信号的处理
unix的系统调用signal()用于接受一个指定的信号,并可以指定相应的处理方法.

在linux系统库signal.h中,它的说明如下:
signal(int sig,sighandler_t handler);
sig用于指定信号类型.handle是用于处理该信号的函数.
handle还可以是:
.SIG_IGN 忽略这个信号.
.SIG_DFL 恢复对这个信号的默认处理.

例如:

main(){
signal(SIGINT,SIG_IGN);
printf(”hello!n”);
sleep(10);
printf(”hellon”);
}
上面的代码忽略了SININT信号.

又例如:
int catch(int sig);

main(){
signal(SIGINT,catch);
printf(”hello!n”);
sleep(10);
printf(”hello!n”);
}

int catch(int sig){
printf(”catch signaln”);
return 1;
}
当用户按下ctrl+c时,进程被中断,catch()被执行.中断处理函数处理完毕后,转回断点执行下面的指令.

当编写自己的中断处理函数时,注意下面两点:
1.信号不能打断系统调用.
2.信号不能打断信号处理函数.

alarm(设置信号传送闹钟)
定义函数
unsigned int alarm(unsigned int seconds);
函数说明
alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds 为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
返回值
返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0。
范例
void handler() {
printf("hellon");
}
main()
{
int i;
signal(SIGALRM,handler);
alarm(5);
for(i=1;i<7;i++){
printf("sleep %d ...n",i);
sleep(1);
}
}
执行
sleep 1 ...
sleep 2 ...
sleep 3 ...
sleep 4 ...
sleep 5 ...
hello
sleep 6 ...

http://blog.csdn.net/sambian/archive/2006/04/30/698718.aspx


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理