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;
}