WebAssembly内存管理机制
WebAssembly内存管理机制
WebAssembly的**线性内存(Linear Memory)**是WebAssembly和JS数据交互的重要桥梁
其采用页式内存管理(Page-based memory management)
1、核心概念:什么是“页”?
在 Wasm 中,内存被划分为固定大小的连续单元,称为“页”。
- 页的大小是固定的:每页的大小为 64 KiB(即 65,536 字节)。这个值是由 WebAssembly 规范明确定义的,不可更改
- 线性内存模型:Wasm 使用一个单一的、线性的地址空间(称为“线性内存”)来存储所有数据。你可以把它想象成一个非常长的、从 0 开始编号的字节数组
- 内存的增长以页为单位:当 Wasm 模块需要更多内存时,它不能一次只申请一个字节,而是必须至少申请一页
不同于现代 OS 的虚拟内存空间,Wasm 的线性内存从设计上就是单线程、线性的,这使得其模型更适合嵌入式、高性能或安全受限环境
2、页式内存管理的关键机制
当一个 Wasm 模块被实例化时,它的内存可以指定两个属性:
initial:初始页数。内存一开始就会分配这么多页maximum(可选):最大页数。内存允许增长到的页数上限。这是一个安全边界,防止模块无限制地消耗宿主(如浏览器)的内存
内存增长:Wasm 提供了一个内置指令 memory.grow。当模块需要更多内存时(例如,在 JavaScript 中执行 new ArrayBuffer 或类似需要动态分配内存的操作时),它可以调用这个指令
1 | memory.grow(2); // 增长 2 页,总计 +128KiB |
tips:增长操作可能会导致整个线性内存被重新分配和复制到一个新的、更大的内存区域。这意味着之前指向内存内部数据的指针(内存地址)可能会失效。然而,在 WebAssembly 的设计中,内存地址是“偏移量”而不是绝对指针。因为内存是线性且由虚拟机管理的,即使底层缓冲区被移动,Wasm 模块看到的地址空间仍然是连续和一致的,模块本身无需关心物理地址的变化,这个重定位过程由宿主环境(如浏览器)透明地处理
3、实例
从 JS 向 Wasm 写入字符串,再由 Wasm 读取并转换大小写
C++代码:
1 |
|
JS代码:
1 | Module = {}; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Oreo's Blog!