WebAssembly(WASM)虚拟文件系统(FS)是一个用于在WebAssembly环境中模拟文件系统的工具。它允许开发者在浏览器或其他WebAssembly运行环境中使用类似于本地文件系统的功能。Emscripten提供了一个虚拟文件系统,以兼容libc/libcxx的同步文件访问函数。
Emscripten 虚拟文件系统架构
Emscripten 虚拟文件系统架构包括三种主要的文件系统:
- MEMFS:MEMFS 内存文件系统,数据存储于内存中,页面刷新或程序重载后数据丢失
- NODEFS:Node.js 文件系统,可以访问本地文件系统,适用于 Node.js 环境
- IDBFS:IndexedDB 文件系统,基于浏览器的IndexedDB对象,可以持久化存储
这些文件系统通过 JavaScript 对象FS封装,供 fopen()、fread()、fwrite() 等 libc/libcxx 文件访问函数调用。
MEMFS
在使用MEMFS之前,需要将文件打包。可以使用emcc命令行或file_packager.py工具进行打包。以下是一个简单的示例:
// packfile.cc
int main() {
FILE* fp = fopen("hello.txt", "rt");
if (fp) {
while (!feof(fp)) {
char c = fgetc(fp);
if (c != EOF) {
putchar(c);
}
}
fclose(fp);
}
return 0;
}
使用以下命令打包文件:
emcc packfile.cc -o packfile.js --preload-file hello.txt
NODEFS示例
NODEFS允许访问本地文件系统,以下是一个使用NODEFS的示例:
// nodefs.cc
void setup_nodefs() {
EM_ASM(
FS.mkdir('/data');
FS.mount(NODEFS, {root:'.'}, '/data');
);
}
int main() {
setup_nodefs();
FILE* fp = fopen("/data/nodefs_data.txt", "r+t");
if (fp == NULL) fp = fopen("/data/nodefs_data.txt", "w+t");
int count = 0;
if (fp) {
fscanf(fp, "%d", &count);
count++;
fseek(fp, 0, SEEK_SET);
fprintf(fp, "%d", count);
fclose(fp);
printf("count:%d\n", count);
} else {
printf("fopen failed.\n");
}
return 0;
}
使用以下命令编译代码:
emcc nodefs.cc -o nodefs.js
IDBFS示例
IDBFS基于IndexedDB,可以持久化存储数据。以下是一个使用IDBFS的示例:
void sync_idbfs() {
EM_ASM(
FS.syncfs(function (err) {});
);
}
EM_PORT_API(void) test() {
FILE* fp = fopen("/data/nodefs_data.txt", "r+t");
if (fp == NULL) fp = fopen("/data/nodefs_data.txt", "w+t");
int count = 0;
if (fp) {
fscanf(fp, "%d", &count);
count++;
fseek(fp, 0, SEEK_SET);
fprintf(fp, "%d", count);
fclose(fp);
printf("count:%d\n", count);
sync_idbfs();
} else {
printf("fopen failed.\n");
}
}
int main() {
EM_ASM(
FS.mkdir('/data');
FS.mount(IDBFS, {}, '/data');
FS.syncfs(true, function (err) {
assert(!err);
ccall('test', 'v');
});
);
return 0;
}