ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Tlb/Thread IPI(Inter-Processor Interrupt)

Tlb/Thread IPI(Inter-Processor Interrupt) IPIInter-Processor Interrupt处理器间中断是 Linux 多核系统中一个非常关键的机制。它允许一个 CPU 核向其他 CPU 核发送中断从而实现核间通信和协调。你前面问的“多线程如何跑在多个 CPU 上”其背后很多协调工作正是靠 IPI 完成的。1. 什么是 IPI在单核时代CPU 只需要处理外部设备中断如网卡、磁盘和软件中断。到了多核时代CPU 之间也需要互相“打招呼”比如“我改了页表你赶紧刷新 TLB。”“重新调度一下别闲着了。”“停下来我要做全局操作。”这种由一个 CPU 发给另一个 CPU 的中断就是 IPI。IPI 本质上是一种核间中断通过中断控制器如 x86 的 APIC、ARM 的 GIC投递到目标 CPU目标 CPU 收到后执行对应的中断处理程序。2. IPI 的典型用途2.1 TLB 刷新TLB Shootdown每个 CPU 有自己的 TLB页表缓存。当某个 CPU 修改了页表比如munmap、mprotect、进程地址空间切换其他 CPU 上缓存的旧 TLB 条目就失效了必须通知它们刷新。流程CPU A 修改页表。CPU A 向所有可能使用该地址空间的 CPU 发送 IPI。目标 CPU 收到 IPI 后执行flush_tlb_*清除相关 TLB 条目。CPU A 等待所有目标 CPU 确认完成才继续。这就是所谓的TLB shootdown是多线程/多进程程序中常见的一种 IPI 开销。2.2 调度唤醒Reschedule IPI当一个线程被唤醒而它更适合在某个正在运行其他任务的 CPU 上执行时调度器会向那个 CPU 发送 IPI让它重新调度。例如CPU A 上有个高优先级线程被唤醒。但 CPU A 正在跑另一个线程。调度器发现 CPU B 上的任务优先级更低。于是向 CPU B 发 IPI让 CPU B 重新调度可能把低优先级任务换出跑高优先级任务。这保证了多核调度的公平性和实时性。2.3 函数调用Call Function IPI内核需要在所有 CPU 上执行某个函数时会通过 IPI 广播smp_call_function()在所有其他 CPU 上执行一个函数。on_each_cpu()在每个 CPU包括自己上执行。典型场景刷新缓存。更新全局状态。CPU 热插拔时的同步。2.4 停止 CPUStop IPI在某些全局操作中需要让其他 CPU 暂停内核崩溃crash dump。挂起/恢复。CPU 热插拔。RCU 的宽限期处理。这时会发送 stop IPI让目标 CPU 进入停止状态等待进一步指令。2.5 定时器与时钟同步在早期多核系统中每个 CPU 有自己的定时器中断。某些情况下需要用 IPI 来同步时钟或触发其他 CPU 的定时器处理。3. IPI 的硬件基础不同架构的中断控制器不同x86使用APICAdvanced Programmable Interrupt Controller。每个 CPU 有 Local APIC。通过写 Local APIC 的 ICRInterrupt Command Register发送 IPI。可以指定目标 CPU、中断向量、投递模式。ARM使用GICGeneric Interrupt Controller。通过 GIC 的 SGISoftware Generated Interrupt机制发送 IPI。最多支持 16 个 SGI 中断号。RISC-V使用PLIC或CLINT相关机制。硬件负责把 IPI 投递到目标 CPU目标 CPU 的中断入口会跳转到对应的处理函数。4. Linux 中的 IPI 实现4.1 中断向量Linux 为 IPI 分配了专门的中断向量例如 x86 上RESCHEDULE_VECTOR调度重发。CALL_FUNCTION_VECTOR函数调用。CALL_FUNCTION_SINGLE_VECTOR单目标函数调用。TLB_FLUSH_VECTORTLB 刷新。IRQ_WORK_VECTORIRQ work。REBOOT_VECTOR重启/停止。每个向量对应一个中断处理函数。4.2 发送 IPI以 x86 为例发送 IPI 的核心函数是apic-send_IPI_mask(mask, vector);或apic-send_IPI(cpu, vector);底层就是写 Local APIC 的 ICR 寄存器。4.3 接收 IPI目标 CPU 收到 IPI 后保存当前上下文。根据中断向量跳转到对应处理函数。执行具体操作如刷新 TLB、重新调度。返回中断前上下文。4.4 同步与等待很多 IPI 操作需要等待目标 CPU 完成比如 TLB shootdown发送方设置一个完成标志。目标 CPU 完成后清除标志。发送方自旋等待所有目标 CPU 完成。这会导致发送方 CPU 短暂停顿称为IPI 风暴或TLB shootdown 开销。5. IPI 对多线程程序的影响虽然 IPI 是内核机制但它会直接影响多线程程序的性能5.1 TLB shootdown 开销多线程程序如果频繁修改地址空间如mmap/munmap、线程创建销毁会触发 TLB shootdown IPI导致其他 CPU 停顿。5.2 调度 IPI线程频繁唤醒、迁移会导致 reschedule IPI增加开销。5.3 缓存一致性IPI 本身不直接维护缓存一致性但缓存一致性协议如 MESI和 IPI 配合保证多核看到一致的内存视图。5.4 减少 IPI 的方法减少不必要的地址空间修改。使用大页减少 TLB 条目。避免线程频繁迁移设置 CPU 亲和性。使用madvise(MADV_DONTNEED)等更精细的接口减少全局 TLB 刷新。6. IPI 与多线程问题的联系问题“Linux 多线程如何运行在多个 CPU 上”调度器把线程分配到不同 CPU。当线程状态变化、负载不均时reschedule IPI让其他 CPU 重新调度。当线程修改页表时TLB shootdown IPI保证其他 CPU 看到正确的地址映射。当内核需要全局同步时call function IPI在所有 CPU 上执行操作。所以IPI 是多核 Linux 能正确、高效运行多线程的底层协调机制之一。7. 总结方面说明定义一个 CPU 向其他 CPU 发送的中断硬件x86 APIC、ARM GIC、RISC-V PLIC/CLINT主要用途TLB 刷新、调度唤醒、函数调用、停止 CPU实现中断向量 发送/接收处理函数影响可能造成 CPU 停顿、性能开销优化减少地址空间修改、设置亲和性、使用大页一句话IPI 是多核 Linux 的“核间电话”让各个 CPU 能协调一致地运行多线程任务。
返回列表