【问题标题】:the use of getitimer and setitimer in CC语言中getitimer和setitimer的使用
【发布时间】:2016-02-27 05:15:05
【问题描述】:

我正在编写以下 C 代码来获取使用 getitimer 和 setitimer 执行简单操作所花费的时间。

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>

#define INTERVAL 1        /* number of milliseconds to go off */

int main() {
    double sum = 0;
    struct itimerval initial, updated;

    initial.it_value.tv_sec     = INTERVAL;
    initial.it_value.tv_usec    = 999999;
    initial.it_interval = initial.it_value;
    memcpy(&(initial.it_interval), &(initial.it_value), sizeof( initial.it_value )); 
    printf("%ld\n", initial.it_value.tv_usec);

    if (setitimer(ITIMER_VIRTUAL, &initial, NULL) == -1) {
        perror("error calling setitimer()");
        exit(1);
    }

    for (unsigned int i; i < 100; i++) 
        sum += 1./i;

    if (getitimer(ITIMER_REAL, &updated) == -1) {
        perror("error calling getitimer()");
        exit(1);
    }

    printf("Time started = %ld\n; Time ended = %ld\n: Time taken = %ld\n",
           initial.it_value.tv_usec, updated.it_value.tv_usec,
           initial.it_value.tv_usec - updated.it_value.tv_usec);
    return 0;
}

我已经编译了:

$ gcc -o timer -std=c99 -Wall -pedantic getitimer.c -lrt -03

但是,我的答案始终是 999999(我提高和降低了 100):

 ./timer 
999999
Time started = 999999
; Time endd = 0
: Time taken = 999999

我的错误是什么?另外,我想问一下使用这样的程序可以获得的最高精度是多少?

非常感谢!

【问题讨论】:

  • 编辑后的代码不是改进。值 INT_MAX 超出了tv_usec 组件的允许值范围(有效范围为 0..999999 微秒),因此出现错误。
  • 谢谢!但是,无论我的循环有多大或多小,最后我都会得到 0。

标签: c time setitimer


【解决方案1】:

我看到的主要是除法运算使用整数除法。所以:

initial.it_value.tv_sec     = INTERVAL/1000000;

在 tv.sec 中放置 0

initial.it_value.tv_usec    = (INTERVAL/1000000) * 1000000;

在 tv_usec 中放置 0

initial.it_interval = initial.it_value;

通常,在分配多字段结构时,使用memcpy() 而不是直接分配。 (直接赋值适用于初始化,但不适用于赋值。)

因此,发布的代码将“间隔”设置为 0

当然,结果值为 0

这是 setitimer() 和 getitimer() 手册页中的关键语句

"定时器从 it_value 递减到零,产生一个信号,然后复位到 it_interval。设置为零的计时器(it_value 为零或计时器到期且 it_interval 为零)停止。"

建议:以下编辑

initial.it_value.tv_set = INTERVAL;
initial.it_value.tv_usec = 0;

memcpy( &(initial.it_interval), &(initial.it_value), sizeof( initial.it_value ) );

...

