SIGALRM 超时——它如何影响现有操作?
我目前正在使用 select()
充当计时器。我有在循环内发生的网络接收操作,并且每隔几秒需要发生一次处理操作。
因此,select() 语句的超时不断变化 - 随着时间的推移减少到零,然后在 3 处重新启动。
rv = select(selectmonitor+1, &readnet, NULL, NULL, &helper.timeout( ));
当事物进入网络时,该语句将被重复,并且 helper.timeout() 传递给它的值会减少。最终,该值将等于零或系统超时,这将导致处理函数执行。但是,我注意到这是相当资源密集型的——必须不断计算 helper.timeout() 的值。当我尝试每秒接收几千个数据包时,完成此操作所需的时间会导致数据包丢失。
我的新想法是使用 SIGALRM
来解决这个问题。这将允许我设置一个计时器,然后在它启动时做出反应。但是,我很困惑它将如何影响我的程序。当 SIGALRM“关闭”时,它将运行我指定的函数。但是,它将如何中断我现有的代码?一旦函数完成,我现有的代码(在 while
语句内)将如何恢复?
另外,似乎不可能设置 SIGALRM 信号来调用类中的函数?这是正确的吗?我想我可以调用一个函数,该函数又可以调用类中的函数。
感谢您提前提供的任何帮助。
I am currently using select()
to act as a timer. I have network receive operations which occur within a loop, and every few seconds a processing operation needs to occur.
As a result, the select() statement's timeout constantly changes -- decreasing to zero over time and then restarting at 3.
rv = select(selectmonitor+1, &readnet, NULL, NULL, &helper.timeout());
As things come in on the network, the statement is repeated and the value passed to it by helper.timeout() decreases. Eventually, the value will either be equal to zero or the system will timeout, which will result in the processing function executing. However, I've noticed that this is quite resource intensive -- the value for helper.timeout() must be constantly calculated. When I am trying to receive a few thousand packets a second, the time it takes for this operation to be done results in packet loss.
My new idea is using SIGALRM
to resolve this. This would allow me to set a timer once and then react when it is set off. However, I'm confused as to how it will affect my program. When SIGALRM 'goes off', it will run a function which I specify. However, how will it interrupt my existing code? And once the function is done, how will my existing code (within the while
statement) resume?
Also, it would appear its impossible to set the SIGALRM signal to call a function within a class? Is this correct? I imagine I can call a function, which can in turn call a function within a class..
Thanks for any assistance ahead of time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用 SIGALRM 处理程序设置标志变量。
使用
sigaction
而不是signal
来设置信号处理程序。不要设置 SA_RESTART 标志。如果 SA_RESTART 不设置,您的 select 语句将被信号中断。您的 select 将返回 -1 并且 errno 将是 EINTR。由于信号可能在其他代码执行时发生,因此您也需要检查标志变量,可能就在进入选择之前。
我只是被提醒,如果这种模式发生在检查标志之后和进入选择之前,则可能会导致丢失信号。
为了避免这种情况,您需要在进入 while 循环之前使用 sigprocmask 来阻止 SIGALRM 信号。然后使用
pselect
而不是select
。通过给pselect
一个信号掩码并取消掩码 SIGALRM,该信号最终将始终在选择期间中断,而不是在任何其他时间发生。Use your SIGALRM handler to set a flag variable.
Use
sigaction
instead ofsignal
to set your signal handler. Do not set the SA_RESTART flag. With SA_RESTART not set your select statement will be interrupted by the signal. Your select will return -1 and errno will be EINTR.Since the signal might happen while your other code is executing you will want to check the flag variable too, probably right before going into the select.
I was just reminded that this pattern can result in missing the signal, if it happens just after checking the flag and just before entering the select.
To avoid that, you need to use
sigprocmask
to block the SIGALRM signal before entering the while loop. Then you usepselect
instead ofselect
. By givingpselect
a signal mask with SIGALRM unmasked, the signal will end up always interrupting during the select instead of happening at any other time.