Linux ファイル記述子、ファイルポインタ、および inode の詳細

Linux ファイル記述子、ファイルポインタ、および inode の詳細

Linux - ファイル記述子、ファイルポインタ、インデックスノード

1. Linux - ファイル記述子

1. ファイル記述子 Fd

プロセスがファイルを開いたり、新しいファイルを作成したりすると、カーネルは開かれたファイルを指すファイル記述子 (負でない整数) を返します。I/O 操作を実行するすべてのシステム コール (読み取り、書き込み) は、ファイル記述子を通過します。

ファイル記述子は、プロセス ファイル記述テーブルのインデックスとして理解できます。また、ファイル記述テーブルが配列と見なされる場合は、ファイル記述子を配列の添え字として見なすことができます。 I/O 操作が必要な場合、fd がパラメータとして渡されます。まず、プロセス ファイル記述子テーブルから fd に対応するエントリが検索され、対応するオープン ファイルのハンドルが取り出されます。ファイル ハンドルが指している値に従って、ファイルが指している inode がシステム fd テーブル内で検索され、ファイルの実際の位置が特定されて I/O 操作が実行されます。

特徴:

  • 各ファイル記述子は開いているファイルに対応します。
  • 異なるファイル記述子が同じファイルを参照する場合があります。
  • 同じファイルを異なるプロセスで開くことも、同じプロセスで複数回開くこともできます。

関連する 3 つの表は次のとおりです。

プロセスレベルのファイル記述子テーブル

構造体task_struct {
  //...
  
    struct files_struct *files //プロセスレベルのファイル記述子テーブル//...
    
};

2. システムレベルのファイル記述子テーブル

カーネルは、システム内のすべてのオープン ファイルの打開文件表を管理します。テーブル内の各項目は、打開文件句柄と呼ばれます。オープン ファイル ハンドルは、オープン ファイルのすべての情報を記述します。

  • 現在のファイル オフセット (read() および write() の呼び出し時に更新されるか、lseek() で直接変更されます)
  • ファイルを開くときに使用されるステータス フラグ (つまり、open() の flags パラメータ)
  • ファイル アクセス モード (読み取り専用モード、書き込み専用モード、open() 呼び出し時に設定される読み取り/書き込みモードなど)
  • 信号ドライバ関連の設定
  • ファイルのi-nodeオブジェクトへの参照
  • ファイルの種類(通常のファイル、ソケット、FIFO など)とアクセス権限
  • ファイルが保持するロックのリストへのポインタ
  • ファイルのさまざまなプロパティ(ファイルサイズ、さまざまな種類の操作に関連付けられたタイムスタンプなど)

3. ファイルシステムのinodeテーブル

各ファイル システムは、そこに保存されているすべてのファイルの inode テーブルを保持します。

ファイル記述子テーブル、オープン ファイル テーブル、および inode テーブルの関係:

プロセス A のファイル記述子 1 と 20 は、open() やその他の関数を複数回呼び出すことによって同じファイルが開かれるため、同じ開いているファイル ハンドルを指します。

プロセス A のファイル記述子 2 とプロセス B のファイル記述子 2 が同じオープン ファイル ハンドルを指している理由は、fork() の呼び出しによるものと考えられます。子プロセスは親プロセスのオープン ファイル記述子テーブルを継承します。つまり、子プロセスは親プロセスのオープン ファイルを継承します。 ; または、プロセスが Unix ドメイン ソケットを介して開いているファイル記述子を別のプロセスに渡すか、または異なるプロセスが独立して open 関数を呼び出して同じファイルを開き、ファイル記述子が他のプロセスによって開かれたファイル記述子と同じに割り当てられます。

プロセス A の記述子 0 とプロセス B の記述子 3 は、異なるオープン ファイル ハンドルを指していますが、これらのハンドルはすべて i-node テーブル内の同じエントリ、つまり同じファイルを指しています。これは、各プロセスが同じファイルに対して open() 呼び出しを開始したために発生します。同じプロセスが同じファイルを 2 回開いた場合にも同様の状況が発生します。

2. ファイルポインタ *FILE

C 言語では、I/O ハンドルとしてファイル記述子の代わりにファイル ポインタを使用します。「ファイル ポインタ」は、プロセス ユーザー領域内の FILE 構造と呼ばれるデータ構造を指します。ファイルポインタを介してファイルを操作する場合には、C言語のstdio.hで提供されているファイルAPI(fopen()、fread()など)を呼び出す必要があります。

