平坦内存与分段内存:递归本质

Hacker News Top 新闻

摘要

本文讨论了x86内存分段的演变,受Unix平坦内存模型影响,并解释CHERI和WebAssembly如何为安全和安保重新引入分段方法,强调了内存细分的递归性质。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/09/01 12:34

# 计算机科学漫谈 来源:https://www.humprog.org/~stephen/blog/2026/08/25/ 分散的思绪,浪费宝贵的时间 ## 2026年8月25日,星期二 ### 平面内存与分段内存——这是个递归问题最近我对x86分段机制的研究[1](https://www.humprog.org/~stephen/blog/research/system-call-instrumentation-on-intel-negative-result.html)[2](https://www.humprog.org/~stephen/blog/research/system-call-instrumentation-on-intel-negative-result-part-two.html)让我注意到x86架构演进中的一个趋势:细粒度内存保护的衰退。这种趋势既体现在向64位架构的过渡中,实际上也早于快速系统调用功能[https://wiki.osdev.org/SYSENTER](https://wiki.osdev.org/SYSENTER)的发展。这两者都部分削弱了精细的分段系统——这本是自286处理器以来该架构的显著特征。其原因可能在于Unix:Unix的主导地位及其对平面地址空间(而非分段地址空间)的偏好,可能源自PDP-11甚至PDP-7架构,这意味着"没人需要"分段特性的64位版本。 与此同时,我喜欢在WebAssembly爱好者中开玩笑说"分段内存正在回归"。WebAssembly很像是回到了OS/2或其他非Unix操作系统的编程模型——在那里平面内存并非至高无上。 当然,这种非平面特性对安全与可靠性仍然至关重要。我最近重读了Poul-Henning Kamp那些常读常新的文章,他将CHERI描述为对抗"任何速度下都不安全"平面内存模型的反应[https://dl.acm.org/doi/fullHtml/10.1145/3534854](https://dl.acm.org/doi/fullHtml/10.1145/3534854)。Kamp指出,软件在任何平面内存上首先要做的就是对其施加某种细分结构。 理解这个问题的一个角度是:硬件在多大程度上应该知晓这种细分结构……CHERI的回答是肯定的,而早期硬件的答案是否定的——当然在某些特定情况下,存在一堆分段机制! - 当然,x86中实现的分段机制并不具备实现细粒度隔离所需的语义,即无法在非平面地址空间的适当角落内进行隔离。非特权代码可以重载段寄存器,从而访问任何已定义的段(仅受限于非常粗粒度的四环权限模型)。因此,传统分段的非平面特性更多是为了故障隔离而非安全:它仅在用户/系统这种粗粒度区分下是安全的,除此之外只防无心之失,不防恶意攻击。 不过,我认为"非此即彼"的看待方式是错误的。这是个递归问题!当我们在平面内存上施加某种细分结构后,我们喜欢再次施加——可以想象内存池或内存区域,也可以想象结构体(嵌套结构体)中的字段。问题不在于是否平面——程序员的思维抽象从来都不是平面的——而在于我们如何协调程序员实践中的递归现象(即细分)与硬件(本质上是非递归的)之间的关系。硬件在概念上是有限状态的,其工程实践倾向于固定结构和有界深度;也许超级复杂指令集CPU能在微代码中提供某些迭代能力,但那已接近极限。 如果硬件是非递归而软件是递归的,我们该如何调和这种差异?一种简单的方法是限制深度:假设硬件知道N层分解(可能N=1),其余由软件处理。但这并不令人满意;这是"硬件对程序员的工作撒手不管"。它导致不一致性,并在更高N值时丧失硬件附加价值。CHERI没有这样做;它保持了处理递归分解的灵活性,因为软件仍然处理递归步骤:边界可以任意窄(大约如此),但由软件精确化并显式传递。因此,在任何时刻可访问的内容,与其说取决于硬件状态,不如说取决于软件的涌现:当前执行代码的可传递闭包范围内流动的内容。(这种涌现自然引出了明显的审计难题,不过合适的工具可以解决。) 有趣的是,CHERI通过一种限制获得了这种灵活性:寻址被约束在一条不间断的能力链上,该链的边界单调递减。我始终对这种权衡感到些许不安,因为软件就是软件,某些程序会选择特立独行,比如执行奇特的非单调地址计算。我们数十年来用软件表达遍历某种细分地址空间的程序传统——随心所欲的实现方式——与任何更具主见的新硬件都会产生摩擦。克服这点只是开发工作量的问题,但要使这种努力常态化,即其成本在行业内"成功"外部化,需要CHERI(或类似技术)"获胜"。(当然,这种成本会带来巨大回报。但"获胜"意味着实现硬件普及,这是一场高风险游戏。) 通过liballocs[https://github.com/stephenrkell/liballocs/](https://github.com/stephenrkell/liballocs/),我"乐得"不那么关注安全性,因此大可不必陷入规定地址派生规则的事务。我更专注于描述性地捕捉真实软件在递归细分其初始平面地址空间时可能产生的任何结构。其核心是递归抽象:分配嵌套于其他分配中,形成树形结构。也不存在"N层切断"或硬件/软件划分:它本质上是软件驱动的,希望通过尽可能统一的反射抽象来捕捉完整的结构层次,尽管系统内存在多样化的异构实现。这种"统一接口,异构实现"的理念当然常与面向对象相关联,而与硬件鲜有关联。 - 虽然liballocs本身并不规定程序如何使用其追踪的递归细分结构,但它确实可用于构建增加安全性的机制(施加某些约束)——但前提是,底层硬件为在相同地址空间内保障这些机制本身提供了有用的原语,否则只能防范无心之失而非恶意攻击。令人烦恼的是,如果操作系统确实向用户空间暴露了x86风格的分段机制,它本可以成为近乎充分的基础。关于我所期望的大致方案,我常想起那篇有趣的论文《x86环的领主》[https://dl.acm.org/doi/10.1145/3243734.3243748](https://dl.acm.org/doi/10.1145/3243734.3243748)。 附带一提,以另一个面向对象的观点作结:经典语言虚拟机的细分方式采取了与硬件完全相反的策略:几乎所有东西都被细分为微小对象和它们之间庞大的显式互引用(指针)关系。程序员脑海中无疑有更粗粒度的结构,但仅止于此:系统不会围绕这些结构组织存储。结果,这些系统也放弃了空间局部性——硬件将字节或字组合成更大单元的启发式优化——因此这类方法长期存在性能劣势。 *[研究](https://www.humprog.org/%7Estephen/blog/research) [所有条目](https://www.humprog.org/%7Estephen/blog-all.html) 固定链接 [联系作者](https://www.humprog.org/~stephen/#contact)* --- Powered by blosxom (http://blosxom.sourceforge.net/) 验证此页面 (http://validator.w3.org/check?uri=https://www.humprog.org/%7Estephen/blog)

相似文章

8086分段内存是一个好主意

Hacker News Top

一项回顾性分析认为,8086分段内存架构是一个巧妙的设计,本可以优雅地扩展,但软件开发者坚持将内存视为平坦空间,导致了其被认为存在缺陷。

采用CHERI实现内存安全与细粒度隔离

Lobsters Hottest

David Chisnall 介绍了 CHERI,一种硬件能力架构,通过 ARM Morello、RISC-V 和 CHERIoT 微控制器等 ISA 扩展实现内存安全和细粒度隔离。该演讲强调了实用编程模型对于安全隔离的重要性。