首页 > 后端开发 > Golang > 正文

为什么在 Go 多线程环境中'setns”会失败并显示 EINVAL?

Linda Hamilton
发布: 2024-11-01 09:23:30
原创
665 人浏览过

Why Does 'setns' Fail with EINVAL in a Go Multithreaded Environment?

从 Go 调用 'setns' 失败,MNT 命名空间出现 EINVAL

问题

尝试从 Go 调用 'setns' 进入 MNT 时命名空间,调用始终返回 EINVAL。尽管相同功能的 C 实现正常工作,但仍观察到此问题。

原因

该问题源于 Go 是一种多线程语言,而 'setns' 期望是从单线程上下文调用。当从多线程环境调用时,“setns”无法正确地将当前线程与目标命名空间关联起来。

解决方案 - CGO 构造函数

此问题的解决方案是利用“CGO 构造函数技巧。”该技术允许您在 Go 运行时初始化之前指定要执行的 C 函数。通过使用这种方法,您的 C 函数可以在创建 Go 线程之前调用“setns”,确保调用是在单线程上下文中进行的。

  1. 构造一个调用“setns”的 C 函数' 与所需的参数。通过使用 __attribute__((constructor)) 宏修饰函数来实现此目的。
  2. 通过使用 import "C" 导入 C 函数,将其包含在 Go 代码中。

工作示例

<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>
登录后复制

请记住将占位符 替换为与目标进程的实际 PID。

限制

这种方法有一些限制:

  • PID 必须在 C 函数中硬编码,就像 Go 一样代码在 C 函数执行时可能不可用。
  • 不可能在 Go 代码中多次调用“setns”,因为 C 代码在 Go 运行时初始化之前运行。

附加说明

“setns(2)”的补丁确认了多线程环境中单线程执行的要求。具有功能的进程还必须在自己的用户命名空间中拥有 CAP_SYS_CHROOT 和 CAP_SYS_ADMIN,并在目标挂载命名空间中拥有 CAP_SYS_ADMIN。

以上是为什么在 Go 多线程环境中'setns”会失败并显示 EINVAL?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!