ホームページ  >  記事  >  バックエンド開発  >  Go マルチスレッド環境で「setns」が EINVAL で失敗するのはなぜですか?

Go マルチスレッド環境で「setns」が EINVAL で失敗するのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-11-01 09:23:30646ブラウズ

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

Go からの 'setns' の呼び出しが MNT 名前空間の EINVAL で失敗する

問題

MNT に入るために Go から 'setns' を呼び出しようとしたときネームスペースの場合、呼び出しは一貫して EINVAL を返します。この問題は、同じ機能の C 実装が正しく動作しているにもかかわらず発生します。

原因

この問題は、Go がマルチスレッド言語であるのに対し、'setns' はマルチスレッド言語であることを期待しているという事実に起因します。シングルスレッドコンテキストから呼び出されます。マルチスレッド環境から呼び出された場合、「setns」は現在のスレッドをターゲットの名前空間に正しく関連付けることができません。

解決策 - CGO コンストラクターのトリック

この問題の解決策は、 「CGO コンストラクターのトリック」この手法を使用すると、Go ランタイムが初期化される前に実行される C 関数を指定できます。このアプローチを使用すると、Go スレッドが作成される前に C 関数で 'setns' を呼び出すことができ、確実にシングルスレッド コンテキストで呼び出しが行われるようになります。

  1. 'setns' を呼び出す C 関数を構築する' 必要なパラメータを指定します。これを行うには、関数を __attribute__((constructor)) マクロで装飾します。
  2. import "C" を使用してインポートして、Go コードに C 関数を組み込みます。

作業例

<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>

プレースホルダー を忘れずに置き換えてください。

制限事項

このアプローチにはいくつかの制限があります。

  • Go のように、PID は C 関数内でハードコーディングする必要があります。 C 関数の実行時にはコードが利用できない可能性があります。
  • C コードは Go ランタイムの初期化前に実行されるため、Go コード内から 'setns' を複数回呼び出すことはできません。

追加メモ

「setns(2)」へのパッチは、マルチスレッド環境でのシングルスレッド実行の要件を確認します。機能を持つプロセスは、独自のユーザー名前空間に CAP_SYS_CHROOT と CAP_SYS_ADMIN を、ターゲット マウント名前空間に CAP_SYS_ADMIN も持つ必要があります。

以上がGo マルチスレッド環境で「setns」が EINVAL で失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。