C hr定时器不工作';如果过期,则返回负值

C hr定时器不工作';如果过期,则返回负值,c,timer,kernel,linux-device-driver,kernel-module,C,Timer,Kernel,Linux Device Driver,Kernel Module,当计时器过期时(我预计为负100毫秒),我得到的不是负值,而是+800毫秒,这非常接近,我无法在预期结果和实际结果之间建立任何联系。 我的第一个教训是,要么hrtimer_get_remaining要么ktime_to_timeval做错了什么,所以我用ktime_to_timespec和hrtimer_expires_remaining,但结果是一样的 还有其他建议吗?Short unswer 也许你得到了正确的结果,但你的解释是错误的。您的代码只检查了tv\u nsec忽略了tv\u sec

当计时器过期时(我预计为负100毫秒),我得到的不是负值,而是+800毫秒,这非常接近,我无法在预期结果和实际结果之间建立任何联系。
我的第一个教训是,要么hrtimer_get_remaining要么ktime_to_timeval做错了什么,所以我用ktime_to_timespec和hrtimer_expires_remaining,但结果是一样的

还有其他建议吗?

Short unswer 也许你得到了正确的结果,但你的解释是错误的。您的代码只检查了
tv\u nsec
忽略了
tv\u sec
,它可能包含
-1
。如果您添加
-1
秒和略大于
800ms
,您将获得~
-100ms

更长的解释 即使
ns_to_timespec
没有像一段时间前那样调用
set_normalized_timespec
,它仍然以相同的方式规范化timespec值。以下是此函数的当前版本:

timeval v = ktime_to_timeval(hrtimer_get_remaining(timer));
此行为由POSIX标准定义。例如,在发出
nanosleep()
函数(
rqtp
类型为
struct timespec*
)后,您可能会遇到以下错误:

下面是Linux手册页中的类似定义:

结构timespec用于指定纳秒精度的时间间隔。其定义如下:

[EINVAL]
  The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 millio
请注意,在这两种情况下,都没有关于负片
tv_sec
无效的信息

简单证明 下面是一个简单的内核模块,它证明了我的观点:

struct timespec {
    time_t tv_sec;        /* seconds */
    long   tv_nsec;       /* nanoseconds */
};

The value of the nanoseconds field must be in the range 0 to 999999999. 

你能检查一下你的电视节目吗?是不是
-1
?负时间值的解释有点奇怪。如果使用%ld打印,对于某些计时器,我会得到-97、-128、-147之类的值(我真的不明白为什么,因为这些计时器不是很旧)。但是,对于我关心的计时器,我应该接收~-200毫秒,事实上,我每秒接收-1,微秒接收800000。我不确定我是否应该进一步依赖它,因为我不理解其他负值。@Cumatru:也许这很奇怪,但POSIX标准就是这样定义的。使用%ld打印时获得-97是什么意思?您实际打印的值是多少?
Note: The tv_nsec part is always in the range of
0 <= tv_nsec < NSEC_PER_SEC
For negative values only the tv_sec field is negative !
[EINVAL]
  The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 millio
struct timespec {
    time_t tv_sec;        /* seconds */
    long   tv_nsec;       /* nanoseconds */
};

The value of the nanoseconds field must be in the range 0 to 999999999. 
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
    struct timeval v = ktime_to_timeval((ktime_t){.tv64 = -200000000});
    printk(KERN_INFO "v= %ld, %ld\n", v.tv_sec, v.tv_usec);

    return -1;
}
v= -1, 800000