我目前正在使用select()
充当计时器。我有一个循环内发生的网络接收操作,每隔几秒钟就需要进行一次处理操作。
结果,select()语句的超时不断变化-随时间减少到零,然后从3重新开始。rv = select(selectmonitor+1, &readnet, NULL, NULL, &helper.timeout());
当事物进入网络时,该语句将重复执行,并且helper.timeout()传递给它的值将减小。最终,该值将等于零,否则系统将超时,这将导致执行处理功能。但是,我注意到这非常耗费资源-必须不断计算helper.timeout()的值。当我尝试每秒接收数千个数据包时,执行此操作所花费的时间会导致数据包丢失。
我的新想法是使用SIGALRM
解决此问题。这将允许我设置一次计时器,然后在关闭计时器时做出反应。但是,我对它如何影响我的程序感到困惑。当SIGALRM“关闭”时,它将运行我指定的功能。但是,它将如何中断我现有的代码?函数完成后,如何恢复现有代码(在while
语句内)?
另外,似乎无法设置SIGALRM信号来调用类中的函数吗?它是否正确?我想我可以调用一个函数,而该函数又可以在一个类中调用一个函数。
感谢您的协助。
最佳答案
使用您的SIGALRM处理程序来设置标志变量。
使用sigaction
而不是signal
来设置信号处理程序。不要设置SA_RESTART标志。如果未设置SA_RESTART,则选择语句将被信号中断。您的选择将返回-1,而errno将为EINTR。
由于信号可能会在您执行其他代码时发生,因此您可能还要在进入选择之前检查标志变量。
我刚被提醒,如果在检查标志之后和进入选择之前刚好发生这种模式,可能会导致信号丢失。
为避免这种情况,需要在进入while循环之前使用sigprocmask
阻止SIGALRM信号。然后,您使用pselect
而不是select
。通过给pselect
提供一个未屏蔽SIGALRM的信号屏蔽,该信号将最终在选择期间始终中断,而不是在其他时间发生。