Qnx定时器的使用

2019-11-26  本文已影响0人  jackniu_ae28
1.创建定时器

QNX定时器首先需要创建一个定时器对象,设置通知类型,一般包括信号、脉冲或线程创建,并创建通知结构(结构sigevent),设置定时类型 (相对与绝对,一次与周期),最后启动它。

   int timer_create( clockid_t clock_id,        struct sigevent * evp,          timer_t * timerid )

第一个参数指向时钟源,分为三类,分别是CLOCK_REALTIME、CLOCK_SOFTTIME、CLOCK_MONOTONIC。
CLOCK_REALTIM: 标准POSIX定义的时钟,如果它处于省电模式,基于这个时钟的定时器可以唤醒处理器。
CLOCK_SOFTTIME:这个时钟只在处理器不处于节电模式时才激活。例如,使用CLOCK_SOFTTIME计时器休眠的应用程序不会在应用程序应该唤醒时唤醒处理器。这将允许处理器进入省电模式。
CLOCK_MONOTONIC:这个时钟总是固定定时增加,无法调整
第二个参数是指向结构sigevent数据结构的指针。这个数据结构用于通知内核,在“触发”时,计时器应该传递什么类型的事件。
第三个参数指向timer_t对象的指针,函数在该对象中存储新定时器参数,如定时周期和启动时间。

2 设置定时器

创建了定时器之后,现在必须决定它是哪种类型的定时器。由timer_settime()的参数组合完成的,timer_settime()函数用于实际启动计时器:

      int timer_settime (timer_t timerid,       int flags,    struct itimerspec *value,      struct itimerspec *oldvalue);

timerid 参数是从 timer_create() 函数调用中得到的值,创建一组计时器,然后在它们上分别调用timer_settime() 来设置和启动它们。
flags参数就是指定绝对与相对标志。如果传递常量TIMER_ABSTIME,那么它就是绝对的,与预期的差不多。然后,在希望计时器关闭的时候传递实际的日期和时间。如果传递一个0,那么计时器将被视为相对于当前时间,那如何指定时间。以下是两个数据结构的关键部分():

   struct timespec {
            long    tv_sec,
                tv_nsec;
    };
   struct itimerspec {
            struct timespec it_value,   //单次启动时间
                        it_interval;              //定时时间
   };

it_value指定从现在开始计时器应该停止多长时间(在相对计时器的情况下),或者计时器应该停止的时间(在绝对计时器的情况下)。一旦计时器触发,it_interval值指定一个相对值来重新加载计时器,以便它能够再次触发。注意,为it_interval指定一个值为0,使它成为一个一次性定时器。创建一个定期计时器,将it_interval设置为reload值,并将it_value设置为零it_valueit_interval成员实际上都是类型
struct timespec的结构,另一个POSIX对象。该结构允许指定秒分辨率。第一个成员,tv_sec,是秒数;第二个成员tv_nsec是当前秒内的纳秒数。

例子1 创建一个单次运行时钟
it_value.tv_sec = 5;
it_value.tv_nsec = 500000000;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 0;

这将创建一个一次性计时器,在5.5秒内关闭。这是一个相对计时器,因为如果不是的话,那么这个时间早就过去了(比1970年1月1日晚5.5秒,GMT时间00:00)。
这是另一个例子:

it_value.tv_sec = 987654321;
it_value.tv_nsec = 0;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 0;

这就产生了一个一次性计时器,在美国东部时间2001年4月19日星期四00:25:21开始计时。(有一大堆函数可读的日期和“自1970年1月1日以来的秒数”之间转换。查看time()asctime()ctime()mktime()strftime()等C库。对于这个例子,我们假设它是一个绝对计时器,因为如果它是相对的会等待大量的秒(987654321秒大约是31.3年)。
最后一个例子:

it_value.tv_sec = 1;
it_value.tv_nsec = 0;
it_interval.tv_sec = 0;
it_interval.tv_nsec = 500000000;

假设它是相对的,这个定时器将会在一秒内停止,然后每隔半秒再次停止。完全不需要重新加载的值看起来像一次性的值。

例子2 定时器实例程序
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>
 
typedef union {
      struct _pulse   pulse;
        int dat;
      
} my_message_t;

my_message_t st;
void testpidsigal()
{


    st.dat++;
    printf("hello world\r\n");
}
#define MY_PULSE_CODE   _PULSE_CODE_MINAVAIL
int main(int argc, char *argv[])
{
 
   struct sigevent         event;
   struct itimerspec       itime;
   timer_t                 timer_id,timer_id1;
   int                     chid;
   int                     rcvid;
   my_message_t            msg;
   void (*testprt)();
 
   chid = ChannelCreate(0);/*创建通道*/

 /*  event.sigev_notify = SIGEV_PULSE;
   event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0,
                                    chid,
                                    _NTO_SIDE_CHANNEL, 0);
   event.sigev_priority = getprio(0);
   event.sigev_code = 1;*/

   SIGEV_PULSE_INIT(&event, ConnectAttach(ND_LOCAL_NODE, 0,chid,_NTO_SIDE_CHANNEL, 0), getprio(0), 1, &testpidsigal);

   timer_create(CLOCK_REALTIME, &event, &timer_id);
 
 
    /*it_value 设定的是第一次初始化值*/
   itime.it_value.tv_sec =1;
   /* 500 million nsecs = .5 secs */
   itime.it_value.tv_nsec = 500000000;
   /*it_interval 设定的是每次间隔值*/
   itime.it_interval.tv_sec = 1;
   /* 500 million nsecs = .5 secs */
   itime.it_interval.tv_nsec = 500000000;
   timer_settime(timer_id, 0, &itime, NULL);
 
 

   for (;;) {
       rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
       if (rcvid == 0) { /* 收到一个脉冲 */
            if (msg.pulse.code == 1) {
                printf("we got a pulse from our timer %d\n",msg.pulse.code);//获取脉冲代码
                testprt=msg.pulse.value.sival_ptr;
                testprt();//这里打印Helloworld
            }
                }
     }

}
上一篇下一篇

猜你喜欢

热点阅读