c-usleep()来计算运行时间的行为很奇怪



我使用下面的代码计算每个连续调用处理程序函数所用的时间(以毫秒为单位)。当我使用usleep(1000)时,即每次呼叫之间的1ms时间差是10ms,当我使用us leep(1000000)时,例如每次呼叫之间1秒的时间间隔意外地下降到小于1ms。以下是代码片段:

    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/time.h>
    #include<unistd.h>
    struct timeval start_time;
    void handler(int);
    int main()
    {
            struct timeval current_time;
            int i=0;
            gettimeofday(&start_time,0);
            gettimeofday(&current_time,0);
            printf("%012.3fms: emulationbeginsn",((current_time.tv_usec-start_time.tv_usec)/1000.0));
            while(i++<5)
            {
                    usleep(1000); // compare with usleep(1000000)
                    handler(i);
            }
            return 0;
    }
    void handler(int i)
    {
            printf("In Handler %dn",i);
            struct timeval current_time;
            gettimeofday(&current_time,0);
            printf("%012.3fms: Handler Calledn",((current_time.tv_usec-start_time.tv_usec)/1000.0));
            return;
    }

请记住,timeval结构的tv_usec字段永远不会达到(或超过)一百万,而是会增加秒数。

您还必须在计算中使用tv_sec字段。

usleep被指定至少睡你给它的量,但它可以睡得更长。它的睡眠时间几乎没有上限,因为如果操作系统有更重要的进程要运行,它就不必运行进程。

在实践中,usleep将休眠多长时间的分辨率由操作系统使用的时钟决定。直到几年前,大多数类似unix的系统都使用静态100Hz定时器(在某些罕见的情况下为1024Hz)来驱动这样的定时器,所以你的usleep总是被四舍五入到最接近的10ms。

最近,在一些系统上已经做了一些去除静态时钟的工作,尽管这并不是因为需要更高分辨率的睡眠,而是因为不断唤醒cpu进行静态时钟滴答声对功耗不利。它可能会有提高计时器分辨率的副作用,但这反过来又暴露了那些睡眠时间很短、行为正常的应用程序中的错误。突然间,随着usleep/nanosleep/poll/select中的超时分辨率越来越高,这些短暂的睡眠导致应用程序在cpu上旋转,一直在重新安排睡眠。

我不确定今天的情况如何,但从10毫秒来看,你的系统似乎仍然使用100Hz的时钟作为内部计时器,或者它故意将超时降低到10毫秒的分辨率,以防止应用程序中断。

最新更新