C 信号处理程序难题中的竞争条件
我需要知道在 C 中处理信号时如何避免竞争条件。每次我的程序收到信号时,我希望它更改(全局)链表。重要的是我不要错过任何信号,同样重要的是我正在修改的全局链表在处理程序执行时不会被更改。
问题是,如果我收到一个信号并启动处理程序,但随后被另一个信号中断。这(据我理解)会触发信号处理程序的新执行,该信号处理程序将在同一全局数据集上运行 - 不允许!
我不能使用锁,因为如果第一个处理程序调用被中断,它自然不会释放锁以供中断处理程序拾取。那么,我该怎么做呢?有什么想法吗?
I need to know how to avoid a race condition when handling signals in C. Each time my program receives a signal, I want it to alter a (global) linked list. It is vitally important that I not miss a signal, and equally important that the global linked list I'm modifying not be changed while the handler is executing.
The problem is, if I receive a signal, and start the handler, but am then interrupted by another signal. This (as I understand it) triggers a new execution of the signal handler, which will operate on the same global dataset - not permissible!
I can't use a lock, because if the first handler call is interrupted, it will naturally never free the lock for the interrupting handler to pick up. So, how do I do it? Any idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您有幸在多线程环境中工作,最好的方法之一是让全局链表由单独的线程专门控制。中断会将请求排队到该线程(例如,只需传递指针即可非常快速地执行的操作),然后线程将按程序遍历每个请求并修改链接列表。这允许无锁执行。
当然,您必须依赖操作系统的消息传递垃圾,因此这可能不是一个选择。
If you have the luck to be working in a multi-threaded environment, one of the best ways is to have the global linked list controlled exclusively by a separate thread. Interrupts would enqueue requests to this thread (something that would be executed very quickly, say, by simply passing a pointer), and then the thread would procedurally go through each request and modify the linked list. This allows lockless execution.
Of course, you have to rely on your OS's message passing junk, so that may not be an option.
您可以在执行信号处理程序时屏蔽信号 - 检查传递给
sigaction()
系统调用的struct sigaction
的sa_mask
字段。You can mask signals while executing signal handler - check
sa_mask
field ofstruct sigaction
you pass tosigaction()
syscall.来自 http://users.evtek.fi/~tk/rtp/signals- programming.html:
保证完全没有竞争的方法是让系统在调用信号处理程序之前为我们设置信号屏蔽。如果我们使用 sigaction() 系统调用来定义信号处理函数和执行处理程序时使用的信号掩码,则可以完成此操作。既然您已经熟悉了信号处理的各种概念,您可能就可以自己阅读 sigaction() 的手册页了。然而,在旧系统上,您不会找到此系统调用,但您仍然可能会找到启用类似功能的 sigvec() 调用。
From http://users.evtek.fi/~tk/rtp/signals-programming.html:
The way to guarantee no races at all, is to let the system set the signal masking for us before it calls the signal handler. This can be done if we use the sigaction() system call to define both the signal handler function AND the signal mask to be used when the handler is executed. You would probably be able to read the manual page for sigaction() on your own, now that you're familiar with the various concepts of signal handling. On old systems, however, you won't find this system call, but you still might find the sigvec() call, that enables a similar functionality.
我认为你应该序列化信号。就像工作队列一样
例如,所有信号应放入工作队列(FIFO)中,然后执行线程始终轮询队列。如果队列不为空,该线程将选择顶部信号并启动它的处理程序。继续这样做,直到队列为空。
I think you should seriate the signal.just like the work queue
E.g. all the signal should put into a work queue(FIFO), and then the executing thread poll the queue all the time. if the queue is not empty,this thread will pick the top signal and start it`s handler. keep doing like that, until the queue is empty.