编程语言研究书库

WASI — WebAssembly 的系统接口

WASI — WebAssembly 的系统接口

1. 这一章讲什么

Wasm 的承诺是「一次编译,到处运行」,但出了浏览器它连一个文件都打不开—— 原始的 Wasm 设计里根本没有系统调用这回事。WASI(WebAssembly System Interface) 就是补这个洞的:一套标准化的系统 API,让模块能读写文件、看时钟、取随机数、读环境变量, 同时把 Wasm 的安全哲学(默认拒绝、逐项授权)贯彻到底。前面章节里它已经出现多次 (Node 的 preopens、边缘固件更新的能力限制),这一章把它讲透。1

2. 顶层全景

  模块声明「我要什么」(import wasi_* 函数)
      │
      ▼
  宿主按「能力清单」逐项授权:映射目录、给环境变量、开网络口
      │  ← 能力制:不给的,模块连名字都看不见
      ▼
  模块经文件描述符(fd)操作资源:open → read/write → close
      │
      ▼
  运行时各家实现:Wasmtime / Wasmer / Node(实验) / 浏览器(需 polyfill)

图说:WASI 的全部设计就压在这一张图里——声明、授权、操作、落地四层。

3. 核心原理

3.1 为什么需要 WASI,它守住的三条原则

Wasm 起初是纯浏览器技术;想在服务器、IoT、桌面上跑,第一步就撞上: 没有文件、没有网络、没有环境变量。WASI 由 Bytecode Alliance (Mozilla、Fastly、Intel 等组成的联盟)推出,三条设计原则:2

原则含义
可移植模块在 Linux/Windows/macOS 上行为一致,不改源码
能力制安全模块只能碰显式授予的资源——不是「先全给再拦」,而是「默认零权限,逐项发」
可扩展API 按领域拆成模块,云、边、IoT 各自生长

「能力制」和日常的操作系统权限模型对比一下就懂了:传统模型是进程以「用户」身份运行, 能做用户能做的一切;能力制是资源逐个授予——这个模块只能读 /sandbox 目录、 那个模块只能连某个端口。被攻破的模块,偷不走没被授予的东西。3

3.2 API 组成:描述符、调用、模块划分

WASI 的 API 围绕文件描述符(fd,一个代表文件/目录/套接字的数字句柄,和 Unix 同款概念) 展开。三组核心函数:4

组函数干什么
文件path_open / fd_read / fd_write / fd_filestat_get开、读、写、查元数据
系统clock_time_get / random_get / proc_exit时钟、安全随机数、退出
环境environ_get / environ_sizes_get / args_get环境变量、命令行参数

API 按模块拆分:wasi-filesystem、wasi-clocks、wasi-random…… 想用一个就 import 一个,攻击面和体积都跟着最小化。当前稳定快照叫 wasi_snapshot_preview1——名字里的 preview1 用了很多年,它仍是 事实标准,模块和运行时要锁同一个版本。5

3.3 文件 I/O 的完整生命周期

书里的 C 例(伪码级,但函数名都是真的),三步走:6

int fd;
__wasi_path_open("/input.txt", __WASI_OFLAGS_RDONLY, &fd);   // ① 开
__wasi_fd_read(fd, buffer, sizeof(buffer), &nread);          // ② 读
__wasi_fd_close(fd);                                          // ③ 关

链路是 open → read → close,和 Unix 习惯完全一致,区别只在: path_open 里的路径是相对于授予目录解析的,模块没有绝对路径概念。7

3.4 网络:还是半成品

诚实的一节:wasi-sockets 仍是提案,TCP/UDP 插座在推进中; HTTP 更没有标准化——目前由运行时各自提供(Wasmtime 的扩展之类)。 能力制同样管网络:只授「某个出站连接」是设计目标。8

这意味着 2026 年前后写「WASI 网络应用」仍然是运行时绑定编程—— 代码能跑在 Wasmtime 上,不代表能跑在 Wasmer 上,跨运行时可移植性在这里打折。 书里的判断和我们一致:这是 WASI 标准化的下一个主战场。9

3.5 环境变量与进程管理

读环境变量是两步协议,书里给了完整 C 例:10

