open(at) システムコールはファイルをディスクに書き込む方法を教えてください。

open(at) システムコールはファイルをディスクに書き込む方法を教えてください。

私は、システムコール、VFS、デバイスドライバの処理、最終的にエンドデバイスに何かを実行させることの間のやり取りについて、できるだけ学びたいと考えています。私は非常に簡単な例(ファイルの生成)を見て、基本的なプロセスをできるだけ詳しく理解しようと思いました。

いくつかのCコードを生成して書き込むために(存在しない)ファイルを開き(最適化なしで)コンパイルし、実行中にstraceを使用して確認しました。具体的にはopenat、システムコールに焦点を当て、この呼び出しが最終的にファイルオブジェクト/ファイル記述を生成するだけでなく、実際にディスク(FYI、EXT4ファイルシステム、SATA HDD)に書き込むことができる理由と方法について説明したいと思います。

一般的に言えば、いくつかの検査とサポートを除いて、このプロセスの私の理解は次のとおりです(私の理解が偏っている場合は訂正してください!)。

  • メモリにマッピングされたELF
  • libc はメモリにマップされます。
  • fopen~と呼ばれる
  • libcオープン
  • openatO_CREATフラグを含むシステムコールが呼び出されます。
  • システムコール番号はRAXレジスタに格納されます。
  • システムコールパラメータ(ファイルパスなど)は、RDIレジスタ(および適切な場合はRSI、RDXなど)に格納されます。
  • Syscall コマンドが発行され、CPU がリング 0 に切り替わります。
  • MSR_LSTAR レジスタが指す System_call コードを呼び出します。
  • カーネルスタックにプッシュされたレジスタ
  • オフセットで呼び出されたRAXの関数ポインタsys_call_table
  • asmlinkageopenat実際のシステムコールコードを呼び出すラッパー

当時は十分に理解できませんでしたが、結局は次の事実を知りました。

  1. open 呼び出しは、プロセスに一意であり、カーネルのファイル記述子テーブルでグローバルに保持されるファイル記述子を返します。
  2. FD はファイル記述ファイルオブジェクトにマップされます。
  3. ファイルオブジェクトは、inode構造、inode_Operations、file_Operationsなどの構造で埋められます。
  4. ファイル作業テーブルは、その呼び出しを処理するために一般的なシステム呼び出しを適切なデバイスドライバにマッピングする必要がありますwrite。 SCSIドライバ)
  5. このマッピングは、ファイル/デバイスの州/マイナー番号に基づいています。
  6. このプロセス中に、コマンドがハードドライブのデバイスドライバに転送されるようにするコードが呼び出されます。このコマンドはディスクコントローラに転送され、ファイルがハードドライブに書き込まれるようにします。またはDMAまたは他のI未定義I / Oメソッド
  7. 最後に、ディスクコントローラは完了を知らせるメッセージをカーネルに送り返し、カーネルはスペースを使用するための制御を返します。

私はカーネルソースのトレースがうまくいかなかったので、いくつか試してみましたが、欠けている部分がたくさんあるようです。私の質問は次のとおりです。

FDを返して破壊するいくつかの関数をカーネルソースで見つけましたが、コードが実際にファイルのファイルオブジェクト/ファイルの説明を満たす場所を見つけることができませんでした。

A)openまたはopenatシステムコールで新しいファイルが作成されると、ファイル構造はどのように入力されますか?データはどこから来ますか?具体的には、このファイルのfile_Operations、inode_Operationsなどはどのように入力されますか?たとえば、この構造を埋めると、カーネルは、この特定のファイルのファイル操作がSCSIドライバの操作と同じでなければならないことをどうやって知ることができますか?

B)プロセス(特に参照元)からデバイスドライバへの移行がどこにありますか?たとえば、ioctl同様の関数が呼び出されると、そのデバイスから呼び出された命令へのいくつかの参照とデータのいくつかのメモリアドレスが渡されると予想されますが、どこでこれが起こるのかを見つけることができません。

