首頁  >  文章  >  後端開發  >  為什麼從 Go 呼叫“setns”會為 Mnt 命名空間返回“EINVAL”?

為什麼從 Go 呼叫“setns”會為 Mnt 命名空間返回“EINVAL”?

Linda Hamilton
Linda Hamilton原創
2024-11-02 21:00:30388瀏覽

Why Does Calling `setns` from Go Return `EINVAL` for Mnt Namespace?

從Go 調用setns 返回mnt 命名空間的EINVAL

問題描述

Go 代碼中,嘗試進入mnt命名空間使用syscall.RawSyscall函數呼叫setns系統呼叫會傳回EINVAL錯誤。儘管設定正確且 C 實作成功進入命名空間,此問題仍然存在。

原因和解決方案

問題的根本原因在於多方面Go 的線程本質。 setns 系統呼叫必須從單執行緒上下文執行才能成功。由於 Go 應用程式預設是多執行緒的,因此必須在 Go 運行時執行緒啟動之前進行 setns 呼叫。

為了解決這個問題,可以使用「cgo 建構子技巧」。該技術允許在 Go 運行時開始之前執行 C 程式碼。透過在 C 程式碼中使用 __attribute__((constructor)) 宏,可以將函數修飾為在 Go 初始化之前在單執行緒 C 上下文中執行。

修改後的Go 程式碼

以下修改後的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>

透過利用cgo 建構函數技巧,Go 應用程式現在可以使用setns 系統呼叫成功進入mnt 命名空間。

以上是為什麼從 Go 呼叫“setns”會為 Mnt 命名空間返回“EINVAL”?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn