これはかなり低レベルの質問であり、質問するのに最適な場所ではない可能性があることを理解しています。しかし、それは他のどのSEサイトよりも適切であると思われたので、ここにいきます。
Linuxファイルシステムでは、一部のファイルが実際にexistのようになっていることを知っています。たとえば、/usr/bin/bash
は存在するファイルです。ただし、(私が理解している限り)実際には存在しないものもあり、より多くのvirtualファイルです(例:/dev/sda
、/proc/cpuinfo
など)。質問は次のとおりです(2つありますが、関連性が高すぎて個別の質問にすることはできません)。
/dev/random
からの読み取りはランダムなデータを返し、/dev/null
からの読み取りはEOF
を返します。この仮想ファイルからどのデータを読み取るか(したがって、データが仮想ファイルに書き込まれた場合、またはどのような場合にどうするか)はどのように計算されますか?各ファイルに適切な個別の読み取り/書き込みコマンドへのポインターを持つある種のマップがあります。それとも仮想ディレクトリ自体ですか?したがって、/dev/null
のエントリは単にEOF
を返す可能性があります。つまり、ここには基本的に2つの異なるタイプがあります。
/proc
と/sys
は、sshfs
やifuse
などのFuseカスタムファイルシステムと同様に、ここでの例です。これらは実際には、ある意味「カスタム」であるセマンティクスを持つファイルシステムを参照しているだけなので、はるかに多様性があります。したがって、/proc
の下のファイルから読み取る場合、通常のファイルシステムのように、以前に他の何かが書き込んで格納した特定のデータに実際にはアクセスしていません。あなたは本質的にカーネルの呼び出しを行っており、オンザフライで生成されるいくつかの情報を要求しています。そして、このコードは、どこかにread
セマンティクスを実装している単なる関数なので、好きなように実行できます。したがって、/proc
下のファイルの奇妙な動作は、たとえば、実際にはシンボリックリンクではないふりをするようなものです。重要なのは、/dev
が実際には通常、最初の種類の1つであることです。最近のディストリビューションでは/dev
をtmpfsのようにするのが普通ですが、古いシステムでは、特別な属性を持たない、ディスク上のプレーンディレクトリにするのが普通でした。重要なのは、/dev
の下のファイルがデバイスノードであることです。これは、FIFOまたはUnixソケットに似たタイプの特殊ファイルです。デバイスノードにはメジャー番号とマイナー番号があり、それらの読み取りまたは書き込みは、FIFOがカーネルを呼び出して出力をこのドライバは、必要なことは何でも実行できますが、通常、ハードディスクにアクセスしたり、スピーカーでサウンドを再生したりするなど、ハードウェアに何らかの影響を与えます。
元の質問に答えるには:
「ファイルが存在する」かどうかに関連する2つの質問があります。これらは、デバイスノードファイルが文字通り存在するかどうか、それをサポートするカーネルコードが意味があるかどうかです。前者は、通常のファイルシステムの場合と同様に解決されます。最新のシステムはudev
またはそのようなものを使用してハードウェアイベントを監視し、それに応じて/dev
の下のデバイスノードを自動的に作成および破棄します。しかし、古いシステム、または軽量のカスタムビルドでは、すべてのデバイスノードを文字通りディスク上に作成し、事前に作成できます。一方、これらのファイルを読み取るときは、メジャーデバイス番号とマイナーデバイス番号によって決定されるカーネルコードを呼び出します。これらが妥当でない場合(たとえば、存在しないブロックデバイスを読み取ろうとしている場合)は、何らかのI/Oエラーが発生します。
どのカーネルファイルがどのデバイスファイルを呼び出すかを決定する方法はさまざまです。 /proc
などの仮想ファイルシステムの場合、独自のread
関数とwrite
関数を実装します。カーネルは、それがどのマウントポイントにあるかに応じて、そのコードを呼び出すだけで、ファイルシステムの実装が残りを処理します。デバイスファイルの場合、メジャーデバイス番号とマイナーデバイス番号に基づいてディスパッチされます。
これが、ほぼ最新のArch Linuxサーバー上の/dev/sda1
のファイルリストです。
% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov 9 13:26 /dev/sda1
したがって、sda
の/dev/
のディレクトリエントリには、iノード番号1294があります。これは、ディスク上の実際のファイルです。
ファイルサイズが通常表示される場所を確認します。代わりに「8、1」が表示されます。これはメジャーおよびマイナーデバイス番号です。また、ファイル権限の「b」にも注意してください。
ファイル/usr/include/ext2fs/ext2_fs.h
には、この(フラグメント)C構造体が含まれています。
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
この構造体は、ファイルのiノードのディスク上の構造を示しています。その構造体には、興味深いものがたくさんあります。長い目で見てください。
i_mode
のstruct ext2_inode
要素は16ビットであり、ユーザー/グループ/その他、読み取り/書き込み/実行のアクセス許可に9つ、setuid、setgid、スティッキに3つだけを使用します。 「プレーンファイル」、「リンク」、「ディレクトリ」、「名前付きパイプ」、「Unixファミリソケット」、「ブロックデバイス」などのタイプを区別するための4ビットがあります。
Linuxカーネルは、通常のディレクトリルックアップアルゴリズムに従い、i_mode
要素の権限とフラグに基づいて決定を行うことができます。 「b」の場合、ブロックデバイスファイルは、メジャーおよびマイナーデバイス番号を見つけることができ、従来は、メジャーデバイス番号を使用して、ディスクを処理するカーネル関数(デバイスドライバー)へのポインターを検索します。マイナーデバイス番号は、通常、SCSIバスデバイス番号、またはEIDEデバイス番号などのように使用されます。
/proc/cpuinfo
のようなファイルの処理方法に関するその他の決定は、ファイルシステムのタイプに基づいて行われます。あなたが行う場合:
% mount | grep proc
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
/proc
のファイルシステムタイプが「proc」であることがわかります。 /proc
のファイルから読み取ると、ReiserFSまたはDOSファイルシステムでファイルを開くと、カーネルがさまざまな関数を使用してファイルを検索するのと同じように、カーネルはファイルシステムのタイプに基づいて別のことを行います。ファイルのデータを見つけます。
結局のところ、これらはすべてUnix用のファイルであり、それが抽象化の美点です。
カーネルがファイルを処理する方法、これは別の話です。
/ procと最近の/ devと/ run(別名/ var/run)は、RAM内の仮想ファイルシステムです。/procは、カーネル変数および構造へのインターフェース/ウィンドウです。
Linuxカーネル http://tldp.org/LDP/tlk/tlk.html およびLinuxデバイスドライバー、第3版 https://lwn.net/Kernel/LDD3 / 。
FreeBSDオペレーティングシステムの設計と実装も楽しんだ http://www.Amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1
あなたの質問に関連している関連ページを見てください。
@RuiFRibeiroと@BruceEdigerの回答に加えて、ユーザーが行う区別は、カーネルが行う区別とは厳密には異なります。実際には、通常のファイル、ディレクトリ、シンボリックリンク、デバイス、ソケットなど、さまざまな種類のファイルがあります(完全なリストを作成するつもりはないので、常にいくつかを忘れています)。 ls
を使用すると、ファイルのタイプに関する情報を取得できます。これは、行の最初の文字です。例えば:
$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov. 08:29 /dev/sda
最初の「b」は、このファイルがブロックデバイスであることを示します。ダッシュは通常のファイル、「l」はシンボリックリンクなどを意味します。この情報はファイルのメタデータに格納されており、たとえばシステムコールstat
を介してアクセスできるため、カーネルはファイルやシンボリックリンクなどを異なる方法で読み取ることができます。
次に、/bin/bash
のような「実際のファイル」と/proc/cpuinfo
のような「仮想ファイル」を区別しますが、ls
は両方を通常のファイルとして報告するため、違いは別の種類です。
ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root 829792 24 août 10:58 /bin/bash
-r--r--r-- 1 root wheel 0 20 nov. 16:50 /proc/cpuinfo
何が起こるかは、それらが異なるファイルシステムに属していることです。 /proc
は、疑似ファイルシステムprocfs
のマウントポイントですが、/bin/bash
は、通常のディスクファイルシステム上にあります。 Linuxがファイルを開くと(ファイルシステムによって異なります)、データ構造file
にデータが入力されます。これには、他の属性の中でも、このファイルの使用方法を説明するいくつかの関数ポインターの構造があります。したがって、ファイルの種類ごとに異なる動作を実装できます。
たとえば、これらは/proc/meminfo
によってアドバタイズされる操作です。
static int meminfo_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, meminfo_proc_show, NULL);
}
static const struct file_operations meminfo_proc_fops = {
.open = meminfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
meminfo_proc_open
の定義を見ると、この関数は、メモリ使用量に関するデータを収集するタスクである関数meminfo_proc_show
から返された情報をメモリ内のバッファに入力していることがわかります。その後、この情報は通常どおり読み取ることができます。ファイルを開くたびに、関数meminfo_proc_open
が呼び出され、メモリに関する情報が更新されます。
ファイルシステム内のすべてのファイルは、ファイルI/Oを許可するという意味で「本物」です。ファイルを開くと、カーネルはファイル記述子を作成します。ファイル記述子は、ファイルのように機能するオブジェクト(オブジェクト指向プログラミングの意味で)です。ファイルを読み取る場合、ファイル記述子はその読み取りメソッドを実行し、それがファイルシステム(sysfs、ext4、nfsなど)にファイルからのデータを要求します。ファイルシステムは、ユーザー空間への統一されたインターフェイスを提供し、読み取りと書き込みを処理するために何をすべきかを知っています。次に、ファイルシステムは他の層に要求を処理するように要求します。たとえばext4ファイルシステムの通常のファイルの場合、これにはファイルシステムのデータ構造の検索(ディスクの読み取りが含まれる場合があります)が含まれ、最終的にはディスク(またはキャッシュ)からの読み取りによってデータが読み取りバッファーにコピーされます。たとえばsysfsのファイルの場合、それは通常、バッファに何かをsprintf()するだけです。ブロック開発ノードの場合、ディスクドライバーにいくつかのブロックを読み取ってバッファーにコピーするように要求します(メジャー番号とマイナー番号は、ファイルシステムに要求するドライバーを指示します)。