【问题标题】:Is it suitable to use usleep as Timer in c是否适合在c中使用usleep作为Timer
【发布时间】:2016-08-09 06:26:52
【问题描述】:

我在 Linux 中做 C 程序。我有一个主线程,它不断更新两个变量的值,其他线程每 20 毫秒将这些变量值写入一个文件。我已经使用 usleep 来实现这个时间间隔。示例代码如下。

 main()
{
 .
 .
 .
 .
 .

 pthread_create(...write_file..);   /* started another thread by passing   a  function write_file */
 while(variable1) 
  {
    updates value of variables 

  }

return 0;
}


void write_file()

{
 .
 .
 .
 .
 fp = fopen("sample.txt" , "a");

 while(variable2)
 {

   fprintf(fp," %d \n", somevariable);

   usleep(20 * 1000);

 }

 fclose(fp);
}

是否适合使用usleep功能达到20毫秒的时间间隔,还是应该使用其他一些方法,如Timer。? 这种睡眠是否足够准确?这个睡眠功能会影响主线程吗?

【问题讨论】:

  • 至少您可以使用gettimeofdayclock_gettime 获取当前时间,并仅在下一个活动缺少的时间睡觉。
  • C11 标准草案 n1570:5.1.2.4 多线程执行和数据竞争 4 如果其中一个修改了内存位置,而另一个读取或修改了相同的内存位置,则两个表达式计算冲突. 25 如果一个程序在不同线程中包含两个相互冲突的操作,则该程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。 TL;DR:sleep() 不是同步。

标签: c multithreading timer pthreads


【解决方案1】:

使用sleep() 系列通常会导致不精确的计时,尤其是当进程有许多消耗 CPU 的线程并且所需的间隔相对较小时,例如 20 毫秒。因此,您不应假设 *sleep() 调用会在指定时间完全阻止执行。对于上述情况,实际睡眠持续时间甚至可能比指定的长两倍或更多(假设内核不是实时的)。因此,您应该实现某种补偿逻辑,以调整后续调用的睡眠持续时间。

更精确(但当然不理想)的方法是使用 POSIX 计时器。见timer_create()。最精确的计时器是使用SIGEV_SIGNALSIGEV_THREAD_ID 通知的计时器(后者仅在Linux 系统上)。作为信号编号,您可以使用实时信号之一(SIGRTMINSIGRTMAX),但请注意 pthread 实现通常在内部使用很少的这些信号,因此您应该谨慎选择实际编号。而且在信号处理程序上下文中做一些事情也需要额外注意,因为不是每个库函数都可以在这里安全地使用。您可以找到安全列表here

附:另请注意,使用空集调用 select() 是一种以亚秒级精度进行睡眠的相当可移植的方式。

【讨论】:

    【解决方案2】:

    睡眠:sleep() 和 usleep()

    现在,让我从更简单的计时调用开始。对于多秒的延迟,最好的选择可能是使用 sleep()。对于至少几十毫秒的延迟(大约 10 毫秒似乎是最小延迟),usleep() 应该可以工作。这些函数将 CPU 分配给其他进程(“睡眠”),因此不会浪费 CPU 时间。有关详细信息,请参阅手册页 sleep(3) 和 usleep(3)。

    对于大约 50 毫秒以下的延迟(取决于您的处理器和机器的速度以及系统负载),放弃 CPU 需要太多时间,因为 Linux 调度程序(对于 x86 架构)通常至少需要大约 10-30 毫秒,然后它将控制权返回给您的进程。因此,在较小的延迟中,usleep(3) 通常延迟比您在参数中指定的量要多一些,至少大约 10 毫秒。

    纳米睡眠()

    在 2.0.x 系列的 Linux 内核中,有一个新的系统调用 nanosleep()(参见 nanosleep(2) 手册页),它允许您在短时间内(几微秒或更长时间)休眠或延迟)。

    对于延迟

    busy loop使用udelay()(很多内核驱动使用的内部内核函数),loop的长度是用BogoMips的值来计算的(这种busy loop的速度是BogoMips的东西之一测量准确)。有关其工作原理的详细信息,请参见 /usr/include/asm/delay.h)。

    来源:http://tldp.org/HOWTO/IO-Port-Programming-4.html

    尝试使用nanosleep() 代替usleep(),20ms 间隔应该更准确。

    【讨论】:

      猜你喜欢
      • 2011-12-30
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-09
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多