Qnx定时器的使用
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_value
和it_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
}
}
}
}