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

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

推薦する

AWSサーバーリソースを無料で使用する方法を教えます

AWS - Amazon のクラウド コンピューティング サービス プラットフォーム以前、AWS の...

主軸上のFlex子要素の比率を制御する方法

背景フレックス レイアウトにより、配置とスペースの割り当てがより効果的に実現されます。最近、flex...

eject を使用せずに create-react-app の設定を変更する方法

1. イジェクトが推奨されないのはなぜですか? 1. eject を実行した後、どのような変化があり...

CentOSバージョンにDockerをインストールする際のエラーの解決方法

1. バージョン情報 # cat /etc/system-release CentOS Linux ...

HTML チュートリアル: HTML 水平線分

<br />このタグを使用すると、画面上に水平線を表示して、ページのさまざまな部分を区切...

CentOS7 で MySQL 5.7.24 をコンパイルしてインストールする詳細なチュートリアル

目次依存関係をインストールするブーストをインストールMySQLをコンパイルしてインストールする構成依...

Nginx+SpringBoot による負荷分散の実装例

負荷分散の概要Nginx の負荷分散実装を紹介する前に、負荷分散の分類について簡単に説明します。負荷...

CentOS で LibreOffice を使用してドキュメント形式を変換する方法

プロジェクト要件では、アップロードされたドキュメントの前処理が必要です。ユーザーが doc 形式でド...

Linux trコマンドの使用

1. はじめにtr はテキストの一部を変換または削除するために使用されます。 tr は transl...

CSSでスペースを処理する方法

1. 宇宙のルールHTML コード内の空白は通常、ブラウザによって無視されます。 <p>...

Vueエンジニアがカプセル化しなければならない埋め込み命令の知識のまとめ

目次序文指導の基本フック機能フック関数のパラメータ文章使い方とアイデア成し遂げる汎用性を高める要約す...

外部ネットワークアクセスを許可するためのMysql5.6の設定手順の詳細を共有する

最近、MySQL 5.6 を導入しましたが、デフォルトでは MySQL はローカル サービスのみを許...

Html+CSS フローティング広告ストリップの実装

1.html部分コードをコピーコードは次のとおりです。 <!DOCTYPE html> ...

uniappがインターフェースドメイン名を動的に取得する方法を分析する

背景インターフェイス ドメイン名はハードコードされておらず、動的に取得されます。具体的な実装は、静的...

4つのReactコンポーネントにおけるDOMスタイル設定の詳細な説明

1. インラインスタイル仮想DOMにインラインスタイルを追加するには、式を使用してスタイルオブジェク...