linux定时器处理函数,Linux定时器

Linux提供了2个函数来实现定时器功能:alarm函数和setitimer函数。

1、alarm函数

如果对定时要求不太精确的话,使用alarm()和signal()就行了。

函数原型:unsigned int alarm(unsigned int seconds)

#include #include #include void time_handler(int sig)

{

printf("alarm!\n");

alarm(2);

return;

}

int main(void)

{

signal(SIGALRM, time_handler);

alarm(2);

while(true)

{

sleep(1);

}

}

注意:alarm只设定一个闹钟,时间到达并执行其注册函数之后,闹钟便失效。如果想循环设置闹钟,需在其注册函数中在调用alarm函数。

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信号。

#include #include #include #include #include #include void time_handler(int sig)

{

switch (sig){

case SIGALRM:

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

break;

case SIGVTALRM:

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

break;

}

return;

}

int main()

{

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

signal(SIGALRM, time_handler);

signal(SIGVTALRM, time_handler);

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 = 2;

value2.it_value.tv_usec = 0;

value2.it_interval.tv_sec = 2;

value2.it_interval.tv_usec = 0;

setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

while(true)

{

sleep(1);

}

}

structitimerval {

structtimeval it_interval;/* next value */

structtimeval it_value;/* current value */

};

structtimeval {

longtv_sec;/* seconds */

longtv_usec;/* microseconds */

}; 先看结构体itimerval:it_value表示设置定时器当前到下一次溢出的时间,it_interval表示下一次定时器溢出时,将会把it_interval的值赋给it_value,即定时器的时间间隔。

setitimer函数是注册内核中的定时器,这种定时器不会引起线程的切换,不会引起线程的阻塞。ITIMER_REAL间隔定时器是利用动态定时器实现的,即使进程不在CPU上运行时,内核也必须向进程发送信号。因此,每个进程描述符包含一个real_timer的动态定时器对象。ITIMER_VIRTUAL和ITIMER_PROF间隔定时器不需要动态定时器,因为只有当进程运行时,它们才被更新。

3、多定时器的实现

多定时器,有的通过gettimeofday函数获取时间差,通过计算时间差来实现多定时器。这边我介绍一种简单的多定时器实现方法。

#include #include #include #include #include #include #define TIMER_1 1

#define TIMER_2 2

#define TIMER_3 3

void time_handler(int sig,siginfo_t *si,void *uc)

{

long long *tid=(long long)si->si_ptr;

switch(*tid)

{

case TIMER_1:printf("This is Timer_1!");break;

case TIMER_1:printf("This is Timer_2!");break;

case TIMER_1:printf("This is Timer_3!");break;

}

}

void timer_init()

{

struct itimerspec value1,value2,value3;

struct sigcation sa;

struct sigevent sev;

timer_t tidlist[3];

tidlist[0]=(timer_t*)TIMER_1;

tidlist[1]=(timer_t*)TIMER_2;

tidlist[0]=(timer_t*)TIMER_3;

sa.sa_flags=SA_SIFINFO;

sa.sa_sigaction=timer_handler;

sigemptyset(&sa.sa_mask);

sigcation(SIGRTMAX,&sa,NULL);

sev.sigev_notify=SIGEV_SIGNAL;

sev.sigev_signo=SIGRTMAX;

value1.it_value.tv_sec=10;

value1.it_value.tv_nsec=0;

value1.it_interval.tv_sec=10;

value1.it_interval.tv_nsec=0;

value2.it_value.tv_sec=2;

value2.it_value.tv_nsec=0;

value2.it_interval.tv_sec=2;

value2.it_interval.tv_nsec=0;

value3.it_value.tv_sec=5;

value3.it_value.tv_nsec=0;

value3.it_interval.tv_sec=5;

value3.it_interval.tv_nsec=0;

sev.sigev.sival_ptr=tidlist[0];

timer_create(CLOCK_REALTIME,&sev,&tidlist[0]);

sev.sigev.sival_ptr=tidlist[1];

timer_create(CLOCK_REALTIME,&sev,&tidlist[1]);

sev.sigev.sival_ptr=tidlist[2];

timer_create(CLOCK_REALTIME,&sev,&tidlist[2]);

timer_settime(tidlist[0],0,&value1,NULL);

timer_settime(tidlist[1],0,&value2,NULL);

timer_settime(tidlist[2],0,&value3,NULL);

}

int main()

{

timer_init();

while(true)

{

sleep(20);

}

}

当程序运行时,收到信号,将会开启中断服务。在信号处理程序中,不能判断捕捉信号时进程执行到哪里。因此,定时器回调函数中一般不能调用不可重入函数,如malloc函数,特别是在C++字符串string处理中,有时候会频繁申请和释放空间,此时如果主进程也是在频繁申请和释放空间,则可能会死锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值