X86 SMP多线程如何共享内存和中断?
我正在为我的内核做一些输入缓冲区的工作,我有一些问题。在双核机器上,我知道可以同时运行多个“进程”。我不知道的是操作系统和各个程序是如何保护数据冲突的 关于这个话题,我想知道两件事: (1) 中断发生在哪里?它们是否保证发生在一个核心上而不是另一个核心上?这是否可以用来确保一个核心上的实时操作不会被(比如)可以在另一个核心上处理的文件IO中断?(从逻辑上来说,我假设中断会发生在第一个内核上,但这总是真的吗?你怎么判断?或者每个内核都有自己的中断设置?这会不会导致一种情况,即每个内核可能以不同的方式同时对同一个中断做出反应?) (2) 双核处理器如何处理操作码内存冲突?如果一个内核正在读取内存中的地址,而另一个内核正在写入内存中的同一地址,会发生什么情况?是引发异常还是读取值?(我假设写操作会以任何一种方式工作。)如果读取一个值,是否保证在冲突发生时它是旧值还是新值X86 SMP多线程如何共享内存和中断?,x86,kernel,multicore,osdev,X86,Kernel,Multicore,Osdev,我正在为我的内核做一些输入缓冲区的工作,我有一些问题。在双核机器上,我知道可以同时运行多个“进程”。我不知道的是操作系统和各个程序是如何保护数据冲突的 关于这个话题,我想知道两件事: (1) 中断发生在哪里?它们是否保证发生在一个核心上而不是另一个核心上?这是否可以用来确保一个核心上的实时操作不会被(比如)可以在另一个核心上处理的文件IO中断?(从逻辑上来说,我假设中断会发生在第一个内核上,但这总是真的吗?你怎么判断?或者每个内核都有自己的中断设置?这会不会导致一种情况,即每个内核可能以不同的方
我理解,理想情况下,编写程序应该避免这些复杂情况,但操作系统肯定不能期望这样,并且需要能够处理此类事件而不受自身限制。IA-32参考手册将明确回答您的问题 我的直觉是,两个内核都会中断,操作系统会对它们进行排序。每个内核上可能都有一个设置寄存器,指定哪个内核获得哪个中断 碰撞。不保证。更准确地说,研究缓存机制以及它们如何排序一致性 对于与此相关的其他线程:
操作系统开始设置处理中断的位置。Linux对中断进行负载平衡,因此它们可以由两个CPU处理。每个中断处理程序都需要获取一个锁,以避免同一处理程序在不同的CPU上并发执行,同时还可以防止其他内核代码在非中断上下文中运行并访问相同的数据结构。然而,我认为可以在给定的CPU上绑定给定中断的执行 关于问题(2):保证与SMP机器给出的保证基本相同,即不会引发异常,结果取决于谁先执行/将值提交到内存/将值提交到共享缓存。无论如何,您都不能依赖于读取值——事实上,给出的保证比您预期的要弱得多 在互联网(谷歌或维基百科)上了解什么是数据竞赛,从研究如何用Java正确编写多线程代码开始。研究它使我更容易理解Linux内核的并发机制 或者只需查看Linux内核源代码树中的Documentation/memory-barriers.txt或。 无论如何,我忘了指出,您读取的值不一定是由某个处理器实际写入的。对于32位值,32位写入是原子的这一事实保证了这一点。对于64位值,这通常不是真的(我不确定64位平台,但由于可移植性的原因,我通常不依赖它) 在任何情况下,如果您发现自己在问这个问题,您可能应该改进代码使用的锁定。在内核中工作时,首先需要编写自己的自旋锁/信号量库来解决这个问题 当你说“你的内核”时,并不清楚你的意思,但我认为你不太可能真正指的是“我正在编写的内核”。无论如何,我不会让任何人问问题(2)在我的机器上运行多线程程序:-) 我知道节目应该 理想情况下,应避免这些问题 各种各样的并发症,但是操作系统 当然不能指望,而且会的 需要能够处理此类事件 没有窒息
要编写用户空间多线程程序,您需要知道这个问题的答案。好吧,您不需要知道“读取哪个值”的确切答案,但正因为您不能依赖于此,即使您为特定处理器编写汇编代码,它也是实现定义的。因为你不能依赖两个并行线程的相对速度。在x86处理器中,这是由APIC处理的。您可以在第9章和中看到详细信息 如果你不想谈所有的细节,我就简单地总结一下 中断可以来自三个不同的来源:
- 外部引脚(在Core i7之前的英特尔处理器中,您有LINT0、LINT1、SMI、INIT。我不知道它们在Core i7、AMD或Via处理器中被称为什么)
- 总线事务。这是现代系统中一个线程向另一个线程发送中断的主要方式。它们被称为IPIs-处理器间中断
- 内部事件,如热中断、事件监视器或内部错误
- LINT0、LINT1、热事件、事件监视器和错误在LVT(逻辑向量表)中都有一个条目,用于指定它是否被屏蔽,如果没有,它将是什么类型的中断
- IPI得到处理。IPI包括中断类型(即