size_t count, buf_size;
__wasi_environ_sizes_get(&count, &buf_size);   // ① 先问「多少个、要多大缓冲」
char** environ = malloc(buf_size);
__wasi_environ_get(environ, buf_size);          // ② 再一次性取回
for (size_t i = 0; i < count; i++) printf("%s\n", environ[i]);

为什么分两步?线性内存里的一切都要预先知道大小——这和第 4 章「先 malloc 再写入」 是同一条纪律在系统 API 层的翻版。进程侧:退出用 proc_exit(code), 命令行参数走 args_get / args_sizes_get(同样的两步式)。11

3.6 在哪跑、怎么跑

四个落地环境,书里一张对照:12

环境WASI 支持
Wasmtime轻量、合规度最高,事实标杆
Wasmer可嵌入,支持 WASI 与 Emscripten
Node.js内置 wasi 模块(实验性)
浏览器基本不支持,需要 polyfill

跑起来的两步:13

wasienv cc program.c -o program.wasm     # ① 用 wasienv(或 Emscripten/clang)编译
wasmtime run --dir=. program.wasm        # ② 跑;--dir=. 就是把当前目录授给它

--dir=. 就是能力制的实操形态:不挂这个旗标,程序连当前目录都看不见。

3.7 主线例子:目录映射授予(把机制走一遍)

书里的受限访问例,一行命令走完授权全程:14

wasmtime run --dir=/safe/path::/app/files program.wasm

读法:宿主机的 /safe/path 目录,在模块眼里挂成 /app/files—— 模块只能在这个映射进来的目录里做文件操作,路径对它来说是绝对的, 对宿主机来说是相对授予的。把这个和「普通进程以用户身份运行」对比: 用户家目录、系统配置、别的进程的文件,这个模块一概摸不到。 CSV(逗号分隔的表格文本)处理例(读 input.csv → 转换 → 写 output.csv)就是在这个授予目录里跑的业务。15

3.8 前景与挑战

在路上的三个:wasi-sockets 标准化、共享内存多线程、模块间动态链接。 影响面:云(serverless,Fastly Compute@Edge 是样板)、边缘、跨平台「一份二进制」。 三个挑战书里没有回避:运行时性能(解释执行 vs AOT)、标准化时间表、 开发者工具链单薄。16

4. 作者的判断与证据

  • 能力制设计:这是 WASI 被业界接受的第一原因,描述准确;
  • 「preview1 是当前稳定版」:属实,但书里没提 preview2 已发布、正在推进的事实 (补充,不在书里:WASI 0.2/Component Model 路线已落地,p1 与 p2 并存,新项目选型要看运行时支持)—— 这是本章最大的时效缺口;
  • 网络「依赖运行时扩展」:诚实且准确。

判断(我们的,不是书里的): WASI 一章最该带走的是「授权面 = 攻击面」这条等式: 传统部署里,进程能访问什么由「它是谁」决定;WASI 里由「它拿到什么」决定—— 这两句话的差别,就是边缘多租户敢把陌生代码跑起来的原因。 如果错,会错在: 如果能力制的授权管理复杂度(成百上千个模块 × 各自的能力清单) 在实践中压倒安全收益,运营方会退回粗粒度方案(整容器/整 VM 授权), WASI 的这块长板就会被「管理成本」抵消——已有平台在两者之间摇摆。

5. 边界与局限

  • preview2/Component Model 缺席:全书以 preview1 为默认,新一代接口模型只在别章零星出现;
  • HTTP 服务端怎么写只有 Rust 骨架两行,没有可跑的完整例子;
  • 性能对比数据缺席:WASI 系统调用相对原生系统调用的开销没有量化;
  • 错误处理的系统走查(WASI 函数返回 errno 的惯例)只提了一句。

