MNT に入るために Go から 'setns' を呼び出しようとしたときネームスペースの場合、呼び出しは一貫して EINVAL を返します。この問題は、同じ機能の C 実装が正しく動作しているにもかかわらず発生します。
この問題は、Go がマルチスレッド言語であるのに対し、'setns' はマルチスレッド言語であることを期待しているという事実に起因します。シングルスレッドコンテキストから呼び出されます。マルチスレッド環境から呼び出された場合、「setns」は現在のスレッドをターゲットの名前空間に正しく関連付けることができません。
この問題の解決策は、 「CGO コンストラクターのトリック」この手法を使用すると、Go ランタイムが初期化される前に実行される C 関数を指定できます。このアプローチを使用すると、Go スレッドが作成される前に C 関数で '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 中国語 Web サイトの他の関連記事を参照してください。