如何在WASM中调用exec链式加载另一个WASM程序?解决报错45问题
WASM中调用exec加载另一个WASM程序报错45(Operation not supported)
问题描述
我在WASM中调用exec加载另一个WASM程序时,出现错误45(Operation not supported)。想请教有没有启用exec的相关编译标志?或者callee.wasm是不是exec调用的正确文件格式?
操作终端步骤
> emcc callee.c -o callee.wasm > emcc caller.c --embed-file callee.wasm -o index.html > # 实际将通过index.html运行,但node用于开发更高效 > # 注意:MEMFS工作目录为"/",且"/callee.wasm"存在 > node index.js Caller Caller: 45
caller.c代码
#include <errno.h> #include <stdio.h> #include <unistd.h> int main() { printf("Caller\n"); char *args[] = {"./callee.wasm", NULL}; execvp(args[0], args); printf("Caller: %d\n", errno); }
callee.c代码
#include <stdio.h> int main() { printf("Success!\n"); }
注:这是简化版本,请勿建议将printf("Success!\n");放入caller.c中以完全规避exec调用。
问题解析与解决方案
错误根源
错误码45对应ENOSYS(Operation not supported),原因有两点:
- Emscripten未实现exec系列调用:WASM运行在沙箱环境中,没有原生操作系统的进程管理能力,Emscripten的syscall层直接对
execvp这类函数返回不支持错误,不存在可以启用它的编译标志。 - callee.wasm不是exec可识别的格式:
exec系列函数用于加载并执行原生操作系统的可执行文件(如ELF、PE),而callee.wasm是纯WebAssembly模块,没有系统级的执行入口,即使exec能调用也无法运行。
替代实现(满足模块加载需求)
如果需要在主程序中加载并运行另一个WASM模块的逻辑,可使用Emscripten的动态链接机制,模拟类似“外部程序调用”的效果:
- 编译callee为动态链接模块
emcc callee.c -o callee.wasm -s EXPORTED_FUNCTIONS=['_main'] -s SIDE_MODULE=1
- 修改caller.c使用动态加载API
#include <errno.h> #include <stdio.h> #include <dlfcn.h> typedef void (*MainFunc)(void); int main() { printf("Caller\n"); // 加载动态模块 void* handle = dlopen("callee.wasm", RTLD_NOW); if (!handle) { printf("dlopen failed: %s\n", dlerror()); return 1; } // 获取模块中的main函数 MainFunc callee_main = (MainFunc)dlsym(handle, "_main"); if (!callee_main) { printf("dlsym failed: %s\n", dlerror()); dlclose(handle); return 1; } // 执行另一个模块的逻辑 callee_main(); dlclose(handle); return 0; }
- 编译caller时启用动态链接支持
emcc caller.c --embed-file callee.wasm -o index.html -s ALLOW_MEMORY_GROWTH=1 -s DYNAMIC_LINKING=1
内容的提问来源于stack exchange,提问作者jmpsabisb
相关产品推荐
相关产品推荐

