Linuxの基本IO

1. 文書に関するコンセンサス

1. 空のファイルでもディスク上のスペースを占有します。ファイル = ファイル データ + ファイル属性であるため、空のファイルにはファイル データはありませんが、ファイル属性は残っています。

2. ファイル = ファイル コンテンツ + ファイル属性であるため、ファイルに対する操作は、コンテンツ/属性に対する操作にすぎません。

3. ファイル操作関数は C プログラムで呼び出される. プログラムが実行されていない場合, これらのファイル操作関数は実行されず, プログラムが実行された場合にのみこれらのファイル操作関数が呼び出される. したがって, ファイル操作の本質開いているファイル間のプロセスと関係

4. ファイルの一意の識別子は「ファイル パス + ファイル名」で、パスが指定されていない場合は、デフォルトで現在のパスになります。

現在のパスは何ですか?

ここに画像の説明を挿入

プログラムが実行されると、それに関連する 2 つの属性が最も目立ちます。1 つは exe: 現在実行されているパスのプログラム、もう 1 つは cwd: 現在実行中のプログラムの作業ディレクトリです。

プロセスの作業ディレクトリは、プロセスの現在のパスです


chdir(要更改的路径名)Linux は、システムコールを呼び出してプロセスの現在のパスを変更することをサポートしています。

ここに画像の説明を挿入

ここに画像の説明を挿入


2. C言語のファイル操作の復習

1.ファイルを開く

ここに画像の説明を挿入

fopen はファイルを開きます。

1.「w」は書き込みモードで開かれ、存在しない場合は作成されます。デフォルトは上書きです(ファイルの元のコンテンツをクリアし、新しいコンテンツを書き込みます)。

2. "r" を読み取り用に開き、ファイルが存在しない場合はエラーが発生します

3.「r+」読み取りおよび書き込みモードが開き、エラーはありません

4. "w+" 読み取りおよび書き込みモードを開く、存在しない場合は作成する

5.「a」追加オープン、ファイルの元のコンテンツの後ろに新しいコンテンツを追加


2. ファイルにデータを書き込む

ここに画像の説明を挿入

形式に従って、%s%df が指すファイルに次のパラメーターを書き込みます。

3. ファイルにデータを追加する

ここに画像の説明を挿入

開封方法を変えるだけ


3. ファイルに関するシステムコール

各言語には独自のファイル操作機能がありますが、ファイルにアクセスするためにオペレーティング システムをバイパスすることはできません.ファイルのオープンとクローズ、読み取りと書き込みのいずれであっても、オペレーティング システムによって処理される必要があり、送信する必要があります。オペレーティング システムへの要求 システム コールを呼び出す必要があります。

つまり、ファイル操作機能はどの言語であっても、ファイルのシステムコールのリパッケージですが、それぞれのパッケージが異なります。システム コールを直接学習すると、学習コストを効果的に削減できます。これは、上位レベルの言語は変更されますが、基になるシステム コールは変更されず、上位レベルの言語は下位レベルのシステム コールに依存するためです。


1.open(ファイルオープン)

フラグは 6 つのマクロを使用してパラメーターを渡します。それらは O_RDONLY (読み取り専用)、O_WRONLY (書き込み専用)、O_CREATE (作成)、O_RDWR (読み取りと書き込み)、O_TRUNC (上書き書き込み)、O_APPEND (追加書き込み) です。

フラグ ビットは、各ビットに 01 の数字が 2 つしかないという事実を利用しており、異なるフラグは異なるビットの異なる位置の 1 で表されるため、フラグ内の 5 つのマクロのビット シーケンスは異なる必要があります。

呼び出しが成功すると、開いているファイルのファイル記述子が返され、失敗すると -1 が返されます。

open に対応するシステム コール インターフェイスは close です. ファイルをオープンした後、手動で close を呼び出してファイルを閉じるのが最善です.


ここに画像の説明を挿入

C言語のファイル操作機能を使用する場合、ファイルを書き込みで開くと、存在しない場合は自動的に作成されます; システムコールの呼び出しはflagsで渡されるパラメータです。O_WRONLY|O_CREATE

ここに画像の説明を挿入