ファイル記述子は POSIX システム コールで直接表示され、ファイル ポインターはそれらの上にある C 言語ラッパーです。

int open(const char *path, int access, int mode)  
FILE *fopen(char *ファイル名, char *モード)

ファイル ポインターへのファイル パス: filepath --fopen()-->FILE*;
ファイル記述子へのファイル パス: filepath--open()--fd;
ファイル記述子からファイル ポインターへ: fd--fdopen()-->FILE*;
ファイル記述子へのファイルポインター: FILE*--fileno()--->fd;

3. インデックスノードの Inode

インデックス ノードは、Unix 系システムのファイル システム内のオブジェクトのメタデータを格納するデータ構造です。

inode には主に以下のデータが格納されます。

  • iノード番号
  • ファイルサイズ
  • 占有ブロック数とブロックサイズ
  • ファイルの種類(通常のファイル、ディレクトリ、パイプなど)
  • ファイルが保存されているデバイス番号
  • リンク数
  • 読み取り、書き込み、実行権限
  • 所有者のユーザーIDとグループID
  • ファイルが最後にアクセスされ、データが最後に変更された時刻
  • inodeが最後に変更された時刻

statコマンドを使用してメタデータを表示し、df -i コマンドを使用して、inode の合計数と各ハードディスク パーティションに使用されている inode の数を表示できます。ファイル名以外のすべての情報は、inode に保存されます。

i ノードもハードディスクの容量を消費するため、ハードディスクをフォーマットすると、オペレーティング システムによってハードディスクが自動的に 2 つの領域に分割されます。 1 つはファイル データを格納するデータ領域であり、もう 1 つは inode に含まれる情報を格納する inode 領域 (inode テーブル) です。

各 inode ノードのサイズは通常128字節または256字節です。 inode ノードの合計数はフォーマット時に指定され、通常は 1KB または 2KB ごとに 1 つの inode が設定されます。 1GB のハードディスクで、各 inode ノードのサイズが 128 バイトで、1KB ごとに 1 つの inode が設定されると仮定すると、inode テーブルのサイズは 128MB に達し、ハードディスク全体の 12.8% を占めることになります。

各ファイルには inode があるため、inode が使い果たされていてもハードディスクがいっぱいになっていない可能性があります。 Linux システムでは、ファイル名ではなく i ノードを使用してファイルを識別します。

表面的には、ユーザーはファイル名でファイルを開きます。実際、システム内のこのプロセスは 3 つのステップに分かれています。まず、システムはファイル名に対応する inode 番号を見つけます。次に、inode 番号を通じて inode 情報を取得します。最後に、inode 情報に基づいて、ファイル データが配置されているブロックを見つけ、データを読み取ります。

ディレクトリ ファイルは、一連のディレクトリ エントリで構成されるデータ構造であり、各ディレクトリ エントリにはファイル名と inode 番号の 2 つの部分が含まれます。

1. Inodeの特別な役割

  • 場合によっては、ファイル名に通常は削除できない特殊文字が含まれていることがあります。このとき、inode ノードを直接削除すると、ファイルを削除できます。
  • ファイルを移動または名前変更すると、ファイル名のみが変更され、inode 番号には影響しません。
  • ファイルを開いた後、システムはそのファイルを inode 番号で識別し、ファイル名は考慮しなくなります。したがって、一般的に、システムは inode 番号からファイル名を認識することはできません。

ポイント 3 では、ソフトウェアの更新が簡単になり、ソフトウェアをシャットダウンしたり再起動したりすることなく更新できます。システムは実行中のファイルをファイル名ではなく、inode 番号で識別するためです。更新すると、ファイルの新しいバージョンによって同じファイル名を持つ新しい inode が生成されますが、実行中のファイルには影響しません。次回ソフトウェアを実行すると、ファイル名は自動的に新しいバージョンのファイルを指し、古いバージョンのファイルの inode はリサイクルされます。

4. 拡大

1. ディスク構造

ファイルはハードディスクに保存され、ハードディスクの最小の保存単位は「セクター」と呼ばれます。各セクターには 512 バイト (0.5 KB に相当) が格納されます。

オペレーティング システムがハード ディスクを読み取るとき、セクターごとに読み取るのではなく (これは非常に非効率的です)、一度に複数のセクターを連続して読み取ります。つまり、一度に 1 つの「ブロック」を読み取ります。複数のセクターで構成されるこの「ブロック」は、ファイル アクセスの最小単位です。最も一般的な「ブロック」サイズは 4KB です。つまり、8 つの連続したセクターがブロックを形成します。