カーネルのソースコードを見ると、実際に見つけることができるのは新しいFDを割り当てるコードだけですが、ファイル構造を埋めるコードもなく、デバイスドライバに制御を転送するために適切なファイル操作を呼び出すコードもありません。

申し訳ありません。説明が長すぎますが、できるだけ多くのことを学びたい、Cの基本的な理解はありますが、他の人のコードを理解するのは本当に難しいです。

私は比喩的なレンガの壁にぶつかるように見えるので、私よりも知識が豊富な誰かがこれらのことを明確にするのを助けることができることを願っています。どんなアドバイスも本当にありがとうございます。

編集する: 次のことで、私が求めている技術的な詳細を明確にできることを願っています。

  • openまたはファイルパスとフラグを使用するシステムコールopenat(後者はディレクトリを指すFDも渡します)
  • このO_CREATフラグも渡されると、ファイルが存在しない場合は「生成」されます。
  • ファイルパスに基づいて、カーネルはファイルのデバイスタイプを識別できます。
  • デバイスタイプは通常、州番号/マイナー番号で識別されます。既存のファイルの場合、これらのデバイスタイプはファイルシステムのファイルinode構造(メンバーi_rdev)とファイルステータス構造(st_devデバイスタイプのメンバー)に保存されます。ファイルがあり、st_rdevファイル自体のデバイスタイプもあります。

実際、私の質問は次のとおりです。

  1. オープンシステムコールのいずれかを使用してファイルを生成した場合は、対応する inode と状態構造も作成して入力する必要があります。オープンシステムコールがこれを行う方法(この時点で進む必要があるのはファイルパスとフラグのみです)親ディレクトリのinodeまたはstat構造を見て、そこから関連構造メンバーをコピーしますか?

  2. どの点(つまりソースコードのどこ)でこれが起こりますか?

  3. 私が理解したのは、これらのオープンシステムコールが呼び出されたときにVFSが呼び出すデバイスドライバコードを知ることができるようにデバイスタイプを知る必要があります。新しいファイルが作成され、ファイルオブジェクト構造にデバイスタイプが設定されていない場合はどうなりますか?コード名とは何ですか?

  4. 順序は次のとおりです。

ユーザープロセスは新しいファイルを開くことを試みます。 ->open('/tmp/foo', O_CREAT)開きます。 -> "/tmp"構造を探し、対応するデバイスタイプを取得します。 -> 未使用のFDを取得します。 ->デバイスタイプを親エントリに設定することを含む、inode / stat構造を埋めます。デバイスタイプ - >デバイスタイプに応じてデバイスドライバコードへのファイル操作/inodeタスクのマッピング - >システムコールのopenためのデバイスドライバコードの呼び出し - >新しいファイルをディスクに書き込むための適切な指示をディスクコントローラに送信する - >コントラスト、スタンバイチェック - > FDをユーザー呼び出し手順に戻しますか?

ベストアンサー1

基本的にあなたは正しいですが、関係のない詳細が混在しています(主にCの仕組みのため)。

プログラムコールopen(2)(システムコール、つまりカーネルコール) これが行われる正確な方法は、アーキテクチャやその他の詳細によって異なります。

システムコールのカーネルの内部部分は、パラメータ(ここでは要求されたパス)やプロセス資格情報などの他の情報とともに呼び出されます(詳細はアーキテクチャ、正確なOSバージョンによって異なります...)。

与えられたパスでは、カーネルは与えられたパスにどのファイルシステムがマウントされているかを知っています。ルートから下に一般的な巡回を実行することで、呼び出し元が必要な権限を持っているか、ディレクトリが存在するかなどを確認できます。これには、ディスクからデータを読み込むことが含まれます。すべてが順調に進むと、ファイルシステムのデータ構造への関連の変更を開始し、新しく開かれたファイルを記録し、スペースを予約し、ディレクトリに登録するなどのタスクを実行します。

ファイルシステムのデータ構造(現在のメモリにあります)への変更をディスクに書き込む必要があるかもしれません(またはネットワークを介して転送する...)。カーネルは、完了のために書き込み操作をキューに追加し(すぐに完了する必要がない場合)、それをユーザーに返します。

おすすめ記事