ファイルが作成されるとき、デフォルトのパーミッションは 666 で、ディレクトリは 777 ですが、システムの umask コードの値によっても影響を受けます. 最終的なパーミッションは次のとおりです: デフォルトのパーミッション &~umsak

システムコールを使い始めた頃は、言語に比べて操作が単純でカジュアルではないことに気付きました。

open関数を使用するときに 3 番目のパラメーターも使用するため、ファイルを作成するための C 言語の既定のアクセス許可は正しいです。

ここに画像の説明を挿入

ファイルが既に存在する場合、ファイルを開くときに 3 番目の許可パラメーターを渡す必要はありません。

システム umask の影響を受けたくない場合は、システム コールを使用してumask変更できます。

ここに画像の説明を挿入


2.write (ファイルへの書き込み)

ここに画像の説明を挿入
ここに画像の説明を挿入

この出力は間違っているようですが、wb と cnt は正しく出力されているのに、最後に wbm1 があるのはなぜですか?

write は上書きであり、開くときに追加されない限り、ファイルを自動的にクリアしませんO_TRUNC

ここに画像の説明を挿入

直接上書きしたくない場合は、O_TRUNC次のように変更できますO_APPEND

ここに画像の説明を挿入


3.read(ファイルを読む)

ここに画像の説明を挿入
ここに画像の説明を挿入

fd で表されるファイルのデータを、buf で表されるバッファーに読み込みます。


4. ファイル記述子

システムには多数の開かれているファイルが必要であり、これらのファイルを管理する必要があります。したがって、オペレーティング システムは最初にファイルを記述し、次にそれらを整理して struct file{} 構造を形成します。この構造には、ほとんどの属性が含まれています。{}ファイル。

ファイルを管理するだけでなく、各ファイルのカーネルデータ構造体(構造体ファイル)も管理する必要があるため、ファイル記述テーブル(struct file_struct)があります。この時点で、そのような理解が少なくとも 1 つあります。
ここに画像の説明を挿入


1. プロセスが自身のファイルを見つける方法

プロセスは複数のファイルを開く場合があり、同時にメモリ内に多数のファイルが開かれている場合、プロセスはどのファイルがそれに属しているかをどのように認識しますか? 答えはファイル記述子テーブルを介してです.ファイル記述子テーブルは配列ポインタです. その各要素はポインタであり, ファイルのカーネルデータ構造を指しています. ファイルを指している各プロセスのPCBにポインタがあります.記述子テーブルです

構造を完成させます。

ここに画像の説明を挿入

ファイル記述子テーブル ポインタは、各プロセスの PCB に格納され、ファイル記述子テーブルは、このポインタを介して見つけることができます. プロセスのファイル記述子テーブル内の要素が指すファイルは、プロセスのファイルです

2. ファイルの fd が 3 から始まる理由

ここに画像の説明を挿入

上記の構造により、ファイルを開いたときに戻り値が 3 である理由が明確にわかります。これは、実際にはファイル記述子の添え字です。

システムはデフォルトで標準入力ストリーム, 標準出力ストリーム, 標準エラーを開きます. これらはそれぞれファイル記述子の 0, 1, 2 添字を占有するので, 新しく開かれたファイルは 3 添字しか占有できません.

ここに画像の説明を挿入

3. FILE と fd の関係

ファイルにアクセスする場合、オペレーティング システムをバイパスすることはできません。オペレーティング システムで特定のファイルを検索できるようにするには、そのファイルのファイル記述子が必要です。したがって、FILE 構造体にはファイル記述子 fd が必要です。

4. ファイル記述子の割り当て規則

ファイルを閉じるにはシステムコールcloseを使用するので、デフォルトで開く 3 つの標準ファイルを閉じることはできますか?

ここに画像の説明を挿入

添字 0 のファイルを閉じた後、新しく開いたファイルの添字は 0 です。これは、ファイル記述子の割り当て規則が、上から下にスキャンして最小で占有されていない添え字を見つけ、それを新しく開いたファイルに割り当てることであるためです。

ここに画像の説明を挿入

1 を閉じて myfile を実行すると何も出力されません。これは、デフォルトで開かれている 3 つのファイルでも閉じることができることを証明するのに十分ですclose

