0

以下代码定期休眠到预期时间点(ts),并立即获取系统时间(tm2)。ts为什么在和之间存在固定时间误差(~52us)tm2,因为两个时间点相邻。

运行环境是实时打补丁的linux,如果我改变周期性时间间隔的大小,固定时间误差几乎没有变化。

#include <time.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
  
#define US 100         /* sleep US micro-seconds */
#define LOOP 20 
  
double delayed[LOOP]; 
  
int main(void) 
{ 
    int loop = 0; 
    struct timespec tm1, tm2, tm2_old; 
    struct timespec ts; 
  
    clock_gettime(CLOCK_MONOTONIC, &tm1); 
    ts.tv_sec   = tm1.tv_sec; 
    ts.tv_nsec  = tm1.tv_nsec; 
  
    while(1){ 
        ts.tv_nsec  = ts.tv_nsec + US * 1000L; 
        ts.tv_sec   = ts.tv_sec + (ts.tv_nsec)/1000000000L; 
        ts.tv_nsec  = (ts.tv_nsec)%1000000000; 
  
        clock_gettime(CLOCK_MONOTONIC, &tm1); 
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL); 
        clock_gettime(CLOCK_MONOTONIC, &tm2); 
  
        delayed[loop] = (tm2.tv_sec-ts.tv_sec)*1000000.0 + \ 
                (tm2.tv_nsec - ts.tv_nsec)/1000.0; 
        ++loop; 
        if(loop >= LOOP) break; 
    } 
    for(int ii=0; ii<LOOP; ++ii){ 
        printf("delayed %4.2f\n", delayed[ii]); 
    } 
}

运行结果:

 delayed 55.62 
 delayed 53.02 
 delayed 52.47 
 delayed 52.30 
 delayed 52.25 
 delayed 52.32 
 delayed 52.30 
 delayed 52.45 
 delayed 52.28 
 delayed 52.29 
 delayed 52.16 
 delayed 52.16 
 delayed 52.19 
 delayed 52.28 
 delayed 52.26 
 delayed 52.23 
 delayed 52.24 
 delayed 52.26 
 delayed 52.32 
 delayed 52.15
4

1 回答 1

0

timerslack在 Linux 内核 4.6 中引入,用于对 CPU 功耗的定时器到期进行分组。

内核使用“当前”计时器松弛来对彼此接近的调用线程的计时器到期进行分组;因此,线程的计时器到期可能会延迟到指定的纳秒数(但永远不会提前到期)。分组定时器到期可以通过最大限度地减少 CPU 唤醒来帮助降低系统功耗。

引自Prctl Linux 手册

用户可以timerslack通过编辑文件来改变值/proc/{self}/timerslack_ns

于 2020-07-03T14:28:56.513 回答