nanosleep不适用于不到一秒的值

时间:2014-09-26 16:05:08

标签: c linux sleep

我有一个使用nanosleep的程序(混合C和Fortran,虽然看起来并不相关)。但是,如果我的timespec的{​​{1}}值为0,则它​​根本就不会睡觉。 tv_sec值可能是一整秒的微秒,但它不会睡眠。 (如果tv_nsectv_sec,则可以暂停一秒钟。)为什么会这样?

为了让事情更加混乱,具有适当值的1(即usleep usec)会按预期暂停一会儿。

我在RHEL 5.8和RHEL 6.4框中看到了这个问题。两者都在使用995000

这里是调用nanosleep的函数:

gcc

显然,我实际上并不需要纳秒精度!

我还测试了一个我检查过返回值的版本;它总是void msleep(int *milliseconds) { long usec; struct timespec sleep; usec = (*milliseconds) % 1000; sleep.tv_sec = (*milliseconds) / 1000; sleep.tv_nsec = 1000*usec; nanosleep(&sleep, NULL); } (成功),因此0输出参数(如果被中断则剩余时间)从未设置过。

3 个答案:

答案 0 :(得分:7)

你错过了1000倍。

试试这个:

#define _POSIX_C_SOURCE 199309L /* shall be >= 199309L */

#include <time.h>

void msleep(int *milliseconds)  
{
  int ms_remaining = (*milliseconds) % 1000;
  long usec = ms_remaining * 1000;
  struct timespec ts_sleep;

  ts_sleep.tv_sec = (*milliseconds) / 1000;
  ts_sleep.tv_nsec = 1000*usec;
  nanosleep(&ts_sleep, NULL);
}

更紧凑:

#define _POSIX_C_SOURCE 199309L /* shall be >= 199309L */

#include <time.h>

void msleep(int * pmilliseconds)  
{
  struct timespec ts_sleep = 
  {
    *pmilliseconds / 1000,
    (*pmilliseconds % 1000) * 1000000L
  };

  nanosleep(&ts_sleep, NULL);
}

最后一个完整的实现,包括错误处理和nanosleep()早期被中断的情况:

#define _POSIX_C_SOURCE 199309L

#include <time.h>
#include <errno.h>
#include <stdio.h>

int ms_sleep(unsigned int ms)
{
  int result = 0;

  {
    struct timespec ts_remaining =
    { 
      ms / 1000, 
      (ms % 1000) * 1000000L 
    };

    do
    {
      struct timespec ts_sleep = ts_remaining;
      result = nanosleep(&ts_sleep, &ts_remaining);
    } 
    while ((EINTR == errno) && (-1 == result));
  }

  if (-1 == result)
  {
    perror("nanosleep() failed");
  }

  return result;
}

遵循包装符合OP的要求:

#include <errno.h>
#include <stdio.h>

int ms_sleep(unsigned int);

void msleep(int * pms)
{
  int result = 0;

  if ((NULL == pms) || (0 > *pms)) /* Check for valid input. */
  {
    errno = EINVAL;
    result = -1;
  }
  else 
  {
    result = ms_sleep(*pms));
  }

  if (-1 == result)
  {
    perror("ms_sleep() failed");
    /* Exit and/or log error here. */
  }
}

更新(请参阅下面的chux评论):

至少假设C99,上面这部分代码

  struct timespec ts_sleep = 
  {
    *pmilliseconds / 1000,
    (*pmilliseconds % 1000) * 1000000L
  };

最好像这样写

  struct timespec ts_sleep = 
  {
    .tv_sec = *pmilliseconds / 1000,
    .tv_nsec = (*pmilliseconds % 1000) * 1000000L
  };

不依赖struct timespec成员的顺序。

答案 1 :(得分:0)

我是这样做的,它起作用了......

#include <stdio.h>
#include <time.h>   /* Needed for struct timespec */


int nsleep(long miliseconds)
{
   struct timespec req, rem;

   if(miliseconds > 999)
   {   
        req.tv_sec = (int)(miliseconds / 1000);                            /* Must be Non-Negative */
        req.tv_nsec = (miliseconds - ((long)req.tv_sec * 1000)) * 1000000; /* Must be in range of 0 to 999999999 */
   }   
   else
   {   
        req.tv_sec = 0;                         /* Must be Non-Negative */
        req.tv_nsec = miliseconds * 1000000;    /* Must be in range of 0 to 999999999 */
   }   

   return nanosleep(&req , &rem);
}

int main()
{
   int ret = nsleep(2500);
   printf("sleep result %d\n",ret);
   return 0;
}

答案 2 :(得分:0)

这是方法

{
"rules": {
    "no-unused-vars": ["error", { "vars": "local", "args": "after-used", "ignoreRestSiblings": true }]
  }
}

下一页将更好地解释这个概念 Convert milliseconds to timespec - GNU Porting