嘗試從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中文網其他相關文章!