如何在C程序中长时间运行while循环时防止软锁定/无响应的正确方法是什么?
(dmesg报告软锁定)
伪代码是这样的:
while( worktodo ) {
worktodo = doWork();
}
我的代码当然更复杂,并且还包含一个printf语句,该语句每秒执行一次以报告进度,但问题是,此时程序停止响应ctrl + c。
我尝试过哪些功能(但我想要一个替代方案):
我正在考虑的是某种process_waiting_events()函数等,正常信号似乎工作正常,因为我可以在不同的shell上使用kill来停止程序。
其他背景信息:我正在使用GWAN,我的代码在main.c“维护脚本”中运行,据我所知,它似乎在主线程中运行。
非常感谢。
PS:是的,我确实检查了我发现的关于软锁定的所有其他线程,但他们似乎都在询问为什么软锁定发生,而我知道为什么和想要有办法阻止他们。 PPS:优化程序(让它运行得更短)并不是真正的解决方案,因为我正在处理一个29GB的bz2文件,它提取到大约400GB xml,在单个线程上以每秒10-40MB的速度提取,所以即使在最大速度下,我也会受到I / O的约束,并且仍然会运行几个小时。答案 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访问控制台,这是一个昂贵且耗时的过程,在您的情况下为工作人员提供足够的时间来完成其工作。