请问xtang先生以及其他的大虾,关于QNX6.5下定时器的精度可以达到多少,可以达到微秒级别吗?

我现在在需要高精度定时(微秒级别),可是发现定时器运行的时候,定时精度达不到我的要求,即使是timer_creat()产生的定时器,依旧出现较大的误差。我改如何解决问题的。
如下是我参考QNX下的例程,稍作修改,希望可以在每10us打印一句话,可是发现,我使用时间戳来计时和定时器的10us差距挺大。

/*
/*
 * Demonstrate how to set up a timer that, on expiry,
 * sends us a pulse.  This example sets the first
 * expiry to 10 us and the repetition interval
 * to 10 us.
 */

#include <stdio.h>
#include <time.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdlib.h>


#define MY_PULSE_CODE   _PULSE_CODE_MINAVAIL
#define NSEC_PER_SEC 1000000000

typedef union 
{
        struct _pulse   pulse;
        /* your other message structures would go here too */
} my_message_t;

main()
{
   struct sigevent         event;
   struct itimerspec       itime;
   struct timespec stop,start,res;
   struct _clockperiod *new;
   timer_t                 timer_id;
   int                     chid;
   int                     rcvid;
   my_message_t            msg;

   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 = MY_PULSE_CODE;

   new = (struct _clockperiod *)malloc(sizeof(struct _clockperiod));
   new->nsec = 1000L;
   new->fract = 0L;
   ClockPeriod(CLOCK_REALTIME,new,NULL,0);
   free(new);

   	if ( clock_getres( CLOCK_REALTIME, &res) == -1 )
   	{
         perror( "clock get resolution" );
         return EXIT_FAILURE;
   	}

   printf("The resolution is %ld ns.\n\n\n",res.tv_nsec);
   timer_create(CLOCK_REALTIME, &event, &timer_id);

   itime.it_value.tv_sec = 0;
   /* 10,000 nsecs = 10us */
   itime.it_value.tv_nsec = 10000;
   itime.it_interval.tv_sec = 0;
   /* 10,000 nsecs = 10 us */
   itime.it_interval.tv_nsec = 10000;
   timer_settime(timer_id, 0, &itime, NULL);

   /*
    * As of the timer_settime(), we will receive our pulse
    * in 10 microseconds (the itime.it_value) and every 10
    * microseconds thereafter (the itime.it_interval)
    */

   for (;;)
   {
       rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
       
       if (rcvid == 0)
       { /* we got a pulse */
            if (msg.pulse.code == MY_PULSE_CODE)
            {
            	clock_gettime( CLOCK_REALTIME, &stop) == -1;
                printf("we got a pulse from our timer\n");
                printf("The sample time %ld ns.\n",(stop.tv_sec - start.tv_sec)*NSEC_PER_SEC + stop.tv_nsec-start.tv_nsec);
                start = stop;
            } /* else other pulses ... */
       } /* else other messages ... */
   }
}

运行的部分结果

we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our timer
The sample time 999847 ns.
we got a pulse from our time

先让我们同意一下标称。

1秒 = 1000 毫秒 = 1000000 微秒 = 1000000000 纳秒
1s = 1000ms = 1000000us = 1000000000 ns

QNX的系统时钟精度标准是1微秒 (在CPU速度低于40MHz时,是10微秒)。

时钟精度是可调的,就像你的程序里用的那样。但有个上下限。具体值我忘了,好象是10us级别。当然,调整系统时钟精度会影响系统性能,这是另一个话题了。

至于你观察到的现像,具体解释可以看看下面这个白皮书。这个是写kernel的人写的,可以帮助你理解误差是怎样形成的。

http://www.qnx.com/developers/docs/6.4.1/neutrino/prog/timing.html?lang=cn

好的,谢谢,请问,如果我们想在每一段时间(数十微秒)触发一件事情,误差不能太多,除了定时器的方式还有别的方式么?

如果需要高精度的时钟,通常做法,是自己找一个高精度的中断源,以它为高精度时钟标准。而不是修改系统时钟,因为这样会增加系统负担。

那对于x86架构下的pc,工控机而言,有比较好的方式么。对于它们而已,引入外部时钟源不易操作。

请问我可不可以以软件的方式来实现较高精度的定时器么。因为我看到网上有一篇文章说过说“此外Posix1.b中为我们提供了实时高精度的定时工具,精度可以达到纳秒。不过每个进程只能有一个”。
地址为http://os.51cto.com/art/201104/256687.htm,QNX不是也遵循POSIX1.b么?难道是此文章的作者笔误? :laughing:
PS.感觉我问的问题都好弱哈~~ :blush:

首先,你要问一下自己,你真的需要高精度时钟吗?如果是为了计时(计算两件事情之间的时间长度),那么你不需要时钟。

时钟总是依赖于某个中断输入的,纯用软件似乎是无法定时的。

x86的体系结构,我记得只提供一个时钟源。如果精确到某个特定的CPU,则有可能有更多的时钟源。工控机,则一般会有自己的多个时钟源。但所有这些,都需要知道具体你的硬件情况,然后,有针对的编程实现高精度时钟。

至于你提到的文章,作者没什么问题。POSIX提供的是如何使用一个时钟的用户接口,至于系统是如何实现时钟的,则不在POSIX考虑的范围之内。