如何在没有睡眠的情况下防止C语言中的Linux软锁定/无响应

时间:2013-09-11 08:45:56

标签: c loops hang

如何在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的约束,并且仍然会运行几个小时。

3 个答案:

答案 0 :(得分:1)

虽然使用线程提出的答案可能是一个选项,但实际上只是将问题转移到另一个线程。毕竟我的解决方案是使用

sleep(0)

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

事实证明,sleep(0)很可能依赖于linux中所谓的 timer slack - 有关此内容的文章可以在这里找到:http://lwn.net/Articles/463357/

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

希望这也有助于其他人;)

答案 1 :(得分:0)

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

这个伪代码怎么样:

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

      workToDo = DoWork()
    }
}

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

void main()
{
    InstallSignalHandler;
    CreateSemaphore
    StartThread;
    waitForWorkerThreadFinished;
}

答案 2 :(得分:-1)

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

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