【问题标题】:sleep() function does not work and print is executed instantaneouslysleep() 函数不起作用,打印会立即执行
【发布时间】:2020-10-18 18:14:35
【问题描述】:
static void timeDelay(int no_of_seconds)
{
#ifdef _WIN32
    Sleep(1000 * no_of_seconds);
#else
    sleep(no_of_seconds);
#endif
}

void somefunction(){
printf("\t\t Load ... \n\t\t"); 
fflush(stdout); 
for (int i = 1; i <= 60; i++)
        {
            fflush(stdout);
            timeDelay(1);
            if (i == 31)
                printf("\n\t\t");
            printf("*****");
        }
        
  }

我也包含了头文件:

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>

星星瞬间打印出来。 在看到答案here 后,我添加了fflush(stdout)。我还注释掉了if (i==31) {} 部分,以检查这是否导致了问题,但事实并非如此。那么我的代码有什么问题呢?

【问题讨论】:

  • 无法重现。
  • @n.'pronouns'm。什么意思?
  • 哪个版本不能按预期工作?
  • @WeatherVane 它一次打印所有的星星。
  • @Archer 好的!这是真的!我也一样!

标签: c sleep windows-subsystem-for-linux


【解决方案1】:

根据sleep() 联机帮助页...

注意事项 在 Linux 上,sleep() 是通过 nanosleep(2) 实现的。请参阅 nanosleep(2) 手册页以了解 使用的时钟。

所以我重写了你的程序以使用 nanosleep。当您使用 WSL 时,我已经放弃了对 Win32 的任何引用,只有 Linux。好吧,问题是这个程序过早地退出了 nanosleep(),并出现“无效参数”错误。我不明白为什么会这样。

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

void timeDelay (time_t no_of_seconds)
{
  struct timespec req, rem;
  int res;

  req.tv_sec = no_of_seconds;
  req.tv_nsec = 0;

  do
  {
    rem.tv_sec = 0;
    rem.tv_nsec = 0;
    res = nanosleep (&req, &rem);
    req = rem;
  }
  while (res == EINTR);
  if (res)
    perror("nanosleep");
}

void somefunction()
{
  printf("\t\t Load ... \n\t\t");
  fflush(stdout);
  for (int i = 1; i <= 60; i++)
  {
    fflush(stdout);
    timeDelay(1);
    putchar('*');
  }
}

int main()
{
  somefunction();
  return 0;
}

我也尝试使用NULL 而不是rem,并使用原始时间而不是剩余时间重新发布nanosleep(),并将测试和 perror() 放在循环中以打印所有可能的错误从纳米睡眠。无论我做什么,从第一次致电nanosleep() 开始,我总会收到EINVAL

因此,WSL 上的nanosleep() 似乎存在真正的问题。见https://github.com/microsoft/WSL/issues/4898。它提到了 WSL 无法从特定版本的 glibc 读取实时时钟的问题。我在我的 WSL 终端中试过这个:

$ sleep 1
sleep: cannot read realtime clock: Invalid argument

这里提到了一种解决方法: https://github.com/microsoft/WSL/issues/4898#issuecomment-612622828

我尝试了另一种方法:使用clock_nanosleep(),这样我就可以为时钟选择另一个来源:在上面的程序中,只需将调用更改为nanosleep(),将其他调用更改为clock_nanosleep()

clock_nanosleep (CLOCK_MONOTONIC, 0, &req, &rem);

CLOCK_MONOTONIC 没有问题,现在程序可以运行了!

【讨论】:

  • 我同意,这并不能解决问题。它甚至也没有真正解决这个问题。如何实现sleep() 无关紧要。它的行为与记录的那样(或者它没有,如果是这样的话)是重点。它确实表现得像我在 WSL 上记录的那样。
  • 它是相关的,因为根本问题是 sleep() 使用 nanosleep(),而 nanosleep() 使用 CLOCK_REALTIME,在 WSL 中无法读取。无论如何,我已经更新了我的答案。
  • sleep() 按照 WSL 上的文档(对我来说)工作。也许它对某些 WSL 提供商来说是错误的,但这是一个相当不同寻常的主张。 WSL 的关键点之一是它提供了一个功能齐全的 Linux 环境。此外,如果它在某些 WSL 提供商上确实存在问题,这并不一定意味着问题出在 nanosleep() 上,尽管这是合理的。
  • 对于某些用户来说它工作正常。该问题也记录在此处:discourse.ubuntu.com/t/ubuntu-20-04-and-wsl-1/15291
  • 太棒了。 将是实际答案的基础。 “sleep() 在某些 WSL 提供程序上无法正常工作,例如 [...]”。 为什么它不起作用是对OP的问题意义不大的细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 2020-12-08
  • 1970-01-01
相关资源
最近更新 更多