zoukankan      html  css  js  c++  java
  • linux定时器的实现方法

    Linux提供定时器机制,可以指定在未来的某个时刻发生某个事件,定时器的结构如下:
    struct timer_list 
    {
        struct list_head list;
        unsigned long expires;
        unsigned long data;
        void (*function)(unsigned long);
    };

    list 实现的时候使用的,和定时器功能无关
    expires 是定时器定时的滴答数(当前的滴答数为 jiffies )
    function 到那个时刻内核调用的函数
    data 由于可能多个定时器调用一个函数,为了使得这个函数能够区分不同的定时器,
    通过在结构中 data 来标识这个定时器,并且通过调用

    function( data )

    使得 function 能区分它们,也就是 data 起到 ID 的作用。

    如何使用

    将定时器加到定时器队列中

    void add_timer(struct timer_list *timer)

    修改定时器的到期时间

    int mod_timer(struct timer_list *timer, unsigned long expires)

    将定时器删除(以后这个定时器将不再起作用)

    int del_timer(struct timer_list * timer)
    如果不要求很精确的话,用 alarm() 和 signal() 就够了
    代码:
       
    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    void sigalrm_fn(int sig)
    {
    	printf("alarm!
    ");
    	alarm(2);
    	return;
    }
    int main(void)
    {
    	signal(SIGALRM,signalrm_fn);
    	alarm(2);
    	while(1)
    	pause();
    }
     
    用select()函数可以实现定时,而且可以将时间精确到毫秒级
     
    #include <stdio.h>
    #include <time.h>
    #include <sys/time.h>
    #include <stdlib.h>
    #include <signal.h>
    int count = 0;
    void set_timer()
    {
            struct itimerval itv, oldtv;
            itv.it_interval.tv_sec = 5;
            itv.it_interval.tv_usec = 0;
            itv.it_value.tv_sec = 5;
            itv.it_value.tv_usec = 0;
     
    
            setitimer(ITIMER_REAL, &itv, &oldtv);
    }
    
    void sigalrm_handler(int sig)
    {
            count++;
            printf("timer signal.. %d
    ", count);
    }
    
    int main()
    {
            signal(SIGALRM, sigalrm_handler);
            set_timer();
            while (count < 1000)
            {}
            exit(0);
    }
    利用定时器机制实现多线程编程
    为了避免Qt系统中多线程编程带来的问题,还可以使用系统中提供的定时器机制来实现类似的功能。定时器机制将并发的事件串行化,简化了对并发事件的处理,从而避免了thread-safe方面问题的出现。
    在下面的例子中,同时有若干个对象需要接收底层发来的消息(可以通过Socket、FIFO等进程间通信机制),而消息是随机收到的,需要有一个GUI主线程专门负责接收消息。当收到消息时主线程初始化相应对象使之开始处理,同时返回,这样主线程就可以始终更新界面显示并接收外界发来的消息,达到同时对多个对象的控制;另一方面,各个对象在处理完消息后需要通知GUI主线程。对于这个问题,可以利用第3节中的用户自定义事件的方法,在主线程中安装一个事件过滤器,来捕捉从各个对象中发来的自定义事件,然后发出信号调用主线程中的一个槽函数。
    另外,也可以利用Qt中的定时器机制实现类似的功能,而又不必担心Thread-safe问题。下面就是有关的代码部分:
    在用户定义的Server类中创建和启动了定时器,并利用connect函数将定时器超时与读取设备文件数据相关联:
    Server:: Server(QWidget *parent) : QWidget(parent)
    {
    readTimer = new QTimer(this);   //创建并启动定时器
       connect(readTimer, SIGNAL(timeout()), this, SLOT(slotReadFile()));   //每当定时器超时时调用函数slotReadFile读取文件
       readTimer->start(100);
    }
    slotReadFile函数负责在定时器超时时,从文件中读取数据,然后重新启动定时器:
    int Server::slotReadFile()    // 消息读取和处理函数
    {
      readTimer->stop();     //暂时停止定时器计时
      ret = read(file, buf );   //读取文件
    if(ret == NULL)
    {    readTimer->start(100);     //当没有新消息时,重新启动定时器
        return(-1);
    }
      else
           根据buf中的内容将消息分发给各个相应的对象处理……;
    readTimer->start(100);    //重新启动定时器
    }
      
    

      

    在该程序中,利用了类似轮循的方式定时对用户指定的设备文件进行读取,根据读到的数据内容将信息发送到各个相应的对象。用户可以在自己的GUI主线程中创建一个Server类,帮助实现底层的消息接收过程,而本身仍然可以处理诸如界面显示的问题。当各个对象完成处理后,通过重新启动定时器继续进行周期性读取底层设备文件的过程。当然,这种方法适合于各对象对事件的处理时间较短,而底层设备发来消息的频率又相对较慢的情况。在这种情况下,上述方法完全可以满足用户的需求,而又避免了处理一些与线程并发有关的复杂问题。
  • 相关阅读:
    python
    python
    python
    Django学习手册
    python
    Django学习手册
    [ThinkPHP] 独立分组配置,坑!!!
    vim 代码片段:通过vundle插件管理器安装ultisnips |centos6.5|vim7.2
    CESHI
    thinkphp实现功能:验证码
  • 原文地址:https://www.cnblogs.com/wuyepeng/p/9788889.html
Copyright © 2011-2022 走看看