免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1819 | 回复: 4
打印 上一主题 下一主题

如何在嵌入式linux下实现定时操作?? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-02 15:26 |只看该作者 |倒序浏览
如何在嵌入式linux下实现定时操作??
比如10s内收到数据则进行操作一,10内未受到则进行操作二,请问各位大侠怎么实现定时操作啊?我也考虑用sleep/usleep来实现,不过,它会阻塞当前线程,除了处理定时功能外,什么活也干不了。谢谢!!

论坛徽章:
0
2 [报告]
发表于 2009-03-02 16:29 |只看该作者
不吝赐教啊~~谢谢

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
3 [报告]
发表于 2009-03-02 16:57 |只看该作者
单timer的话可以使用signal,多timer的话,可以使用rt库

下面转一篇

软件定时器的主要功能是实现状态机的超时机制和实现基于超时的计数功能。
由于协议状态机运行于Linux内核之上,也就是说在用户态运行。在Linux系统中,用户态应用程序只能调用三个定时器:ITIMER_REAL、 ITIMER_VIRTUAL和ITIMER_PROF。而在协议状态机中需要32个定时器,所以需要新的机制来完成定时功能。
软件定时器主要被用来解决硬件定时器的物理限制,并为应用程序提供更加灵活的定时器编程接口。定时器最基本的作用就是允许某个任务在将来某个特定时间点运 行。定时器超时,被注册的任务开始运行,在我们的系统中,和定时器相关的任务就是产生某个定时器超时事件。我们定义最基本的定时器结构Timer,当作我 们的软件定时器对象:

  1. #define MAX_TIMERS N   //N为你需要的定时器的个数
  2. struct Timer{
  3.             long timeout;                      // 定时器超时时间,单位毫秒ms
  4.             long expire;                      // 下一次中断时定时器剩余的超时时间,单位毫秒ms
  5.             int inuse;                      // 定时器是否被使用
  6.             int set;                                // 定时器是否超时
  7.             int signal;                      // 定时器超时时,发送的事件类型
  8.             int param;                      // 定时器超时时,发送的事件类型的参数
  9. }T[MAX_TIMERS];// 定时器集合
  10.        软件定时器提供给应用程序的接口主要有4个:
  11.        Int init_timers();                                // 初始化定时器集合
  12.        Int start_timer(struct Timer *T);        // 启动定时器T
  13.        Int stop_timer(struct Timer *T);        // 停止定时器T
  14.        Int get_event();                                // 查询超时的定时器事件
复制代码

程序初始化时调用init_timers()初始化定时器集合,初始化之后就可以在系统中调用start_timer()和stop_timer()来使用定时器功能。协议状态机循环调用get_event()查询超时的定时器事件,输入到协议状态机内部。
软件定时器基于一个内部的由Linux操作系统提供的定时器ITIMER_REAL,实际的定时工作都由该定时器完成。定时器ITIMER_REAL每次 超时时,调用update_timers()更新定时器集合,将超时的定时器的set位置位,并查询定时器集合中所有已经启动的定时器,选择expire 值最小的那个定时器,用该expire值来重置定时器ITIMER_REAL,并更新定时器集合中所有已启动定时器的expire值。也就是说在该 expire毫秒后,定时器ITIMER_REAL将重新发生超时中断,重复以上过程。如果没有软件定时器被启动,定时器ITIMER_REAL将被清 零,直到下一次调用start_timer()。
如果在两次中断之间调用start_timer(struct Timer *T),将会比较T->expire值和离下一次时钟中断的时间间隔time_remain。如果T->expire小于 time_remain,则将把T作为最小定时器,用T->expire重置内部定时器ITIMER_REAL,并更新定时器集合中所有已启动定时 器的expire值;如果T->expire不小于time_remain,则只需更新T的expire值。
stop_timer(struct Timer *T)只需将T的使用标识位insue置零,在更新定时器集合时就会被自动忽略。

