linux c语言定时器.doc_第1页
linux c语言定时器.doc_第2页
linux c语言定时器.doc_第3页
linux c语言定时器.doc_第4页
linux c语言定时器.doc_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

linux c语言定时器linux c语言定时器2010-09-01 20:13linux定时器的使用使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务。要达到这一目的,一般有两个常见的比较有效的方法。一个是用linux内部的三个定时器,另一个是用sleep, usleep函数让进程睡眠一段时间,其实,还有一个方法,那就是用gettimeofday, difftime等自己来计算时间间隔,然后时间到了就执行某一任务,但是这种方法效率低,所以不常用。首先来看看linux操作系统为每一个进程提供的3个内部计时器。ITIMER_REAL: 给一个指定的时间间隔,按照实际的时间来减少这个计数,当时间间隔为0的时候发出SIGALRM信号ITIMER_VIRTUAL: 给定一个时间间隔,当进程执行的时候才减少计数,时间间隔为0的时候发出SIGVTALRM信号ITIMER_PROF: 给定一个时间间隔,当进程执行或者是系统为进程调度的时候,减少计数,时间到了,发出SIGPROF信号,这个和ITIMER_VIRTUAL联合,常用来计算系统内核时间和用户时间。用到的函数有:#include int getitimer(int which, struct itimerval *value);int setitimer(int which, struct itimerval*newvalue, struct itimerval* oldvalue);strcut timevallong tv_sec; /*秒*/long tv_usec; /*微秒*/;struct itimervalstruct timeval it_interval; /*时间间隔*/struct timeval it_value; /*当前时间计数*/;it_interval用来指定每隔多长时间执行任务, it_value用来保存当前时间离执行任务还有多长时间。比如说, 你指定it_interval为2秒(微秒为0),开始的时候我们把it_value的时间也设定为2秒(微秒为0),当过了一秒, it_value就减少一个为1, 再过1秒,则it_value又减少1,变为0,这个时候发出信号(告诉用户时间到了,可以执行任务了),并且系统自动把it_value的时间重置为 it_interval的值,即2秒,再重新计数。为了帮助你理解这个问题,我们来看一个例子:1. #include 2. #include 3. #include 4. #include 5. #include 6.7. static char msg = “time is running outn”; 8. static int len; 9.10. / 向标准错误输出信息,告诉用户时间到了 11. void prompt_info(int signo) 12. 13. write(STDERR_FILENO, msg, len); 14. 15.16. / 建立信号处理机制 17. void init_sigaction(void) 18. 19. struct sigaction tact; 20.21. /*信号到了要执行的任务处理函数为prompt_info*/ 22. tact.sa_handler = prompt_info; 23. tact.sa_flags = 0; 24. /*初始化信号集*/ 25. sigemptyset(&tact.sa_mask); 26. /*建立信号处理机制*/ 27. sigaction(SIGALRM, &tact, NULL); 28. 29.30. void init_time() 31. 32. struct itimerval value; 33.34. /*设定执行任务的时间间隔为2秒0微秒*/ 35. value.it_value.tv_sec = 2; 36. value.it_value.tv_usec = 0; 37. /*设定初始时间计数也为2秒0微秒*/ 38. value.it_interval = value.it_value; 39. /*设置计时器ITIMER_REAL*/ 40. setitimer(ITIMER_REAL, &value, NULL); 41. 42.43. int main() 44. 45. len = strlen(msg); 46. init_sigaction(); 47. init_time(); 48. while ( 1 ); 49. exit(0); 50. 该程序的ITMER_REAL定时器,每隔2秒钟都会发送一个SIGALRM信号,当主函数接收到了这个信号之后,调用信号处理函数 prompt_info在标准错误上输出time is running out这个字符串。对于ITIMER_VIRTUAL和ITIMER_PROF的使用方法类似,当你在setitimer里面设置的定时器为 ITIMER_VIRTUAL的时候,你把sigaction里面的SIGALRM改为SIGVTALARM, 同理,ITIMER_PROF对应SIGPROF。不过,你可能会注意到,当你用ITIMER_VIRTUAL和ITIMER_PROF的时候,你拿一个秒表,你会发现程序输出字符串的时间间隔会不止2秒,甚至5-6秒才会输出一个,至于为什么,自己好好琢磨一下_下面我们来看看用sleep以及usleep怎么实现定时执行任务。1. #include 2. #include 3. #include 4. #include 5.6. static char msg = “I received a msg.n”; 7. int len; 8. void show_msg(int signo) 9. 10. write(STDERR_FILENO, msg, len); 11. 12. int main() 13. 14. struct sigaction act; 15. union sigval tsval; 16.17. act.sa_handler = show_msg; 18. act.sa_flags = 0; 19. sigemptyset(&act.sa_mask); 20. sigaction(50, &act, NULL); 21.22. len = strlen(msg); 23. while ( 1 ) 24. 25. sleep(2); /*睡眠2秒*/ 26. /*向主进程发送信号,实际上是自己给自己发信号*/ 27. sigqueue(getpid(), 50, tsval); 28. 29. return 0; 30. 看到了吧,这个要比上面的简单多了,而且你用秒表测一下,时间很准,指定2秒到了就给你输出一个字符串。所以,如果你只做一般的定时,到了时间去执行一个任务,这种方法是最简单的。下面我们来看看,通过自己计算时间差的方法来定时:1. #include 2. #include 3. #include 4. #include 5. #include 6.7. static char msg = “I received a msg.n”; 8. int len; 9. static time_t lasttime; 10. void show_msg(int signo) 11. 12. write(STDERR_FILENO, msg, len); 13. 14. int main() 15. 16. struct sigaction act; 17. union sigval tsval; 18.19. act.sa_handler = show_msg; 20. act.sa_flags = 0; 21. sigemptyset(&act.sa_mask); 22. sigaction(50, &act, NULL); 23.24. len = strlen(msg); 25. time(&lasttime); 26. while ( 1 ) 27. 28. time_t nowtime; 29. /*获取当前时间*/ 30. time(&nowtime); 31. /*和上一次的时间做比较,如果大于等于2秒,则立刻发送信号*/ 32. if (nowtime lasttime = 2) 33. 34. /*向主进程发送信号,实际上是自己给自己发信号*/ 35. sigqueue(getpid(), 50, tsval); 36. lasttime = nowtime; 37. 38. 39. return 0; 40. 这个和上面不同之处在于,是自己手工计算时间差的,如果你想更精确的计算时间差,你可以把 time 函数换成gettimeofday,这个可以精确到微妙。上面介绍的几种定时方法各有千秋,在计时效率上、方法上和时间的精确度上也各有不同,采用哪种方法,就看你程序的需要 itimerval时钟的使用#include#include#include/itimerval结构体的定义int handle_count=0;void set_time(void) struct itimerval itv; itv.it_interval.tv_sec=10;/自动装载,之后每10秒响应一次 itv.it_interval.tv_usec=0; itv.it_value.tv_sec=5;/第一次定时的时间 itv.it_value.tv_usec=0; setitimer(ITIMER_REAL,&itv,NULL);void alarm_handle(int sig) handle_count+; printf(have handle count is %dn,handle_count);void main(void) struct itimerval itv; signal(SIGALRM,alarm_handle); set_time(); while(1) getitimer(ITIMER_REAL,&itv); printf(pass second is %dn,(int)itv.it_value.tv_sec); sleep(1); return;linux c 定时器Linux系统中的定时器有2种,以下分别介绍:1、alarm如果不要求很精确的话,用alarm()和signal()就够了unsigned int alarm(unsigned int seconds)函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。返回值: 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0。alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。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 int sec;void sigroutine(int signo) switch (signo) case SIGALRM:printf(Catch a signal - SIGALRMn);break;case SIGVTALRM:printf(Catch a signal - SIGVTALRMn);break;return;int main() struct itimerval value,ovalue,value2;sec = 5;printf(process id is %dn,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);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 itimervalstruct itimerval struct timeval it_interval; /* timer interval */struct timeval it_value; /* current value */;itimerval: i - intervalval - valueitimerval结构中的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下的定时器:alarm()与setitimer()关注Linuxeden官方微博 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 %dn, getpid(); signal(SIGALRM, sigroutine); signal(SIGVTALRM, sigroutine); value.it_value.tv_sec = 1; value.it_value.tv_usec = 0; v

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论