加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

nanosleep不适用于不到一秒的值

发布时间:2020-12-16 09:54:26 所属栏目:百科 来源:网络整理
导读:我有一个程序(混合C和Fortran,虽然这似乎没有相关性)使用nanosleep.但是,如果我的timespec的tv_sec值为0,它就不会休眠. tv_nsec值可能是一整秒的微秒,但它不会睡眠. (如果tv_sec为1,它可以暂停一秒钟.)为什么会这样? 为了使事情变得更加混乱,使用适当的值(
我有一个程序(混合C和Fortran,虽然这似乎没有相关性)使用nanosleep.但是,如果我的timespec的tv_sec值为0,它就不会休眠. tv_nsec值可能是一整秒的微秒,但它不会睡眠. (如果tv_sec为1,它可以暂停一秒钟.)为什么会这样?

为了使事情变得更加混乱,使用适当的值(即995000 usec)睡眠时间仅为预期的一秒钟.

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

这是调用nanosleep的函数:

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(成功),因此从未设置rem输出参数(中断时的剩余时间).

解决方法

你缺少一个因子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成员的顺序.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读