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