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 の例

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

推薦する

CSSアダプティブレイアウトは、サブ要素項目の全体的な中央揃えと内部項目の左揃えを実現します。

日常業務では、次のようなレイアウトに遭遇することがあります。親要素のフレーム (ブラウザのサイズに応...

MySQLでカーソルトリガーを使用する方法

カーソル選択クエリによって返される行のセットは、結果セットと呼ばれます。結果セット内の行は、入力した...

CSSレコードテキストアイコン配置のいくつかのソリューション

開発中に画像とテキストが 1 行に表示されることはよくあります。2 つのインライン要素を揃えるのは通...

Vueはdivホイールのズームインとズームアウトを実装します

Vue プロジェクトで div ホイールのズームインとズームアウト、ドラッグ効果、キャンバス効果に似...

MySQLテーブルの自動インクリメント列の初期値をリセットする方法

MySQLテーブルの自動インクリメント列の初期値をリセットする方法1. 問題の説明MySQL データ...

CSS transform-originプロパティを理解する

序文最近、花火アニメーションを作成しました。花火が散るアニメーションです。アニメーションの実装中、花...

MySQLでルートユーザーのパスワードを変更する方法

方法1: SET PASSWORDコマンドを使用する mysql> username@loca...

Dockerを使用してシンプルなJava開発およびコンパイル環境を構築する方法の詳細な説明

Java 言語には多くのバージョンがあります。一般的に使用されている Java 8 に加えて、一部の...

Vue+SpringBoot のフロントエンドとバックエンドの分離におけるクロスドメインの問題

フロントエンドとバックエンドを分離した開発では、フロントエンドがバックエンドの API を呼び出して...

ECMAScriptにおけるプリミティブ値と参照値の詳しい説明

目次序文動的プロパティとは何ですか?値のコピー値の種類を決定する要約する序文これは JavaScri...

Linux で crontab を使用してスケジュールされたタスクを追加する方法

序文Linux システムはシステム サービス crond によって制御されます。 Linux システ...

インタラクティブな視覚化 JS ライブラリ gojs の使い方の紹介とヒント

目次1. gojsの紹介2. Gojsのアプリケーションシナリオ3. gojs を選ぶ理由: 4. ...

nginx/apache 静的リソースのクロスドメインアクセスの問題を解決する詳細な説明

1. Apache 静的リソースのクロスドメイン アクセスApache設定ファイルhttpd.con...

MySQLの指定されたテーブルからデータをエクスポートする例の詳細な説明

指定されたテーブルからデータをエクスポートするMySQLの詳細な説明必要とする: 1. テーブルはす...

Eclipse は Tomcat を構成しますが、Tomcat には無効なポート解決策があります

目次1. EclipseがTomcatを構成する2. Tomcat の無効なポートの解決方法方法1:...