cgroup の基本的な紹介

cgroup も例外ではありません. 新しい概念の出現には理由があるはずです. cgroup も例外ではありません. 元々は Google のエンジニアである Paul Menage と Rohit Seth [1] によって提案されまし. 1 台のマシンで異なるコンピューティング モデルを使用する同じ実行ジョブで使用できます。最初は、プロセス コンテナーにちなんで名付けられました.その後、コンテナーには複数の意味があるため、誤解を招きやすい.2007 年に、名前が Control Groups に変更され、2.6.24 カーネルに統合されました.制限、記録、および分離を行うことができます.プロセス グループによって使用される物理リソース (cpu/memory/io など) および物理リソースの使用を制御する優先順位 この記事では、主にカーネル 5.10 ソース コードを参照して、cgroup の基本的な紹介を行います。

1. cgroupの構成

cgroup を使用して、プロセス グループのリソースを処理します。これは、次のコンポーネントから切り離すことはできません。

7269edef25c970b3fb0c321d74e69fbe.png

cgroupv1 は複数のレベルを許可できます. v1 の構成では、使用されるサブシステムが同じレベルに接続されている場合、サブシステムのリソース制御を分離する方法がなく、一部のプロセスが他のサブシステムの影響を受ける可能性があります. したがって、V1 では複数のレベルの組織であり、レベルはツリーと見なすことができ、フォレストと見なすことができます。

また、cgroup、タスク、サブシステム、階層の関係と基本的なルールは次のとおりです。

  1. 1 つ以上のサブシステムを同じ階層に接続できます。

  2. サブシステムを複数の階層に接続できるのは、それらの階層にこのサブシステムしかない場合だけです。

  3. 作成する階層ごとに、タスクは 1 つの cgroup にのみ存在できます。つまり、タスクは同じ階層の異なる cgroup に存在できませんが、タスクは異なる階層の複数の cgroup に存在できます。

  4. フォーク時にプロセス (タスク) によって作成された子タスク自体は、デフォルトでは元のタスクと同じ cgroup にありますが、子タスクを別の cgroup に移動することは許可されています。

1.1 サブシステムの紹介

サブシステムは主にリソースを制御するために使用されます.それは特定の制御モジュールであるため,個別に紹介されます.要件と機能の増加に伴い,次のより重要で一般的に使用されるサブシステムがあります:

475be6438b74f62cc636874cb1b6ec3b.png

これらのサブシステムを抽出するcgroupも、これらのリソース管理モジュールを再利用しています.本質的には、これらのリソース管理モジュールにフックを付けて、リソースの制限と優先度の割り当てを実現することです.

1.2 cgroup キーのデータ構造

システムが複数のレベルを持つ可能性があり、各タスクが複数のサブシステムによって制約される可能性があるため、タスクと cgroup がどのようにマッピングされるかに関心があります。したがって、タスクと cgroup は多対多の関係にあります。この関係を記録するために、リンクされたリストを追加できますが、検索と変更の効率が低すぎます. Linux では、2 つの中間データ構造 css_set と cgrp_cset_link を使用して、このマッピングを完了します。

プロセスが子プロセスを複製するときに、特定の cgroup を指定しない場合、デフォルトの子プロセスはプロセスと同じ cgroup に残り、同じ cgroup を共有するプロセスのグループが抽出され、 css_set で識別されると想像してください。各プロセスは 1 つの css_set にのみ存在します。css_set には複数のプロセスが含まれる場合があります。プロセスが cgroup 間で移行されると、すべての css_set はハッシュ テーブルを介して編成されます。css_set は作成された cgroup の共通性に基づいているため、css_set も再利用できます。

プロセス中の cgroup 情報:

a42312e695f9f03c201ae90d90db6c3c.png

css_set を使用すると、同じタイプのプロセスが css_set にリンクされますが、css_set と cgroup の間で多対多のマッピングの問題が残りますが、css_set の数はタスクの数よりも少なくなります。 , cgrp_cset_link がやってくる New 追加された 3 番目のテーブルにより、cgroup と css_sets がお互いを見つける効率が大幅に向上します。

全体的な接続関係:

3cbb4c971f24825b98624edac0250739.png

さらに、一方で css_set はプロセス情報を cset に記録し、サブシステム サブシステム (略して css) の情報も維持します。これは、2 つの間のリンクと見なすこともできます。

css_set の主要メンバー:

65c6b7661f09840507205b012045a67d.png

ec04b98cf9a813af5f83d93760344691.png

cgroup の主要メンバー:

efc228c190ff41e38eb5b7c97a6bc9ee.png

8aa23c4db4a95c5aa835f8adce0549ef.png

cgroup_subsys_state は、サブシステム操作に関連する、ファイル公開を含む cgroup 操作の主要なオブジェクトです。

その主要メンバー:

45f73833f52320e4beafaf8fe9be87ef.png

cgroup_subsys サブシステムには、主に各サブシステムの一般的な操作方法が含まれています。

主なメンバー:

ff2972002f3a63c203575ae86888bcd5.png

cgroup の各データ構造の関係図:

1674f152155992e33c18dadb829aa9e6.png

2. cgroup の初期化

cgroup の初期化は比較的単純で、主に cgroup_init_early と cgroup_init の 2 つのステップに分かれています。

2.1 cgroup_init_early

起動の非常に早い段階にあるため、主に次の作業を行います。

  1. init_task と同様に、システムは cgrp_dfl_root をデフォルト階層の cgroup_root として初期化します. 同様に、init フェーズで関連するタスクを初期化する init_css_set もあります。この段階で、デフォルトでは、init プロセスによってフォークされた子プロセスは init_css_set でハングします。

  2. init フェーズで他のモジュールが使用する必要がある関連サブシステムがある場合、サブシステムに関連する cgroup データ構造が構築され、関連する ss/css/cgroup/css_set 間の関係が確立され、最後に online_css が実行されます。実際に css を有効にするために呼び出されますが、まだファイル システムにレンダリングされず、init_css_set のサブシステムを初期化します。

2.2 cgroup_init

ここで初期化が行われ、vfs と sysfs が初期化されました。主な作業は次のとおりです。

  1. cgroup_setup_root を呼び出して cgrp_dfl_root を初期化し、cgroup がユーザーに公開する関連ファイルを作成します。サブシステムは実際には関与しません. 異なる階層の移動は、関連する css を有効にせず、ss 関連ファイルを公開しません. 次に、すべての既存の css_sets をルート cgroup に接続します。結局のところ、現時点ではすべてデフォルト階層の下にあります。

  2. cgroup_subsys.h で定義された各サブシステムを初期化します。2.1 を参照してください。

  3. init_css_set を cgrp_dfl_root にマウントして、cgrp_dfl_root を介して init_css_set でハングしたすべてのプロセスを取得できるようにします。

  4. 初期化されるサブシステムごとに、ユーザー空間に公開されるファイルが初期化され、作成されます。

  5. init_css_set のサブシステムが初期化および変更されているため、css_set_table へのハッシュ リンクをやり直します。

  6. cgroup および cgroup2 ファイルシステム タイプを登録します。

  7. /proc/cgroups ファイルを作成して、現在のシステム cgroup の概要を表示します。ubuntu を例にとると、起動後、179 個の cgroup が作成され、14 個のサブシステムが有効になっている階層が 1 つしかありません。

cf83bf2dcd6c5c4ac1c44a2a386d16ef.png

3.cgroup の作成と割り当てタスク

cgroup vfs は kernfs に基づいています. マウント プロセスは主に kernfs を使用してスーパー ブロックとルート ディレクトリを初期化します. さらに, cgroupv1 と cgroupv2 は区別されます. v2 はスレッド モードをサポートし、「デフォルトの統合階層」は 1 つだけです. 形式の違いにより、v1 では階層を検索または作成する必要がありますが、v2 では必要ありません. また、マウント時のパラメーター処理にいくつかの違いがありますが、ここでは詳しく説明しません.

3.1 cgroup の作成

マウントが成功したら、mkdir を使用して、マウントされたファイル ディレクトリに cgroup を作成できます。

主なプロセスは次のとおりです。

  1. cgroup の親ノードを見つけて、現在のレベルのいくつかの制限 (主に子孫の数と深さの制限) が要件を満たすことができるかどうかを確認します。

  2. cgroup_create を呼び出して特定の初期化を行い、そのライフ サイクルを管理する refcnt を初期化し、それが配置されている kernfs のディレクトリを作成し、親ノードの現在の凍結状態を継承して、凍結が自動的に有効になるようにし、それ自体をリンクします。便利な親ノードの子リストに cgroup のツリー構造を確立します。これは、後でその子孫をトラバースするために使用されます。デフォルトの階層では cgroup v2 が有効になっている可能性があるため、その subtree_control は初期化されません。他のレベルでは、現在の cgroup とその子孫の subtree_control と subtree_ss_mask が初期化されます. 2 つの具体的な違いについては、前のパラメーターの紹介を参照してください.

  3. css_populate_dir を呼び出して、現在のディレクトリに cgroup 共通ファイルを作成します。

  4. 有効なサブシステムごとに、css と現在のサブシステムの初期化ファイル (dfl_cftypes

および legacy_cftypes ですが、デフォルトの階層で選択されているかどうかに基づいて作成されます)、手動で mkdir cgroup を実行すると、自動的に作成されたファイルが多数表示されます。

3.2 タスクを cgroup に割り当てる

ここでスレッドモードについて簡単に説明します。作成できるのはドメイン cgroup のみですが、「threaded」と書くことができます

' 現在の cgroup の "cgroup.type" ファイルに移動して、cgroup をスレッド化します.cgroup がスレッド化された cgroup になると、ドメイン cgroup に変更できなくなります. スレッド化された後、その最も近いドメイン cgroup 親ノードがリソース統計を担当し、スレッド化された cgroup の dom_cgrp になります.この時点で現在の親ノード cgroup の「cgroup.type」ノードを cat すると、そのことがわかります。 type が domain から For domain threaded に変更され、親ノードのすべての子孫が削除された場合、それは domain に復元されます。

スレッドモードは、スレッドの粒度でグループ化することで制御をサポートできますが、スレッド化されたドメインにある必要があります。

cgroupv1 の「cgroup.procs」と「tasks」、cgroupv2 の「cgroup.procs」と「cgroup.threads」などのノードは、特定のタスク pid をノードに書き込むことで cgroup 制御を実現できます。

「cgroup.procs」を例にとると、具体的なプロセスは次のようになります。

  1. ユーザー入力から割り当て先の cgroup を取得します。v2モードで動作するため、プロセスとスレッドを区別して制御し、「cgroup.procs」ノードは、操作対象タスクのプロセスグループリーダーを見つけ、プロセスグループ内のすべてのスレッドを移動します。宛先 cgroup 。

  2. タスクが現在配置されている cgroup を取得します。これは、デフォルトの階層にあり、検索方法が cset_group_from_root を介して理解しやすいためです。

  3. cgroup_attach_task は、主要な移行アクションを実行します。ここで、cgroup_migrate_add_src は、スレッド グループ内のすべてのタスクが移行プロセスを記録するデータ構造 mgctx の preloaded_src_csets リンク リストに属する cset をリンクします。

  4. cgroup_migrate_prepare_dst は、最初に preloaded_src_csets リンク リストからソース cset を取り出し、対応する宛先 cgroup を重ね合わせて移行し、宛先 cset を取得してから、ソース cset と宛先 cset の間の対応関係を記録します。 cset と宛先 cset が矛盾しています。これは、サブシステムの状態が異なることを意味します。移行中に can_attach と attach コールバックを再実行し、それらをサブシステム リソース管理に再度組み込む必要があります。

  5. cgroup_migrate_add_task は、スレッド グループ内のタスクの cg_list を、それが属する cset の mg_tasks リンク リストに移行し、タスクにマークを付けて移行プロセスを開始します。次に、cset を mgctx の src_csets リンク リストにリンクします。

  6. cgroup_migrate_execute は、最初に can_attach を呼び出して変更されたサブシステムの状態を検出し、次に src_csets リンク リストから移行する cset を取得し、cset 内の mg_tasks リンク リスト内のタスクをトラバースし、対応する宛先 cset を取り出し、css_set_move_task を呼び出して移行します。 rcu_assign_pointer ( task->cgroups, to); 移行を完了します。

4. まとめ

この記事では、cgroup のデータ構造とその基本概念の説明に焦点を当てています. cgroup のデータ構造はもう少し複雑なので、焦点を絞って説明します. 読者は、コードと照らし合わせて読むとより快適に感じるでしょう. スペースは限られており、特定の cgroup サブシステムは関与していません. 興味のある学生はそれを補うことができます.

参考文献:

【1】https://lwn.net/Articles/199643/

【2】ドキュメンテーション/cgroup-v1/*

【3】ドキュメント/cgroup-v2.txt

【4】Kernel-5.10ソースコード

0f9e50614436859341859a40cc056938.gif

長押しでカーネル職人のWeChatをフォロー

Linux Kernel Black テクノロジー | 技術記事 | 注目のチュートリアル

おすすめ

転載: blog.csdn.net/feelabclihu/article/details/129095852