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

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

推薦する

フロントエンドアプリケーションのjenkins+gitlab+nginxデプロイメント

目次関連する依存関係のインストールドッカーDockerでJenkinsをインストールするDocker...

フレックスインサイドボタンの垂直方向の中央揃えが中央揃えにならない問題の解決方法

問題の説明ボタンのスタイルはアイコン + テキストです。フレックス レイアウトを使用して垂直方向に中...

DBeaver を MySQL バージョン 8 以降に接続し、起こりうる問題を解決する方法の詳細な説明

データベース MySQL バージョン 8.0.18 DBeaver.exeをダウンロードするダウンロ...

CSSはcalc()を使用して現在の表示画面の高さを取得します

まず、CSS3 の相対的な長さの単位を見てみましょう (詳細なチュートリアルを参照してください)。相...

MySQL でデータ テーブルを作成し、主キーと外部キーの関係を確立する方法の詳細な説明

序文MySQL テーブルの主キーと外部キーを作成するときは、次の点に注意する必要があります。主キーと...

CSS 3.0 テキストホバージャンプ特殊効果コード

これは、CSS 3.0 で実装されたテキストのホバーとジャンプ効果です。効果は次のとおりです。 以下...

Docker で既存のイメージに基づいて新しいイメージを構築する方法

既存のイメージから新しいイメージを構築することは、Dockerfile ドキュメントを通じて行われま...

VueプロジェクトにPWAを導入する手順

目次1. 依存関係をインストールする2. vue.config.js ファイルで pwa を設定しま...

Vue バックエンド管理システムのページング機能の実装例

この記事では、主に Vue バックグラウンド管理システムのページング機能の実装を紹介し、次のように共...

sshとは何ですか?使い方は?どのような誤解があるのでしょうか?

目次序文SSHとは何かssh は何に使用されますか? sshの使い方ssh 再修正要約する序文ssh...

MySQL 5.7.11 zip インストールと設定方法のグラフィックチュートリアル

1. MySQL 5.7.11 zipインストールパッケージをダウンロードするこのマシンはwin7 ...

Dockerでコンテナを作成するときにコンテナIPを指定する実装例

Docker はコンテナを作成するときに、デフォルトでブリッジ ネットワークを使用し、IP アドレス...

MySQL ALTERコマンドの知識ポイントのまとめ

テーブル名を変更したり、テーブル フィールドを変更したりする必要がある場合は、 MySQL ALTE...

ウェブデザイナーが注意すべき 43 のウェブデザインの間違い

これはウェブサイトのユーザビリティに関する記事です。著者は自身の経験に基づいて、ウェブサイトのデザイ...