SMP多线程如何共享内存和中断?

时间:2009-01-07 07:36:30

标签: x86 kernel multicore osdev

我正在为我的内核做输入缓冲区的工作,我有一些问题。在双核机器上,我知道可以同时运行多个“进程”。我不知道的是操作系统和各个程序如何保护数据中的冲突。

我想就此主题了解两件事:

(1)中断发生在哪里?它们是否保证在一个核心而不是另一个核心上发生,并且可以用来确保一个核心上的实时操作不会被文件IO中断,这可以在另一个核心上处理吗? (我逻辑上假设中断会发生在第一个核心上,但总是如此,你会怎么说?或者每个核心都有自己的中断设置?这不会导致核心可能会以不同的方式同时对同一个中断作出反应吗?)

(2)双核处理器如何处理操作码内存冲突?如果一个内核正在读取内存中的地址,而另一个内核正在写入内存中同一个地址的同一时间,会发生什么?抛出异常,还是读取值? (我假设写入会以任何一种方式工作。)如果读取一个值,它是否保证在碰撞时是旧值还是新值?

我知道理想情况下应该编写程序以避免这些并发症,但操作系统当然不能指望这样,并且需要能够处理此类事件而不会窒息。

3 个答案:

答案 0 :(得分:6)

在x86处理器中,这由APIC处理。您可以在Intel® 64 and IA-32 Architectures Software Developer's Manual,特别是volume 3,第9章和x2APIC specification中查看详情。

如果您不想了解所有细节,我会给出快速摘要。

中断可以来自三个不同的来源:

  • 外部引脚(在Intel处理器中,直到Core i7,你有LINT0,LINT1,SMI,INIT。我不知道它们在Core i7或AMD或Via处理器中被称为什么。)
  • 巴士交易。这是一个线程向现代系统中的另一个线程发送中断的主要方式。它们被称为IPI - I nter- P rocessor I nterrupts。
  • 内部事件,例如热中断,事件监视器或内部错误。

每个逻辑处理器(SMT系统中的线程,非SMT多核系统中的核心,非SMT非多核系统中的处理器)都具有APIC。 APIC控制逻辑处理器如何响应任何此类中断。

简而言之:

SMI和INIT引脚总是分别路由到SMI或INIT。

如果APIC被禁用,LINT0被路由到INTR,LINT1被路由到NMI,并且IPI被忽略。

如果已启用:

  • LINT0,LINT1,热事件,事件监视器和错误每个都在LVT中有一个条目( L 逻辑 V ector T 能够)指定它是否被屏蔽,如果没有,它将是什么类型的中断。
  • 处理IPI。 IPI包括中断类型(即INTR,SMI,NMI,INIT,SIPI)和目的地。每个逻辑处理器都有一个APIC-ID,即。如果IPI的目的地与其ID匹配,则它处理中断。否则就会忽略它。

如果您需要有关启用APIC,编程LVT,设置APIC-ID和发送IPI的详细信息,您必须查看我链接到的手册。

答案 1 :(得分:1)

IA-32参考手册将最终回答您的问题。

我的直觉是两个内核rx都会中断,操作系统会将它们排除在外。每个内核上可能都有一个设置寄存器,用于指定哪个内核获得哪个中断。

碰撞。不保证。更准确地说,查看缓存机制以及它们如何理清一致性。

对于与此相关的其他线程:

How do interrupts in multicore/multicpu machines work?

答案 2 :(得分:1)

操作系统可以设置处理中断的位置。 Linux确实对中断进行负载均衡,以便它们可以由两个CPU处理。每个中断处理程序都需要获取一个锁,以避免在不同的CPU上同时执行相同的处理程序,还要保护在非中断上下文中运行的其他内核代码并访问相同的数据结构。但是,我认为可以在给定的CPU上绑定给定中断的执行。

关于问题(2):保证与SMP机器给出的保证基本相同,即没有抛出异常,结果取决于谁将值执行/提交给内存/将值提交给共享先缓存。你无论如何都不能依赖于阅读价值 - 事实上,给出的保证远不如你预期的那么强。

在互联网上(在谷歌或维基百科上)了解数据竞争是什么,首先研究如何在Java中正确编写多线程代码。研究使我更容易理解Linux内核的并发机制。

或者只是从Linux内核源代码树或C/C++ almost "official" memory model FAQ获取文档/ memory-barriers.txt中的Jeremy Manson's post on the issue。 无论如何,我忘了指出你读的价值并不一定是由某个处理器实际写的。对于32位值,32位写入是原子的这一事实保证了这一点。对于64位值,这通常不正确(我不确定64位平台,但由于可移植性原因,我通常不依赖它)。

在任何情况下,如果您发现自己提出了这个问题,那么您可能应该改进代码使用的锁定。在内核中工作,首先需要编写自己的自旋锁/信号量库来解决这个问题。

当你说“你的内核”时,你不清楚你的意思,但我认为你实际上不太可能意味着“我正在写的内核”。无论如何,我不会让任何人问问题(2)在我的机器上运行多线程程序: - )。

  

我理解程序应该   理想情况下,写作是为了避免这些   各种并发症,但操作系统   当然不能指望,并且会   需要能够处理此类事件   没有窒息。

这个问题的答案是你需要知道写的用户空间多线程程序。好吧,你不需要知道“你读哪个值”的确切答案,但仅仅因为你不能依赖它,即使你为特定的处理器编写汇编代码,它也是实现定义的。仅仅因为你不能依赖两个平行线程的相对速度。如初。

相关问题