这真是一个困惑我很久的问题。我尝试了很多谷歌搜索,但仍然不太明白。我的问题是这样的:
对于epoll()、mutex、semaphore等系统调用,它们有一个共同点:一旦有事情发生(以mutex为例,线程释放锁),就会有一个线程被唤醒(线程等待锁的人可以被唤醒)。
我想知道这种机制(一个线程中的事件发生,然后另一个线程被通知)是如何在幕后实现的?我只能想出两种方法:
- 硬件级别的中断:比如另一个线程一释放锁,就会发生边沿触发。
- Busy waiting:在很低的级别忙着等待。例如,一旦另一个线程释放锁,它就会从 0 变为 1,以便等待锁的线程可以检查该位。
我不确定我的猜测(如果有的话)中的哪一个是正确的。我想阅读 linux 源代码在这里会有帮助。但是对于我这种菜鸟来说有点难。在这里有一个大概的想法加上一些伪代码会很棒。
最佳答案
Linux 内核有一个名为“等待队列”的内置对象类(其他操作系统也有类似的机制)。等待队列是为所有类型的“可等待”资源创建的,因此内核中有相当多的等待队列。当线程检测到它必须等待一个资源时,它就加入相关的等待队列。大致过程如下:
- 线程将其控制结构添加到与所需等待队列关联的链表中。
- 线程调用调度程序,它将调用线程标记为休眠,将其从“准备运行”列表中删除并将其上下文隐藏在 CPU 之外。然后,调度程序可以自由选择任何其他线程上下文来加载到 CPU 上。
当资源可用时,另一个线程(无论是用户/内核线程还是由中断处理程序调度的任务——那些通常搭载在特殊的“工作队列”线程上)调用相关的“唤醒”调用等待队列。 “唤醒”是指调度器应从等待队列链表中删除一个或多个线程控制结构,并将所有这些线程添加到“准备运行”列表中,这将使它们能够在适当的时候被调度。
这里有更多的技术概述: http://www.makelinux.net/ldd3/chp-6-sect-2
关于linux - epoll()、互斥量和信号量之类的系统调用是如何在后台实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41155494/