おそらく、これらのリンクが役立つかもしれません:
- 運用中の PID 名前空間
- PID 名前空間の簡単な紹介 (これはシステム管理者からのものです)
2 番目のリンクをたどると、名前空間がリソースを分離する優れた方法であることが明らかになります。Linux を含むどの OS でも、プロセスは存在する最も重要なリソースの 1 つです。彼自身の言葉で
はい、それだけです。この名前空間を使用すると、PID の番号付けを再開して、独自の「1」プロセスを取得できます。これは、プロセス識別子ツリーの「chroot」と見なすことができます。日々の仕事で pid を処理する必要があり、4 桁の数字に悩まされている場合に非常に便利です…</p>
したがって、独自のプライベート プロセス ツリーを作成し、それを特定のユーザーや特定のタスクに割り当てます。このツリー内では、プロセスは PID がこの「コンテナ」の外部のものと競合することを心配する必要はありません。したがって、このツリーを別の「ルート」ユーザーに完全に引き渡すのと同じくらい良いことです。そのすばらしい仲間は、すばらしい例を挙げて物事を説明する素晴らしい仕事をしてくれたので、ここでは繰り返しません。
カーネルに関する限り、私はあなたが始めるためのいくつかの指針を与えることができます. 私はここの専門家ではありませんが、これがある程度役立つことを願っています。
この LWN記事では、PID の古い見方と新しい見方について説明しています。それ自身の言葉で:
タスクが持つ可能性のあるすべての PID については、 に説明がありstruct pid
ます。この構造には、ID 値、この ID を持つタスクのリスト、参照カウンター、および検索を高速化するためにハッシュ テーブルに格納されるハッシュ リスト ノードが含まれます。タスクのリストについてもう少し説明します。基本的に、タスクには、プロセス ID (PID)、プロセス グループ ID (PGID)、およびセッション ID (SID) の 3 つの PID があります。PGID と SID はタスク間で共有される場合があります。たとえば、2 つ以上のタスクが同じグループに属し、各グループ ID が複数のタスクをアドレス指定する場合などです。PID 名前空間により、この構造は柔軟になります。現在、各 PID には複数の値があり、それぞれが 1 つの名前空間で有効です。つまり、ある名前空間ではタスクの PID が 1024 で、別の名前空間では 256 である可能性があります。したがって、前者struct pid
は変更されます。これが方法です
struct pid
PID 名前空間を導入する前は、次のように見えました。
struct pid {
atomic_t count; /* reference counter */
int nr; /* the pid value */
struct hlist_node pid_chain; /* hash chain */
struct hlist_head tasks[PIDTYPE_MAX]; /* lists of tasks */
struct rcu_head rcu; /* RCU helper */
};
そして、これが今の様子です:
struct upid {
int nr; /* moved from struct pid */
struct pid_namespace *ns; /* the namespace this value
* is visible in */
struct hlist_node pid_chain; /* moved from struct pid */
};
struct pid {
atomic_t count;
struct hlist_head tasks[PIDTYPE_MAX];
struct rcu_head rcu;
int level; /* the number of upids */
struct upid numbers[0];
};
ご覧のとおり、struct upid
は PID 値を表しています。これはハッシュに格納され、PID 値を持っています。struct pid
をPID に、またはその逆に
変換するにはtask_pid_nr()
、pid_nr_ns()
、find_task_by_vpid()
、 などの一連のヘルパーを使用できます。
少し古くなっていますが、この情報はあなたが始めるのに十分公平です. ここで言及する必要があるもう 1 つの重要な構造があります。ですstruct nsproxy
。この構造は、名前空間が関連付けられているプロセスと比較して、すべての名前空間の焦点です。このプロセスの子プロセスが使用する PID 名前空間へのポインタが含まれています。現在のプロセスの PID 名前空間は、task_active_pid_ns
.
内struct task_struct
には、適切に呼ばれる名前空間プロキシ ポインタがあり、nsproxy
このプロセスのstruct nsproxy
構造を指します。task_struct
新しいプロセスを作成するために必要な手順をたどると、struct nsproxy
との間の関係を見つけることができますstruct pid
。
Linux の新しいプロセスは常に既存のプロセスからフォークされ、後でexecve
(または exec ファミリーの同様の関数) を使用してイメージが置き換えられます。したがって、の一部としてdo_fork
、copy_process
が呼び出されます。
親プロセスのコピーの一部として、次の重要なことが起こります。
task_struct
を使用して最初に複製されdup_task_struct
ます。
- 親プロセスの名前空間も を使用してコピーされ
copy_namespaces
ます。これにより、子の新しいnsproxy
構造も作成され、nsproxy ポインターはこの新しく作成された構造を指します。
非 INIT プロセス (元のグローバル PID別名ブート時に生成された最初のプロセス) の場合、PID
構造体が割り当てられます。alloc_pid
これにより、新しく作成されたプロセスに新しい PID 構造体が実際に割り当てられfork
ます。この関数の短いスニペット:
nr = alloc_pidmap(tmp);
if(nr<0)
goto out_free;
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
これupid
により、構造体に新しい PID と現在属している名前空間が与えられ、構造体にデータが入力されます。
さらにcopy process
関数の一部として、この新しく割り当てられた PID は、対応するtask_struct
via 関数にリンクされます。pid_nr
つまり、そのグローバル ID (INIT 名前空間から見た元の PID nr) が のフィールドpid
に格納されtask_struct
ます。
の最終段階で、とこの新しい構造の間に、フィールドを介して 関数 を介してcopy_process
リンクが確立されます。task_struct
pid
pid_link
task_struct
attach_pid
まだまだたくさんありますが、これで少なくとも有利なスタートが切れることを願っています。
注: 私は最新の (現時点での) カーネル バージョンを参照しています。3.17.2.