部分代码如下:
程序soft_timer.c:

  1. #include "soft_timer.h"
  2. int delta = 10;
  3. long start = 0;
  4. struct itimerval phy_timer;
  5. struct itimerval old_timer;
  6. struct Timer *cur_timer;

  7. void update_timers(int sig)
  8. {
  9.        int i = 0;
  10.        int min_timer = -1;
  11.        long min_expire = 1000000000;

  12.        if(cur_timer->inuse)cur_timer->set = 1;

  13.        for(i=0; i<MAX_TIMERS; i++){
  14.             if(T.inuse && !T.set){
  15.                      if(T.expire<delta){
  16.                                T.set = 1;
  17.                      }else if(T.expire > 0 && min_expire>T.expire){
  18.                                min_expire = T.expire;
  19.                                min_timer = i;
  20.                      }
  21.             }
  22.        }

  23.        if(min_timer<0){
  24.             timerclear(&(phy_timer.it_value));
  25.             timerclear(&(phy_timer.it_interval));
  26.        }else{
  27.             phy_timer.it_value.tv_sec = min_expire/1000;
  28.             phy_timer.it_value.tv_usec = (min_expire%1000)*1000;
  29.             timerclear(&(phy_timer.it_interval));
  30.             cur_timer = &T[min_timer];
  31.             for(i=0; i<MAX_TIMERS; i++){
  32.                      if(T.inuse && !T.set){
  33.                                T.expire -= min_expire;
  34.                      }
  35.             }
  36.        }

  37.        setitimer(ITIMER_REAL, &phy_timer, NULL);
  38. }

  39. int create_phy_timer(struct itimerval *timer, void (*handler)(int))
  40. {
  41. int rc = 0;
  42.        struct sigaction sa;
  43.        memset (&sa, 0, sizeof (sa));
  44.        sa.sa_handler = handler;
  45.        sigaction(SIGALRM, &sa, NULL);

  46.        timerclear(&(timer->it_value));
  47.        timerclear(&(timer->it_interval));
  48.       
  49.        setitimer(ITIMER_REAL, timer, NULL);

  50.        return rc;

  51. }

  52. int init_timers()
  53. {
  54. int ret = 0;
  55.        int i = 0;
  56.        for(i=0;i<MAX_TIMERS;i++){
  57.             T.inuse = 0;
  58.             T.param = 0;
  59.             T.set = 0;
  60.             T.timeout = 0;
  61.             T.expire = 0;
  62.        }
  63. cur_timer = &T[0];
  64.        create_phy_timer(&phy_timer, update_timers);
  65. }

  66. int start_timer(struct Timer *t)
  67. {
  68. int ret = 0;
  69.        int i = 0;
  70.        long diff = 0;
  71.        long time_remain;

  72.        t->expire = t->timeout;
  73.        t->inuse = 1;
  74.        t->set = 0;
  75.        getitimer(ITIMER_REAL, &old_timer);

  76.        time_remain = old_timer.it_value.tv_sec*1000+old_timer.it_value.tv_usec/1000;
  77.        //printf("time_remain=%ld\n",time_remain);
  78.        if(time_remain==0){
  79.             
  80.             phy_timer.it_value.tv_sec = t->timeout/1000;
  81.             phy_timer.it_value.tv_usec = (t->timeout%1000)*1000;
  82.             timerclear(&(phy_timer.it_interval));
  83.             setitimer(ITIMER_REAL, &phy_timer, NULL);
  84.             cur_timer = t;
  85.             return ret;
  86.        }
  87.       
  88.        if(t->timeout+delta<=time_remain){
  89.             diff = time_remain - t->timeout;

  90.             for(i=0; i<MAX_TIMERS; i++){
  91.                      
  92.                      if(cur_timer==&T){
  93.                                cur_timer->expire = diff;
  94.                      }else if(t==&T){
  95.                      }else if(T.inuse && !T.set){
  96.                                T.expire +=   diff;
  97.                      }
  98.             }

  99.             phy_timer.it_value.tv_sec = t->timeout/1000;
  100.             phy_timer.it_value.tv_usec = (t->timeout%1000)*1000;
  101.             timerclear(&(phy_timer.it_interval));
  102.             setitimer(ITIMER_REAL, &phy_timer, NULL);
  103.             cur_timer = t;

  104.             }else{
  105.                      t->expire = t->timeout - time_remain;
  106.                      //printf("t->expire =%ld\n", t->expire);
  107.             }
  108.        return ret;
  109.       
  110. }
  111. int stop_timer(struct Timer *t)
  112. {
  113.        int ret = 0;
  114.        t->inuse = 0;
  115.        t->expire = t->timeout;
  116.        t->set = 0;
  117.        return ret;
  118.       
  119. }
  120. long current_millis()
  121. {
  122.        struct timeval tv;
  123.        long   now;
  124.        gettimeofday(&tv, NULL);
  125.        now = (tv.tv_sec%100000)*1000+tv.tv_usec/1000;
  126.        return now;
  127. }

  128. void sleep_millis(long ms)
  129. {
  130.        struct timespec tv;
  131.        tv.tv_sec = ms/1000;
  132.        tv.tv_nsec = (long)(ms%1000)*1000000;

  133.        nanosleep(&tv, NULL);
  134. }


复制代码


soft_timer.h头文件如下:

  1. #define MAX_TIMERS N

  2. struct Timer{
  3.        long timeout;
  4.        long expire;
  5.        int inuse;
  6.        int set;
  7.        int signal;
  8.        int param;
  9. }T[MAX_TIMERS];


  10. extern int init_timers();
  11. extern int start_timer(struct Timer *t);
  12. extern int stop_timer(struct Timer *t);
  13. extern int start_phy_timer(struct Timer *t, void (*handler)(int));
  14. extern int stop_phy_timer(struct Timer *t);

  15. extern long current_millis();
  16. extern void sleep_millis(long ms);

  17. #ifdef __cplusplus
  18. }
  19. #endif

  20. #endif /*__soft_timer_h*/
复制代码



在调用的时候可以先将其初始化

  1.        init_timers();
  2.        for(i = 1; i< MAX_TIMERS; i++){
  3.             if(i<N_TIMERS){
  4.                      T.timeout = timeouts;
  5.                      T.signal = time_events;
  6.             }else{
  7.                      T.timeout = T[13].timeout;
  8.                      T.signal = T[13].signal;
  9.             }
  10.        }

复制代码


随后在适当的时刻start_timer(&T[n]);或者stop_timer(&T[n]);就可以了

论坛徽章:
0
4 [报告]
发表于 2009-03-02 19:58 |只看该作者

回复 #3 T-bagwell 的帖子

谢谢你,我先学习一下!

论坛徽章:
0
5 [报告]
发表于 2009-03-02 23:19 |只看该作者
学习了,反正就得用定时器实现
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP