Linux仮想ファイルシステム:なぜ必要なのか、どのように機能するのか? パート2

みなさん、こんにちは。出版物の第2部「Linuxの仮想ファイルシステム:なぜ必要なのか、どのように機能するのか」を共有しています。第1部はここで読むことができます 。 この一連の出版物は、 Linux Administratorコースでの新しいスレッドの立ち上げに専念していることを思い出してください。

eBPFおよびbccツールでVFSを見る方法

カーネルがsysfsファイルでどのように動作するかを理解する最も簡単な方法は、実際にこれを調べることです。ARM64を観察する最も簡単な方法は、eBPFを使用することです。 eBPF(Berkeley Packet Filterの略)は、特権ユーザーがコマンドラインからqueryできるカーネルで実行されている仮想マシンで構成されています 。 カーネルソースは、カーネルに何ができるかを読者に伝えます。 ビジーなシステムでeBPFツールを実行すると、カーネルが実際に行うことを示します。



幸いなことに、一般的なLinuxディストリビューションからパッケージとして入手でき、 Bernard Greggによって詳細に文書化されているbccツールを使用すると、eBPFを使い始めるのは簡単です。 bccツールは、小さなCコードを挿入したPythonスクリプトです。つまり、両方の言語に精通している人なら誰でも簡単に変更できます。 bcc/toolsには80個のPythonスクリプトがありbcc/tools 。これは、開発者またはシステム管理者が問題の解決に適したものを選択できる可能性が高いことを意味します。

実行中のシステムでVFSが何をするかについての表面的なアイデアを得るには、 vfscountまたはvfsstat試してください。 これは、例えば、 vfs_open()と「彼の友人」への何十もの呼び出しが文字通り毎秒発生することを示します。



vfsstat.pyは、VFS関数呼び出しを単純にカウントするCコード挿入を含むPythonスクリプトです。


もっと簡単な例を挙げて、USBフラッシュドライブをコンピューターに挿入し、システムがそれを検出するとどうなるかを確認します。



eBPFを使用すると、USBフラッシュドライブが挿入されたときに/sys何が起こるかを確認できます。 簡単で複雑な例を次に示します。


上記の例では、 sysfs_create_files()コマンドがsysfs_create_files()されると、 bccツールtrace.pyがメッセージを表示します。 sysfs_create_files()は、挿入されているフラッシュドライブへの応答としてkworkerストリームを使用して起動されましたが、どのファイルが作成されましたか? 2番目の例は、eBPFの全機能を示しています。 ここで、 trace.pyは、カーネルバックトレース(-Kオプション)とsysfs_create_files()たファイルの名前を表示します。 単一ステートメントの挿入は、LLVM ジャストインタイムコンパイラーを実行するPythonスクリプトによって提供される簡単に認識可能なフォーマット文字列を含むCコードです。 彼は、カーネル内の仮想マシンでこの行をコンパイルして実行します。 sysfs_create_files ()関数の完全な署名を2番目のコマンドで再現して、フォーマット文字列がパラメーターの1つを参照できるようにする必要があります。 このCコードフラグメントのエラーは、認識可能なCコンパイラエラーになります。 たとえば、-lオプションを省略すると、「BPFテキストのコンパイルに失敗しました」と表示されます。CおよびPythonに精通している開発者は、 bccツールを簡単に展開および変更できます。

USBドライブが挿入されると、カーネルkworkerは、PID 7711がsysfs «events»ファイルを作成したkworkerストリームであることを示します。 したがって、 sysfs_remove_files()sysfs_remove_files()た呼び出しは、ドライブを削除するとeventsファイルが削除されたことを示します。これは、参照カウントの一般的な概念に沿っています。 同時に、USBドライブの挿入中にsysfs_create_link ()を表示すると、少なくとも48のシンボリックリンクが作成されていることがわかります。

では、イベントファイルの意味は何ですか? cscopeを使用して__device_add_disk()を検索すると、 disk_add_events()disk_add_events ()"media_change"または"eject_request"いずれかをイベントファイルに書き込むことができます。 ここで、カーネルブロックレイヤーは、ユーザースペースに「ディスク」の外観と抽出を通知します。 この研究方法は、ソースからのみすべてがどのように機能するかを理解しようとする場合と比較して、USBドライブを挿入する例によってどれほど有益であるかに注意してください。

読み取り専用ルートファイルシステムにより、組み込みデバイスが可能

もちろん、サーバーやコンピューターの電源を切ってプラグをコンセントから抜くことはありません。 しかし、なぜですか? 物理ストレージデバイスにマウントされたファイルシステムには保留中のレコードがあり、そのステータスを記録するデータ構造はストレージ内のレコードと同期されない可能性があるためです。 これが発生すると、システム所有者は、次のブートがfsck filesystem-recoveryユーティリティを実行するのを待たなければならず、最悪の場合、データを失います。

ただし、ルーター、サーモスタット、自動車だけでなく、多くのIoTデバイスがLinuxを実行していることは誰もが知っています。 これらのデバイスの多くには実質的にユーザーインターフェイスがなく、「クリーン」にそれらをオフにする方法はありません。 Linuxの制御デバイスの電源が絶えず上下するときに、放電したバッテリーで車を始動することを想像してください。 エンジンが最終的に動作を開始したときに、システムが長いfsckなしでブートするのはどうですか? そして答えは簡単です。 組み込みデバイスは、読み取り専用ルートファイルシステム( ro-rootfs (読み取り専用ルートファイルシステム)と略記)に依存しています。

ro-rootfsは、本物ほど明白ではない多くの利点があります。 1つの利点は、Linuxプロセスが書き込みできない場合、マルウェアが/usrまたは/lib書き込むことができないことです。 もう1つは、サポートスタッフがローカルシステムと名目上同一のローカルシステムを使用するため、リモートデバイスのフィールドサポートには、ほとんど変更できないファイルシステムが重要であることです。 おそらく最も重要な(しかし最も陰湿な)利点は、ro-rootfsにより、システム設計の段階であっても、変更するシステムオブジェクトを決定することを開発者に強制することです。 プログラミング言語のconst変数ではよくあることですが、ro-rootfsの操作は不快で痛みを伴う場合がありますが、それらの利点は簡単に追加のオーバーヘッドを回収します。

rootfs専用のrootfsを作成するにはrootfs組み込み開発者にとって余分な労力が必要です。そこでVFSが登場します。 Linuxでは、 /var内のファイルが書き込み可能であることが必要です。さらに、組み込みシステムを実行する多くの一般的なアプリケーションは、 $HOME構成dot-filesを作成しようとします。 ホームディレクトリの構成ファイルの解決策の1つは、通常、 rootfs予備的な生成とアセンブリです。 /var 、可能なアプローチの1つは、書き込み可能な別のセクションにマウントすることです。一方、 /マウント自体は読み取り専用です。 別の一般的な代替手段は、バインドまたはオーバーレイマウントの使用です。

リンク可能で重複するマウント、コンテナによる使用

man mountコマンドの実行は、 man mountバインドとオーバーラップについて学ぶ最良の方法です。これにより、開発者とシステム管理者は、ある方法でファイルシステムを作成し、それを別の方法でアプリケーションに提供できます。 組み込みシステムの場合、これは読み取り専用フラッシュドライブの/varにファイルを保存できることを意味しますが、起動時にtmpfsから/varへのパスをオーバーレイまたはリンクすると、アプリケーションはそこにメモを書き込むことができます(スクローリング)。 次回有効にすると、 /varへの変更は失われます。 オーバーレイマウントは、 tmpfsとその下にあるファイルシステムの結合を作成し、 ro-tootf既存のファイルを修正できるとされていますが、リンクされたマウントは、 ro-rootfsパスで書き込み可能な新しい空のtmpfsフォルダーを表示できます。 overlayfsproper種類のファイルシステムですが、バインディングマウントはVFS名前空間に実装されます

重ねてリンクされたマウントの説明に基づいて、 Linuxコンテナがそれらを積極的に使用していることに誰も驚かない。 systemd-nspawnを使用て、 bcc mountsnoopツールを使用してコンテナを起動するとどうなるかを見てみましょう。



system-nspawn呼び出すと、 mountsnoop.py中にmountsnoop.py開始されます。

何が起こったのか見てみましょう:



コンテナーが「ロード」されている間にmountsnoopを実行すると、コンテナーランタイムが接続されているマウントに大きく依存していることがmountsnoopます(長い出力の先頭のみが表示されます)。

ここで、 systemd-nspawnsysfsホストのprocfssysfs選択されたファイルを、そのrootfsへのパスとしてコンテナに提供しrootfs 。 バインディングマウントを設定するMS_BINDフラグに加えて、マウントされたシステムの他のいくつかのフラグは、ホスト名前空間とコンテナの変更の関係を決定します。 たとえば、バインディングマウントは、 /procおよび/sys変更をコンテナにスキップするか、呼び出しに応じてそれらを非表示にすることができます。

おわりに

Linuxの内部構造を理解することは、カーネル自体に大量のコードが含まれ、 glibcようなCライブラリのLinuxユーザー空間アプリケーションとシステムコールインターフェイスを残すため、不可能なタスクのように思えるかもしれません。 進歩させる1つの方法は、ユーザー空間に面するシステムコールとヘッダー、およびカーネルのメイン内部インターフェイス( file_operationsテーブルなど)を理解することに重点を置いて、1つのカーネルサブシステムのソースコードを読み取ることです。 ファイル操作は「すべてがファイルである」という原則を提供するため、それらの管理は特に便利です。 最上位ディレクトリfs/のCソースファイルは、仮想ファイルシステムの実装を表します。仮想ファイルシステムは、一般的なファイルシステムとストレージデバイスの広く比較的単純な互換性を提供するシェルレイヤーです。 Linuxネームスペースを介したバインディングおよびオーバーレイによるマウントは、読み取り専用のコンテナーとルートファイルシステムを作成できるVFSの魔法です。 ソースコード学習、eBPFコアツールおよびそのbccインターフェイスとの組み合わせ
カーネルの研究をこれまで以上に簡単にします。

友人、この記事を書くのはあなたにとって役に立ちましたか? 何かコメントやコメントがありますか? また、Linux管理者コースに興味のある方は、4月18日に開催される一般公開日にご招待します。

最初の部分。

Source: https://habr.com/ru/post/J447748/


All Articles