您的位置:首页 > 大数据 > 人工智能

Linux Posix Timer使用(转载自http://blog.csdn.net/hongszh/article/details/8608781)

2017-06-21 22:44 716 查看
初学者,大家多指教。最近用Qt在ARM9上做开发,开了多个线程,其中一个线程用到了QTimer,每隔50ms触发一次,可是程序执行一会,报出
GLib:ERROR:gmain.c:1963:g_main_dispatch: assertion failed: (current->dispatching_sources == ¤t_source_link)
Aborted 错误.查找问题,在QTimer的start有问题,项目紧张,也找不出其他可能引起问题的地方了。姑且暂用Posix Timer,代替QTimer.本篇文章介绍的很详细。


本文转载自转载自http://blog.csdn.net/hongszh/article/details/8608781:

最强大的定时器接口来自POSIX时钟系列,其创建、初始化以及删除一个定时器的行动被分为三个不同的函数:timer_create()(创建定时器)、timer_settime()(初始化定时器)以及timer_delete(销毁它)。

man timer_create/timer_settime,可以看到man帮助的详细文档:

[cpp] view
plain copy

TIMER_CREATE(2)                                      Linux Programmer's Manual    

  

NAME  

       timer_create - create a POSIX per-process timer  

  

SYNOPSIS  

       #include <signal.h>  

       #include <time.h>  

  

       int timer_create(clockid_t clockid, struct sigevent *sevp,  

                        timer_t *timerid);  

       int timer_settime(timer_t timerid, int flags,  

                         const struct itimerspec *new_value,  

                         struct itimerspec * old_value);  

       int timer_gettime(timer_t timerid, struct itimerspec *curr_value);  

我的实现如下:

1. 定义timer timeout的函数指针类型: 

[cpp] view
plain copy

typedef void (*timerTimeout)(union sigval sig);  

2. 为我们的GstPlayer定义两个timer ID:

[cpp] view
plain copy

timer_t  mSeekTimer;  

timer_t  mPrepareAsyncTimer;  

 
3. 定义createTimer函数,创建timer,设置timeout函数
    timerId: 输入输出参数
    func:    timer timeout函数

[cpp] view
plain copy

void createTimer(timer_t *timerId, timerTimeout func)  

{  

    struct sigevent sev;  

  

    sev.sigev_notify = SIGEV_THREAD;  

    sev.sigev_signo = SIGRTMIN;  

    sev.sigev_value.sival_ptr = gPlayer;  

    sev.sigev_notify_function = func;  

    sev.sigev_notify_attributes = NULL;  

  

    /* create timer */  

    if (timer_create (CLOCK_REALTIME, &sev, timerId) == -1)  

    {  

        ERR ("timer_create, error");  

        return;  

    }  

  

    if (*timerId == -1)  

        ERR  ("timer_create error, id is -1");  

    return;  

}  

4. setTimer函数, 调用Linux的timer_settime, 如果还没到time out,重置之前的timer

如果已经time out,那就得重新调用createTimer生成有效的timer ID,然后才能调用setTimer开始定时器计时。

-这里,将interval参数设置为0,指定我的定时器不工作在循环模式。
-timeMSec是输入参数,指定time out的时间,单位为毫秒。

[cpp] view
plain copy

void setTimer(timer_t *timerId, int timeMSec)  

{  

    struct itimerspec its;  

  

    /* Start the timer */  

    its.it_value.tv_sec = timeMSec / 1000;  

    its.it_value.tv_nsec = (timeMSec % 1000) * 1000000;  

  

    its.it_interval.tv_sec = 0;  

    its.it_interval.tv_nsec = 0;  

  

    if (timer_settime (*timerId, 0, &its, NULL) == -1)  

    {  

        ERR ("timer_settime error");  

    }  

    DEBUG ("call timer_settime reset timer done.");  

    return;  

}  

seekTimerTimeout函数,time out以后,销毁之前调用createTimer创建的timer,完成time out后要做的工作

[cpp] view
plain copy

void seekTimerTimeout(union sigval sig)  

{  

    GstPlayer *player = (GstPlayerplayer*)sig.sival_ptr;  

    if (player->mSeekTimer != -1)  

    {  

        DEBUG("timeout, delete timer:Id = %d",  

                player->mSeekTimer);  

        timer_delete(player->mSeekTimer);  

        player->mSeekTimer = -1;  

    }  

    // ... 完成time out后要做的工作  

}  

prepareAsyncTimeout的time out函数:

[cpp] view
plain copy

void prepareAsyncTimeout(union sigval sig)  

{  

    GstStateChangeReturn state_return;  

    GstPlayer *player = (GstPlayerplayer*)sig.sival_ptr;  

  

    if (player->mPrepareAsyncTimer != -1)  

    {  

        DEBUG("timeout, delete timer:Id = %d",  

                player->mPrepareAsyncTimer);  

        timer_delete(player->mPrepareAsyncTimer);  

        player->mPrepareAsyncTimer = -1;  

    }  

  

    // ...完成time out后要做的工作  

}  

调用一:

[cpp] view
plain copy

创建timer,设定prepareAsyncTimeout  

开始timer,timeout时间为500ms  

  

        createTimer(&mPrepareAsyncTimer, prepareAsyncTimeout);  

        setTimer(&mPrepareAsyncTimer, 500/*ms*/);  

调用二: 

[cpp] view
plain copy

创建timer,设定timeout回调函数。  

    // create timer  

    if (mSeekTimer == -1)  

    {  

        createTimer(&mSeekTimer, seekTimerTimeout);  

    }  

  

判断mSeekTimer是否有效,有效,计算到timeout的剩余时间,如果还没到timeout,重置timer,  

开始新的计时。  

    // if timer exist and not expire, reset timer.  

    if (mSeekTimer != -1)  

    {  

        gulong remaining = 0; //us  

        struct itimerspec its;  

  

        timer_gettime(mSeekTimer, &its);  

        remaining = its.it_value.tv_sec * 1000000  

                   its.it_value.tv_nsec / 1000;  

        DEBUG ("-- remaining time = %lu us", remaining);  

        if ((100/*ms*/ * 1000 - remaining) > 0)  

        {  

           setTimer(&mSeekTimer, 100/*ms*/);  

           DEBUG ("the new seek interval < 100ms, return");  

           mSeekCount = 1;  

           return TRUE;  

        }  

    }  

参考: http://blog.163.com/zheng_he_xiang/blog/static/18650532620116311020390/ http://blog.csdn.net/leo9150285/article/details/8271910
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: