[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$flTbl6Z_daqWI90TgSmRbwu-VUXiMJUKuxKqP9Aguv04":3},{"item":4,"related":44},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":36,"sourceUrl":37,"status":38,"seoTitle":7,"seoDescription":9,"canonicalUrl":35,"isFeatured":39,"sno":40,"sortOrder":41,"publishedAt":42,"updatedAt":43,"createdAt":43},"437da461-85dd-41b2-a1b6-ab3477530402","article","TLB Shootdown：页表改了，为什么还要通知其他 CPU？","tlb-shootdown-multicore-address-translation","CPU 会缓存虚拟地址到物理地址的转换，页表更新后旧缓存可能仍需失效。本文解释多核同步的原因、成本和现代内核如何减少不必要的刷新。","程序访问一个虚拟地址时，处理器需要通过页表找到它对应的物理内存。若每次都层层查页表，开销会很大，于是 CPU 把近期转换结果放进 TLB（地址转换后备缓冲器）。问题在于：操作系统改了页表，TLB 里可能还留着旧映射。所谓 TLB Shootdown，就是在多核系统中协调处理器，让仍可能缓存旧转换的核心及时失效这些条目。\n\n用办公室地图打比方：墙上的总地图刚改了房间编号，但几个同事手里还有旧复印件。只更新总地图并不足够；若同事继续照着旧地图走，就可能读到不该读的数据，或者把写入送到错误位置。TLB 中的旧条目同样可能使进程继续使用过期映射。操作系统因此必须在页表变化和后续访问之间建立正确的同步关系。\n\n为什么叫“shootdown”？历史上常用的做法，是一个 CPU 发起请求，通知其他可能使用该地址空间的 CPU 刷新相应 TLB 项；收到通知的核心执行失效操作并确认完成。全量刷新当然简单，但会清掉许多仍有效的转换，增加之后重新遍历页表的成本。现代内核会尽量精确地判断受影响的地址空间、范围和处理器，减少不必要的广播；不同体系结构提供的失效机制也不完全相同。\n\n这类协调不是抽象的性能小事。频繁创建和销毁映射、进程共享地址空间、内存回收或虚拟机相关操作，都可能引发地址转换同步。核心数量越多，一次失效可能涉及的协作越复杂；跨插槽通信、处理器中断和等待确认都可能增加延迟。不过不能简单说“每次改页表都要暂停所有 CPU”：内核会根据地址空间使用情况和平台能力采取更精细的策略。\n\n调优时要同时看正确性和成本。减少不必要的映射变更、批量处理地址区间，可能降低失效频率；但过度缓存或延迟更新又会影响内存占用和资源回收。只有在性能剖析显示地址转换同步确实是热点时，优化才有依据。普通应用开发者通常不会直接发 shootdown 指令，却会在容器、虚拟机、数据库和高并发运行时的性能问题中间接遇到它。\n\nTLB Shootdown 揭示了多核系统的一条重要规律：内存映射虽然由操作系统维护，却可能同时被多个处理器缓存，所以“改一张页表”有时需要一场小型的跨核协作。\n\n来源：[Linux 内核文档：Cache and TLB Flushing](https:\u002F\u002Fdocs.kernel.org\u002Fcore-api\u002Fcachetlb.html)","\u002Fuploads\u002F2026-10-06\u002Fe3966f46-6a10-46bc-8802-768f58ad7e37.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"Linux Kernel Documentation：Cache and TLB Flushing","https:\u002F\u002Fdocs.kernel.org\u002Fcore-api\u002Fcachetlb.html","published",false,60,0,"2026-10-06T00:00:00.000Z","2026-10-06T07:51:17.096Z",[45,54,63],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":52,"createdAt":53},"5e0c84da-6011-41e8-b1f7-726c8bf0b30a","RCU：读多写少的系统，为什么敢让读者几乎不加锁？","rcu-read-copy-update-explained","RCU 把共享数据的更新与旧版本回收拆开，让读者以极低成本读取，同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。","\u002Fuploads\u002F2026-09-26\u002F3398ce37-ca4f-4cc3-84b3-fe931d2f055d.jpg",41,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:40.784Z",{"id":55,"type":6,"title":56,"slug":57,"summary":58,"coverUrl":59,"authorName":14,"sno":60,"publishedAt":61,"createdAt":62},"0bc79f1c-f305-4d64-a9f8-589d1d6da0b3","EEVDF：Linux 如何判断哪个任务“最该先用 CPU”？","eevdf-linux-fair-cpu-scheduling","EEVDF 是 Linux 调度器的一种公平调度思路：先判断任务是否获得了应有份额，再按虚拟截止时间安排运行机会。本文用共享厨房的比喻，解释它如何兼顾长期公平与短期响应，并澄清它并非硬实时保证。","\u002Fuploads\u002F2026-10-13\u002Fdc59d374-8c78-41ba-bdfe-a6f0e62ab246.jpg",43,"2026-10-13T00:00:00.000Z","2026-10-13T02:13:28.103Z",{"id":64,"type":6,"title":65,"slug":66,"summary":67,"coverUrl":68,"authorName":14,"sno":69,"publishedAt":52,"createdAt":70},"23b5596a-29ab-4ff8-8237-1fd34d8e0bd1","Seqlock：读者不加锁，为什么还能读到一份一致的数据？","seqlock-sequence-counter-explained","Seqlock 让读者先后读取序列号并在变化时重试，以校验快照是否被写者打断，适合读多写少且字段可安全复制的数据。","\u002Fuploads\u002F2026-09-26\u002Fe6a9caee-7551-469f-9b16-d27fcc97f034.jpg",44,"2026-09-26T16:25:51.305Z"]