1 をオフにすると、新しく開いたファイルは添字 1 の付いたファイル、つまり標準出力がモニターから今開いたファイルに変わり、そのファイルに内容が入力されるはずです。表示するファイル:

ここに画像の説明を挿入

なぜ何もないのですか?

ここにはバッファの問題も含まれるため、データをディスプレイに更新する戦略とファイルに更新する戦略が異なります。

ここに画像の説明を挿入

モニターに出力されるはずだったものをファイルに出力しましたが、たまたま出力リダイレクトが発生しました


5.リダイレクト

ディスプレイに出力すべき内容を指定したファイルに出力するのがアウトプットリダイレクトなので、リダイレクトの本質は上位層で使用するfdはそのままで、カーネル内で構造体ファイル*に対応するfdのポイントを変更することです。 .

1. 標準入出力の変更方法

標準入出力の変更の本質は、ファイル記述子テーブルの添字 0 と 1 の内容を変更することです。

ファイルディスクリプタの割り当て規則では、まず標準入出力を閉じてから、新しいファイルを開く.このとき、新しいファイルは閉じたばかりの標準入出力ストリームの位置を占有する.これを変更する方法である. 、しかし、それはややイライラしすぎます。

dup2標準入出力を変更するためにオペレーティング システムによって提供されるシステム コール:

ここに画像の説明を挿入

Dup2 は oldfd の内容を newfd にコピーすることです

リダイレクション機能は、dup2 システムコールで簡単に実装できます。

2.出力と追加のリダイレクト

a. 出力リダイレクト

したがって、間の出力リダイレクトは次のように記述できます。

ここに画像の説明を挿入

結果は 3 になります。これは、dup2 がコピーであり、最後に newfd と oldfd の両方が oldfd の内容になるためです。つまり、新しく開かれたファイルは、ファイル記述子テーブルの 3 添え字のポインターによってまだ指されています。ですが、標準出力を表す添字 0 の struct file* も新しく開かれたファイルを指しています。

b. リダイレクトを追加

ここに画像の説明を挿入

アペンド リダイレクションも出力リダイレクションの一種で、最初にアペンドされたコンテンツは直接ディスプレイに出力され、ファイルにも配置されます。


3. 入力リダイレクト

ここに画像の説明を挿入

いわゆる入力リダイレクトとは、ファイル内のコンテンツを読み取り、それをディスプレイに出力することです。

4. 子プロセスのリダイレクトは親プロセスに影響しますか?

子プロセスのリダイレクトは親プロセスには影響しません. 子プロセスは作成時に親プロセスに基づいてモデル化されます. ファイル記述子テーブルを含む親プロセスのカーネルデータ構造の一部をコピーします. ファイル記述子子プロセスのテーブル構造体ファイル*のポイントが変更されました。親プロセスとは関係ありません。

プロセスは独立しており、すべてのファイル記述子テーブルもコピーを保持します。

6. Linux はどのようにしてすべてをファイルにするのか

すべてがファイルであることの難しさは、ハードウェアをファイルとして扱う方法です。

ここに画像の説明を挿入

オペレーティング システムは、最初に各ファイルを記述し、次に構造体ファイルのカーネル データ構造を編成します. ファイルのほとんどの属性は、このカーネル データ構造に格納されます。このカーネル データ構造には、多数の関数ポインタも含まれます. これらの関数ポインタは、特定のファイルを指します. 読み書きの具体的な方法。

各ファイルは異なりますが、ファイルの属性には大きな類似性があります.管理を容易にするために,ファイルをファイル属性に抽象化することができます.ファイルの説明はファイルの属性の説明です.管理の本質であるため.管理するデータです。

ハードウェアを同じ方法で管理し、ハードウェアの読み取りおよび書き込みメソッドを関数ポインターに抽象化し、さまざまな属性を構造体ファイルのカーネル データ構造に抽象化します。

構造体ファイルに立つと、ハードウェアも含めてすべて構造体ファイルで管理されているので、私にとってハードウェアはファイルと同じです。つまり、すべてがファイルであるという現象が発生します。

おすすめ

転載: blog.csdn.net/m0_62633482/article/details/130208792