【讨论】:

  • “使用memcpy() 而不是分配”背后的原因是什么?这对我来说似乎非常可疑。
  • 这不起作用:实际上甚至无法编译。我想我没有得到建议!
  • @user3236841,我确实看到了在我应该输入 tv_usec 时输入 tvuser 的按键错误。但是,该按键错误对您来说应该是显而易见的。顺便说一句:我刚刚编译/运行了您发布的代码,并带有我建议的修改,它编译得很干净。它运行并产生了预期的输出。
  • 对不起,我之前做了更正,代码没有编译。这是我得到的:getitimer.c:在函数'main'中:getitimer.c:16:10:错误:'memcpy'memcpy(initial.it_interval,initial.it_value,sizeof(initial.it_value)的参数1的类型不兼容));等等............你能发布你的完整代码吗? ^ 在 getitimer.c:5:0 中包含的文件中:/usr/include/string.h:42:14:注意:预期为 'void *restrict' 但参数类型为 'struct timeval' extern void *memcpy (void * __restrict __dest, const void *__restrict __src, ^
  • T前两个参数给memcpy() function must be the addresses not the contents. Suggest using: memcpy( &(initial.it_interval), &(initial.it_value), sizeof(initial.it_value) );`
【解决方案2】:

setitimergetitimer 不是用于分析的正确函数。它们与 interval timers 相关,后者是在计时器到期时生成警报(更准确的信号)的计时器。

实现您想要的主要选项是clockclock_gettime API。

【讨论】:

  • 此外,POSIX 将 getitimer() 和 [setitimer()] 标记为已过时,您应该改用 timer_gettime() 和 [timer_settime()] 函数。它们具有纳秒级分辨率(它们使用struct timespec 而不是struct timeval)。
  • 这些功能是否允许虚拟计时?我有兴趣找到执行 (unsigned int i; i 指令所花费的时间
【解决方案3】:

最新代码的主要问题是对getitimer() 的调用引用了与setitime() 调用不同的计时器

不过,下面的代码使用起来很简单

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
//#include <limits.h>
//#include <string.h>

// do not place comments on same line as #define statement
// always surround numeric values with parens to avoid 'text replacement' errors
// wrong comment:  number of milliseconds to go off

// number of seconds in interval
#define INTERVAL (1)

// number of usec in interval
#define MICRO_INTERVAL (999999)

int main() {
    //double sum = 0;
    struct itimerval initial;
    struct itimerval updated;

    initial.it_value.tv_sec     = INTERVAL;
    initial.it_value.tv_usec    = MICRO_INTERVAL;
    initial.it_interval.tv_sec  = INTERVAL;
    initial.it_interval.tv_usec = MICRO_INTERVAL;

    // remove this line: initial.it_interval = initial.it_value;
    // remove this line: memcpy(&(initial.it_interval), &(initial.it_value), sizeof( initial.it_value ));
    //printf("%ld\n", initial.it_value.tv_usec);

    printf( "Time value: %ld.%ld\n", initial.it_value.tv_sec, initial.it_value.tv_usec );
    printf( "Time interval: %ld.%ld\n", initial.it_interval.tv_sec, initial.it_interval.tv_usec );

    if (setitimer(ITIMER_VIRTUAL, &initial, &updated) == -1)
    {
        perror("error calling setitimer()");
        exit(1);
    }

    //for (unsigned int i=0; i < 10; i++)  // must initialize the 'i' variable
    //    sum += 1./i;

    // the 'which' parameter should be 'ITIMER_VIRTUAL'
    //     as that is what was started in the call to setitimer()
    //if (getitimer(ITIMER_REAL, &updated) == -1)
    //{
    //    perror("error calling getitimer()");
    //    exit(1);
    //}

    if (setitimer(ITIMER_VIRTUAL, &initial, &updated) == -1)
    {
        perror("error calling setitimer()");
        exit(1);
    }

    printf( "end interval counter: %ld.%ld\n", updated.it_interval.tv_sec, updated.it_interval.tv_usec );
    printf( "end value counter: %ld.%ld\n", updated.it_value.tv_sec, updated.it_value.tv_usec );

    //printf("Time started = %ld\n; Time ended = %ld\n: Time taken = %ld\n",
    //       initial.it_value.tv_usec, updated.it_value.tv_usec,
    //       initial.it_value.tv_usec - updated.it_value.tv_usec);
    return 0;
}

// accuracy is +/-1 microsecond, not millisecond

即使在两次调用 setitimer() 之间没有做任何事情,结果输出是:

Time value: 1.999999
Time interval: 1.999999
end interval counter: 1.999999
end value counter: 2.3999

【讨论】:

  • 计数器计数up 而不是down,我有点惊讶
猜你喜欢
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-19
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
相关资源
最近更新 更多