1

在C程序中长时间运行的while循环中防止软锁定/无响应的正确方法是什么?

(dmesg 报告软锁定)

伪代码是这样的:

while( worktodo ) {
  worktodo = doWork();
}

我的代码当然要复杂得多,并且还包括一个 printf 语句,该语句每秒执行一次以报告进度,但问题是,此时程序停止响应 ctrl+c。

我尝试过的有效方法(但我想要一个替代方案):

  • 每次循环迭代都执行 printf(不知道为什么,但是程序会再次以这种方式响应(???)) - 由于不需要 printf 调用而浪费了大量性能(每个 doWork() 调用不会花费很长时间)
  • 使用 sleep/usleep/... - 对我来说似乎也是浪费(处理)时间,因为整个程序已经全速运行了几个小时

我正在考虑的是某种 process_waiting_events() 函数等,正常信号似乎工作正常,因为我可以在不同的 shell 上使用 kill 来停止程序。

附加背景信息:我正在使用GWAN,我的代码在 main.c“维护脚本”中运行,据我所知,它似乎在主线程中运行。

非常感谢。

PS:是的,我确实检查了我发现的有关软锁定的所有其他线程,但它们似乎都在询问为什么会发生软锁定,而我知道原因并希望有一种方法来防止它们。

PPS:优化程序(使其运行时间更短)并不是真正的解决方案,因为我正在处理一个 29GB bz2 文件,该文件提取到大约 400GB xml,在单个线程上的速度约为每秒 10-40MB,所以即使在最大速度下,我会受到 I/O 的约束,并且仍然可以运行几个小时。

4

3 回答 3

1

虽然使用线程提出的答案可能是一种选择,但实际上它只会将问题转移到不同的线程。毕竟我的解决方案是使用

sleep(0)

还测试了 sched_yield / pthread_yield,这两者都没有真正的帮助。不幸的是,我一直无法找到在 linux 中记录 sleep(0) 的好资源,但对于 Windows,文档指出使用 0 值可以让线程产生它是当前 cpu 片的剩余部分。

事实证明,sleep(0) 很可能依赖于 linux 中所谓的计时器松弛- 可以在此处找到有关此的文章:http: //lwn.net/Articles/463357/

另一种可能性是使用nanosleep(&(struct timespec){0}, NULL)它似乎不一定依赖于计时器松弛- linux man pages for nanosleep state 如果请求的间隔低于时钟粒度,它将被四舍五入到时钟粒度,根据手册页,这在 linux 上取决于 CLOCK_MONOTONIC . 因此,0 纳秒的值是完全有效的,并且应该始终有效,因为时钟粒度永远不能为 0。

希望这对其他人也有帮助;)

于 2013-09-11T11:00:45.103 回答
0

您的场景并不是真正的软锁定,而是一个进程正忙于做某事。

这个伪代码怎么样:

void workerThread()
{
    while(workToDo)
    {
       if(threadSignalled)
          break;

      workToDo = DoWork()
    }
}

void sighandler()
{
   signal worker thread to finish
   waitForWorkerThreadFinished;
 }

void main()
{
    InstallSignalHandler;
    CreateSemaphore
    StartThread;
    waitForWorkerThreadFinished;
}
于 2013-09-11T09:12:39.690 回答
-1

显然是时间问题。使用信号机制应该可以解决这个问题。

使用 printf 解决了这个问题,因为 printf 访问控制台是一个昂贵且耗时的过程,在您的情况下,它为工作人员提供了足够的时间来完成其工作。

于 2013-09-11T14:51:52.180 回答