尝试从 Go 调用 'setns' 进入 MNT 时命名空间,调用始终返回 EINVAL。尽管相同功能的 C 实现正常工作,但仍观察到此问题。
该问题源于 Go 是一种多线程语言,而 'setns' 期望是从单线程上下文调用。当从多线程环境调用时,“setns”无法正确地将当前线程与目标命名空间关联起来。
此问题的解决方案是利用“CGO 构造函数技巧。”该技术允许您在 Go 运行时初始化之前指定要执行的 C 函数。通过使用这种方法,您的 C 函数可以在创建 Go 线程之前调用“setns”,确保调用是在单线程上下文中进行的。
<code class="go">/* #include <sched.h> #include <stdio.h> #include <fcntl.h> __attribute__((constructor)) void enter_namespace(void) { setns(open("/proc/<PID>/ns/mnt", O_RDONLY, 0644), 0); } */ import "C" ... rest of file is unchanged ... </code>
请记住将占位符
这种方法有一些限制:
“setns(2)”的补丁确认了多线程环境中单线程执行的要求。具有功能的进程还必须在自己的用户命名空间中拥有 CAP_SYS_CHROOT 和 CAP_SYS_ADMIN,并在目标挂载命名空间中拥有 CAP_SYS_ADMIN。
以上是为什么在 Go 多线程环境中“setns”会失败并显示 EINVAL?的详细内容。更多信息请关注PHP中文网其他相关文章!