settimer()函数和alarm()函数

网友投稿 1220 2022-09-24

settimer()函数和alarm()函数

settimer()函数和alarm()函数

unsigned int alarm(unsigned int seconds)函数,用来定时,当到达定时的时间后,内核会发送SIGALRM信号给进程,如果进程忽略该信号,该进程会终止,也可以自己定义SIGALRM信号的处理函数,当然是用的是signal()函数

void (*signal)(int signo, void (*func)(int)))(int );

signo 指定要处理的信号,信号处理函数void func(),当要处理多个信号时候,func(int sig)用sig参数传进信号,在func中判断信号类型,然后指定处理

alarm()函数并不轮询定时,因此可以在func()中收到SIGALRM后,在次设定alarm()函数

但是下面介绍的settimer()函数产生的定时信号讲会持续有效,

example:

#include#include#includevoid fun(int sig);int main(){    alarm(3);    signal(SIGALRM,fun);  // pause();  //wait the signal   while(1);  //always wait for signal   return 0;}void fun(int sig){   if(sig==SIGALRM)   printf("get timer alarm!/n");   else   printf("get timer failed!/n");   alarm(3);}

仍旧有一个函数,settimer() 也是用来定时的,定时到了后内核会发出信号,

函数原型

#include

int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue){struct task_struct *tsk = current;struct hrtimer *timer;ktime_t expires;cputime_t cval, cinterval, nval, ninterval;

/* * Validate the timevals in value. * * Note: Although the spec requires that invalid values shall * return -EINVAL, we just fixup the value and print a limited * number of warnings in order not to break users of this * historical misfeature. * * Scheduled for replacement in March 2007 */check_itimerval(value);

switch (which) {               case ITIMER_REAL:         again:                       spin_lock_irq(&tsk->sighand->siglock);                        timer = &tsk->signal->real_timer;                      if (ovalue) {                                             ovalue->it_value = itimer_get_remtime(timer);                                              ovalue->it_interval= ktime_to_timeval(tsk->signal->it_real_incr);                                       }/* We are sharing ->siglock with it_real_fn() */                      if (hrtimer_try_to_cancel(timer) < 0) {                                       spin_unlock_irq(&tsk->sighand->siglock);                                       hrtimer_wait_for_timer(&tsk->signal->real_timer);                                       goto again;                          }                      expires = timeval_to_ktime(value->it_value);                      if (expires.tv64 != 0) {                       tsk->signal->it_real_incr =                       timeval_to_ktime(value->it_interval);                      hrtimer_start(timer, expires, HRTIMER_MODE_REL);                      }

else                       tsk->signal->it_real_incr.tv64 = 0;

spin_unlock_irq(&tsk->sighand->siglock);                       break;        case ITIMER_VIRTUAL:                            nval = timeval_to_cputime(&value->it_value);                             ninterval = timeval_to_cputime(&value->it_interval);                            read_lock(&tasklist_lock);                             spin_lock_irq(&tsk->sighand->siglock);                            cval = tsk->signal->it_virt_expires;                             cinterval = tsk->signal->it_virt_incr;                             if (!cputime_eq(cval, cputime_zero) || !cputime_eq(nval, cputime_zero)) {                                               if (cputime_gt(nval, cputime_zero))                                               nval = cputime_add(nval,                                                 jiffies_to_cputime(1));                                              set_process_cpu_timer(tsk, CPUCLOCK_VIRT,&nval, &cval);                           }                            tsk->signal->it_virt_expires = nval;                          tsk->signal->it_virt_incr = ninterval;                          spin_unlock_irq(&tsk->sighand->siglock);                          read_unlock(&tasklist_lock);                         if (ovalue) {                                        cputime_to_timeval(cval, &ovalue->it_value);                                           cputime_to_timeval(cinterval, &ovalue->it_interval);                               }                              break;                               case ITIMER_PROF:                           nval = timeval_to_cputime(&value->it_value);                           ninterval = timeval_to_cputime(&value->it_interval);                           read_lock(&tasklist_lock);                          spin_lock_irq(&tsk->sighand->siglock);                          cval = tsk->signal->it_prof_expires;                            cinterval = tsk->signal->it_prof_incr;                          if (!cputime_eq(cval, cputime_zero) ||!cputime_eq(nval, cputime_zero)) {                                if (cputime_gt(nval, cputime_zero))                                              nval = cputime_add(nval,jiffies_to_cputime(1));                                   set_process_cpu_timer(tsk, CPUCLOCK_PROF,&nval, &cval);                              }                           tsk->signal->it_prof_expires = nval;                           tsk->signal->it_prof_incr = ninterval;                           spin_unlock_irq(&tsk->sighand->siglock);                            read_unlock(&tasklist_lock);                          if (ovalue) {                             cputime_to_timeval(cval, &ovalue->it_value);                             cputime_to_timeval(cinterval, &ovalue->it_interval);                             }                             break;                             default:                             return -EINVAL;                }            return 0;}

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。

struct itimercal:

struct itimerval {                               struct timeval it_interval; /* timer interval */                               struct timeval it_value; /* current value *      };

itimerval结构中的it_value是减少的时间,当这个值为0的时候就发出相应的信号了. 然后再将it_value设置为it_interval值.这样就实现了轮询的定时,而不是想alarm那样只能定时一次,而且其精确度也很高

看例子:

#include      #include      #include      #include      void fun(int sig);      int main()      {             struct itimerval val;             val.it_value.tv_sec=3;             val.it_value.tv_usec=0;             val.it_interval.tv_sec=3;             val.it_interval.tv_usec=0;             setitimer(ITIMER_REAL,&val,NULL);             signal(SIGALRM,fun);             while(1);  //always wait for signal             return 0;      }      void fun(int sig)      {             if(sig==SIGALRM)             printf("get timer alarm!/n");             else             printf("get timer failed!/n");      }

setitimer()为其所在进程设置一个定时器,如果itimerval.it_interval不为0(it_interval的两个域都不为0),则该定时器将持续有效(每隔一段时间就会发送一个信号)

注意:Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是:进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。

Linux实现定时还有一种方法,就是是用RTC来定时,不过感觉好像很麻烦

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:动态库在不同操作系统中的不同意义
下一篇:不吹不黑,瑞幸其实是家新品营销公司!(瑞幸的营销)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~