LInux编程 解决X11定时器因系统时间改变而失效的缺陷 timer_create使用

     最近公司用了20年的产品,被客户抱怨莫名其妙的图像定在那里,过了好几分钟才恢复正常。经研究发现是因为X11的定时器存在缺陷,每次注册定时器下次执行的时间时,使用的是系统时间,如果系统时间被修改为较早的时间,则定时器任务不会被触发,得系统时间走到注册时间才会触发。

     于是我进行了研究,刚开始考虑用线程加sleep来模拟定时器,后面查阅了资料发现,Linux内核也有定时器接口timer_create,并且它强大之处是可以选择定时器创建的时钟模式,我选用了CLOCK_MONOTONIC模式,即创建一个以系统启动时间为时钟的定时器,它不受系统时间改变的影响。

     timer_create在创建时还可以选择用线程还是信号的方式,一开始我用了线程方式,发现它是每次定时器触发都会新建一个线程,当定时器触发频繁的时候这样并不好,所以后面我改用了信号触发的方式。  

     因为timer_create在一个进程中只能创建一个定时器,所以我们只能用它创建一个原子定时器,然后通过加定时器任务的方式实现多个定时器。

     那么定时器加好后,能不能直接在定时器里面处理画图等工作呢,答案是不能。因为信号中断如果发生在malloc加锁处,在定时器处理中也遇到malloc,将会死锁。所以我想是不是可以使用事件触发,XSendEvent将定时器任务当做事件发到主事件循环中去,发现XtAppNextEvent它又是阻塞的,当界面有操作,这个接口才会触发返回,XSendEvent发过去的事件不会唤醒它。后面通过查阅资料发现XtAppAddWorkProc,它可以添加工作函数在后台执行,即XtAppNextEvent阻塞时,没事做的时候,就执行XtAppAddWorkProc添加的工作函数。

     XtAppAddWorkProc添加的工作函数只有在其执行完后,返回FALSE,消息循环才会再次调用工作函数。所以,为了避免因阻塞导致,工作函数不被循环调用,在工作函数中可以用AddTimer把工作函数添加到消息队列中排队,也可以用其他发消息的方式。

     当然,实际过程比上面讲的更复杂曲折,这里写文简略了,分享出来,就是让后来人少走弯路,确实这块儿东西,网上的资料太少了。同时留个记录,也方便自己日后查阅。

     下面贴上主要代码:

      CApp.h

#include <signal.h>
#include <time.h>
#include <vector>
using namespace std;
struct M_SubTimerTask
{
    int id;
    int value;//定时时间(ms)
    int interval; //间隔时间(ms)
    int intervaltemp;
    void(*handler)(); //处理函数
};
extern vector <M_SubTimerTask> g_SubTimerTasks;
extern timer_t g_TimerId;

typedef void (*TimerThreadHandlerType) (sigval_t);
int M_AddTimer(TimerThreadHandlerType handle, timer_t *retTimeId, int id);
int M_StartTimer(timer_t timer, __time_t value_sec, long int value_nsec, __time_t interval_sec, long int interval_nsec);
void M_DeleteTimer(timer_t timerid);

int M_AddSubTimerTask(void (*handle)(), int value, int interval);
void M_DeleteSubTimerTask(int id);

class CApp : public CAppContext
{
    ...
    public:
    int tm1,tm2,tm3,tm4,tm5,tm6,tm7,tm8,tm9,tm10;
    static void OnTimer1();
    static void OnTimeTimer1();
    static void OnNetTimer1();
    static void OnCheckTimer1();
    static void OnOnceTimer1();
    static void OnAutoBypassTimer1();
    static void OnInitSectorTimer1();
    static void OnAlertViewsTimer1();
    static void OnTimerClearLog1();
    static void OnReadFromFileTimer1();
    static void OnCheckPlanStateTimer1();
    st
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值