6. 可带走的

  1. WASI = Wasm 缺的系统调用层;出生就是为了「出浏览器还能当正经程序跑」。
  2. 能力制三句话:默认零权限、逐项显式授予、被偷也偷不走没授予的。
  3. fd 是一切资源的句柄;文件生命周期 open → read/write → close。
  4. 两步式 API(environ_sizes_get → environ_get)是线性内存「先报大小」纪律的系统层翻版。
  5. 快照名 wasi_snapshot_preview1;模块和运行时要锁同一版本。
  6. 授权实操:wasmtime run --dir=宿主目录::模块内目录 program.wasm。
  7. 网络还没标准:wasi-sockets 是提案,HTTP 靠运行时扩展——写网络应用先选运行时。
  8. 落地四环境:Wasmtime(标杆)、Wasmer、Node(实验)、浏览器(要 polyfill)。
  9. 最佳实践:最小授权、缓冲 I/O、锁版本、跨运行时测试。
  10. 挑战记住三个:性能、标准化时间表、工具链。

7. 原文地图

主题原书章原文位置
WASI 的由来与三原则WebAssembly System Interface (WASI)text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:57(搜「lacked direct access」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:67(搜「Portability:」)
Bytecode Alliance 与历史同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:99(搜「Bytecode Alliance」)
API 组成:fd/系统调用/环境同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:117(搜「File Descriptors」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:133(搜「System Calls」)
模块化设计同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:163(搜「Modularity」)
版本快照同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:211(搜「wasi_snapshot_preview1」)
文件 I/O 生命周期同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:281(搜「read_file」)
网络现状与限制同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:323(搜「wasi-sockets」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:365(搜「No standardized HTTP API」)
环境变量两步式同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:411(搜「print_env」)
运行环境与两步跑法同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:455(搜「Supported Runtimes」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:481(搜「wasienv cc」)
CSV 例与目录映射同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:525(搜「process_csv」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:627(搜「/safe/path::/app/files」)
前景与挑战同上text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:557(搜「Emerging Features」) · text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:587(搜「Challenges」)

Footnotes

  1. 出处:「WebAssembly System Interface (WASI)」第 51–95 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:55,搜「outside the browser」)。 ↩

  2. 出处:「WebAssembly System Interface (WASI)」第 59–83 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:65,搜「secure, portable, and modular access」)与 text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:99(搜「Bytecode Alliance」)。 ↩

  3. 出处:「WebAssembly System Interface (WASI)」第 71–79 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:75,搜「capability-based」)。「Modules only access explicitly granted resources」见 text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:79(搜「explicitly granted」)。 ↩

  4. 出处:「WebAssembly System Interface (WASI)」第 115–155 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:117,搜「File Descriptors」)。 ↩

  5. 出处:「WebAssembly System Interface (WASI)」第 161–213 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:167,搜「wasi-clocks」)与 text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:211(搜「wasi_snapshot_preview1」)。 ↩

  6. 出处:「WebAssembly System Interface (WASI)」第 275–297 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:285,搜「__wasi_fd_open」)。 ↩

  7. 出处:「WebAssembly System Interface (WASI)」第 299–311 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:311,搜「open → read → close」)。 ↩

  8. 出处:「WebAssembly System Interface (WASI)」第 313–367 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:323,搜「wasi-sockets」)与 text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:365(搜「No standardized HTTP API」)。 ↩

  9. 出处:「WebAssembly System Interface (WASI)」第 365–367 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:367,搜「Dependent on runtime features」)。 ↩

  10. 出处:「WebAssembly System Interface (WASI)」第 387–431 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:417,搜「environ_sizes_get」)。 ↩

  11. 出处:「WebAssembly System Interface (WASI)」第 433–449 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:437,搜「proc_exit」)。 ↩

  12. 出处:「WebAssembly System Interface (WASI)」第 451–509 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:455,搜「Supported Runtimes」)。 ↩

  13. 出处:「WebAssembly System Interface (WASI)」第 477–487 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:485,搜「wasmtime run --dir=」)。 ↩

  14. 出处:「WebAssembly System Interface (WASI)」第 625–627 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:627,搜「--dir=/safe/path::/app/files」)。 ↩

  15. 出处:「WebAssembly System Interface (WASI)」第 515–539 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:525,搜「process_csv」)。 ↩

  16. 出处:「WebAssembly System Interface (WASI)」第 551–593 段(text/21-fm-ultimate-webassembly-for-high-performance-apps-b.txt:587,搜「Challenges」)。 ↩

On this page