上記から、(柱面號,盤面號,扇區號)を使用して、任意の「ディスクブロック」を見つけることができます。外部メモリ内のファイルデータが保存されているブロック番号(論理アドレス)についてよく言及します。このブロック番号は、(シリンダ番号、ディスク面番号、セクター番号)のアドレス形式に変換できます。

このアドレスから「ブロック」は次のように読み取ることができます。

①「シリンダ番号」に従って磁気アームを動かし、磁気ヘッドが指定のシリンダ(トラックとも言う)を指すようにする

②指定されたディスク面に対応するヘッドを作動させる。

③ ディスクが回転すると、指定されたセクタがヘッドの下を通過し、指定されたセクタの読み取り/書き込みが完了します。

Linux ファイル ディスクリプタ、ファイル ポインタ、インデックス ノードの詳細に関するこの記事はこれで終わりです。Linux ファイル ディスクリプタ、ファイル ポインタ、インデックス ノードに関するより詳しい情報については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Linux インデックスノード inode の詳細な説明
  • Linux デバイスに空き容量がありません inode の満杯により 500 エラーが発生します
  • Linux ネットワーク設定の詳細
  • MyCat を使用して Linux で MySQL マスター/スレーブの読み取り/書き込み分離を実装する方法
  • Unix/Linuxフォークの隠れたオーバーヘッド
  • Linux での UDP について学ぶ
  • Linux スワップ パーティション (詳細説明)
  • Linux での C++ ネットワーク プログラミング、epoll テクノロジ、Windows での IOCP モデル
  • Linux サーバーは最大いくつのポートを開くことができますか?

<<:  div を下から上にスライドさせる CSS3 の例

>>:  フォーム内のどの隠し属性をフォームとともに送信できるか

推薦する

SpringBootはActiviti7実装コードを統合する

Activiti7 の正式リリース以降、SpringBoot2.x との統合開発を全面的にサポートし...

JavaScript 関数はランダムな色の検証コードをカプセル化します (完全なコード)

数字、文字、またはランダムな色の数字と文字の混合で構成される n 桁の確認コード。以下に完全なコード...

CocosCreatorでシューティングゲームを作る詳しい解説

目次シーン設定ゲームリソース砲塔の回転動的に生成された弾丸衝突計算効果を高めるターゲットの動き弾薬庫...

Linuxでスワップパーティションファイルを作成する方法

スワップの紹介Linux のスワップ (スワップ パーティション) は、Windows の仮想メモリ...

Vue+webrtc (Tencent Cloud) ライブブロードキャスト機能の実装実践

目次1. 生放送効果2. ライブストリーミングを開始する手順2.1 Tencent Web(高速ライ...

Portainer を使用して Docker のビジュアル インターフェースを構築する方法

ポーテナーの紹介Portainer は、ステータス表示パネル、アプリケーション テンプレートの迅速な...

Axios の二次カプセル化の例 プロジェクトのデモ

1. なぜパッケージングを行うのですか?全体的なコード呼び出し、リクエストの公開処理、パーソナライズ...

CSS3 のディスプレイのグリッドレイアウトとフレックスレイアウトの詳細な説明

Gird レイアウトは Flex レイアウトといくつかの類似点があり、どちらもコンテナーの内部項目を...

DockerでKafkaをデプロイする方法

目次1. Dockerをビルドする2. コンテナに入る3. 設定ファイルを変更する4. Kafkaを...

CSS calc() の数式に関する詳細な理解

数式 calc() は CSS の関数であり、主に数学演算に使用されます。 calc() を使用する...

Vue3カプセル化メッセージメッセージプロンプトインスタンス関数の詳細な説明

目次Vue3 カプセル化メッセージプロンプトインスタンス関数スタイルレイアウトカプセル化メッセージ....

Mysqlマスタースレーブ同期の実装原理

1. MySQL マスター/スレーブ同期とは何ですか?マスター データベースのデータが変更されると、...

DockerにTomcatコンテナを追加したときにホームページにアクセスできない問題の解決方法

質問docker run コマンドを使用して、tomcat コンテナが正常に追加されました。ポートも...

Ubuntuが仮想マシンでインターネットに接続できない問題の解決策

インターネットに接続できない仮想マシンをセットアップするのは非常に面倒です。ここでは、Ubuntu ...

Vue2.xは、ユーザーのログインと終了を実装するためにルーティングナビゲーションガードを設定します。

目次序文1. ルーティングナビゲーションガードを設定する1. グローバルナビゲーションガード2. ロ...