WebAssembly
WebAssembly 是一个相对较新的标准,主要是在网页上支持与体系结构无关的可执行文件。 但它远不止这些,而且它的特定规范方式造成了它独特的特性,适合于语言、操作系统和机器独立的可执行格式。
基本原理
您可能会问,任何Web技术与OS内核有什么关系。 事实上,WebAssembly(简称WASM)这个名称很容易引起误解,其实它是一种非常明确的字节码格式,具有最小的解释环境,根本不需要任何与Web相关的技术。
内核都已经有一个可执行的格式加载器和解析器(就像ELF解析器一样),但这必须使用本机CPU指令。 假如在其中添加一个小字节码解释器将允许任何业余操作系统执行机器和操作系统独立的二进制文件,这是一个很大的好处。 这与不同的安卓设备使用Java执行专有的APK系统的方式类似。
与Java和Dalvik(译者注:Dalvik是Android里的定制JVM)不同,解释WebAssembly二进制文件要容易得多,没有法律问题,而且已经有用多种语言编写的许多库可以做到这一点(最著名的是C和Rust)。
与其他字节码格式的比较
Lua
Lua是一种非常流行的脚本语言。 然而,它的编译器、解释器和执行环境混合在一个库中。 这对于与用户空间应用程序集成是很好的,但是很难嵌入到内核中 (内核集成只需要字节码解释器部分)。 而且它的字节码格式并没有真正标准化,尽管看起来相当稳定。
Python
尽管看起来很奇怪,但并不存在像Python字节码标准这样的东西。 因此,将Python解释器嵌入到内核中是非常不可能的。 有一些解释器库可以链接进来,但正如格式一样,它们也在不断地变化、更新,并且仅限于特定版本的Python。
Java
Java有一个非常好的已定义字节码格式,但不幸的是没有简单的字节码解释器库。 官方的JVM和它的开源软件都是巨大的臃肿软件,并不是真正为嵌入内核而设计的。 即使有一个简单的解释器库,Java也是由Oracle授权的,使用也要遵守某些法律条款。 更清楚地说,Android根本不使用Java字节码,它解释的是Dalvik字节码,虽然这是从Java源代码编译而来的。
WebAssembly
与其他语言不同,WebAssembly与任何编程语言无关,而是W3C制定的开放规范。 因此,可以将C、C++、RISE、PASCAL甚至BASIC编译成WASM字节码。 此外,执行环境是分开的,并且定义得很好,因此有许多实现可供选择。
产生WASM字节码的最著名的C/C编译器之一是 EmScripten,它构建在LLVM编译器体系结构之上。 有一个W3C提供的“参考字节码解释器”,该解释器采用OCAML语言,旨在实现简单性(而非速度)。
WebAssembly文档规范允许无限的语言和翻译器,并且不涉及许可问题。 您可以自由使用任何WASM编译器的任何语言,并在您的内核中实现自己的解释器。
WebAssembly 解释器术语
- WASM: 包含BINARY WEB ASSEMBLY BYTE CODE的文件名,也是引用解释器(reference interpreter)的名称。
- WAT: WebAssembly文本源代码格式,是字节码的 纯文本表示 (请参阅 Binaryen wasm-at工具)。
- WABT: WebAssembly二进制工具包,相当于binutils。 包括汇编程序、对象转储(objdump)和其他工具(参见WABT)。
- MVP: 最小可行产品(Minimal Viable Product),这意味着最小的WASM解释器 (不需要或不包括任何与网络相关的)。 定义于WebAssembly核心规范
- WASI: WebAssembly系统接口(System Interface),它定义了一套ABI和一组函数,即字节码如何与操作系统和非WASM库交互。
- EmScripten: WASI模块,EmScripten编译器可能生成代码的功能如内存分配等所有东西。 简单地说,这是WebAssembly中的libc(译者注:Linux下的ANSI C的核心函数库)。
- Web API: 将WebAssembly集成到网页中的标准化方式,目前并不是我们关心的问题。 请注意,Web API对于WebAssembly是 “可选的”。
链接
WebAssembly有一个非常干净的模块链接接口WASI。 还定义了独立于操作系统的简单非Web集成。 WebAssembly有官方的POSIX和SDL模块(更像是库包装器),但非官方的第三方库的数量正在与日俱增。
现在提供了针对JavaScript、C/C++、Rust、Python和许多其他语言的链接,并且经过了良好的测试。 对于内核开发,主要对 C 或Rust链接会感兴趣。 这里是一分不完整和成长中的链接器列表。
目前,Emcripten模块用于操作系统接口,但这种情况很快就会改变。 WASI要付出巨大的努力,以musl为参考,为WASM字节码提供了功能齐全的libc接口。 一旦WASI规范被冻结,您只需要实现或包含一个WASI解释器。
二进制格式
WASM文件以四个字节的魔术 “asm\001” 开头,其中最后一个字符表示格式版本。 因此,很容易识别。
在头之后是几个节(Section),其中一个包含字节码。 binutils等效的WABT包括一个名为wasm-objdump的工具来转储这些并反汇编字节码。 详细信息和编码由WebAssembly核心规范(WebAssembly Core Specification)指定二进制格式。
另见
规范清单
- WebAssembly Core Specification
- WASI, 在Web浏览器之外运行WASM的ABI规范
- WASI overview
- CommonWA 非Web用户模式环境的标准API的最低规范
- WebAssembly on Wikipedia
- WebAssembly on Mozilla Development Network
- Rust and WebAssembly
编译器
- EmScripten, 产生WASM字节码的参考C/C++编译器
- LLVM 很好地描述了如何使用LLVM的缺省wasm目标‘’而不使用臃肿的EmScripten
- Asterius, 产生WASM字节码的 Haskell 编译器
- wasm-pack 产生WASM字节码的Rust编译器
- JWebAssembly, 一个Java字节码到WebAssembly字节码的转换器
- Binaryen, W3C提供的用于WebAssembly的底层工具
- Cranelift, Rust中的WASM到本机代码编译器
解释器(Interpeters)
- Reference Interpreter 在OCaml中(译者注:一种编程语言),由W3C提供
- libwasmint W3C提供的C++中的解释器,这是一个为嵌入而设计的库
- wasm-interp C++中的解释器,它是WABT的一部分,比libwa mint更完整
- wasmtime 还有另一个wasm解释器,这次是在WASI支持下的rust中 (这是WASI的参考实现)
- wac, wax, wace 在C中的解释器,这提供了MVP、WASI、EmScripten的兼容性;可能是最容易嵌入内核的
- wasm3 C语言中的解释器,目标是高性能和WASI兼容性
- wasmi, Rust 中的解释器
- wasmtime Mozilla在Rust中的解释器,支持WASI
- pywasm Python中的解释器
- life Go中的解释器
- wasmjit C中的Linux内核模块,用于运行wasm字节码
- cervus C中的Linux的WebAssembly子系统
- PWASM 易于集成WASM执行库 (使用DynASM JIT) 以 C编写
示例
- kwast 这是一个用Rust编写的内核,它在用户空间运行wasm字节码(从2020年初开始大量开发)。
- wasm-mandelbrot 示例如何使用EmScripten、wasm-toolchain、clang BinaryEm等。
- WebAssembly examples by Mozilla
- WASM的Rust教程 by Mozilla