
これは非常に低いレベルの質問であり、おそらくこれが質問するのに最適な場所ではないことを知っています。しかし、他のどのSEサイトよりも適切に見えたので、ここまでです。
Linuxファイルシステムでは、一部のファイルが実際に存在する、例:/usr/bin/bash
存在します。しかし(私が理解している限り)一部は実際には存在せず、より多くが存在します。仮想次のファイル/dev/sda
:/proc/cpuinfo
など私の質問は次のとおりです(2つですが、別の質問になるにはあまりにも密接に関連しています)。
- 読み取りコマンド(または同様のコマンド)が実行されると、Linuxカーネルはこれらのファイルが実際であるか(したがってディスクから読み取られるか)どうすればわかりますか?
- ファイルが実際ではない場合:たとえば、read fromはランダムな
/dev/random
データを返し、read fromは/dev/null
を返しますEOF
。この仮想ファイルから読み取るデータを決定する方法(およびデータが仮想ファイルに書き込まれるときに実行するアクション) - 各ファイルまたは仮想ディレクトリに適した個別の読み取り/書き込みへのポインタを持つ一種のマッピングはありますか?自分で注文しますか?したがって、アイテムは/dev/null
単にEOF
。
答え1
したがって、ここには基本的に2つのタイプがあります。
- データとメタデータを含むディレクトリに慣れている方法でファイルを保存する一般的なファイルシステム(ソフトリンク、ハードリンクなどを含む)は常にそうではありませんが、通常は永続ストレージに使用されるブロックデバイスにバックアップされます(tmpfsはRAMにのみ存在します)しかし、それ以外は通常のファイルシステムと同じです)。読み、書き込み、名前変更などの意味はなじみがあり、すべてが期待どおりに機能します。
- さまざまな仮想ファイルシステム。
/proc
またはなどのFUSEカスタムファイルシステムと同様に、ここには例があります/sys
。実際には、ある意味では「ユーザー定義」の意味を持つファイルシステムを参照するので、はるかに多様です。したがって、ファイルの下のファイルからデータを読み取るとき、通常のファイルシステムのように、以前に作成された他の項目によって保存された特定のデータに実際にアクセスすることはありません。本質的にカーネル呼び出しを実行して、即座に生成された情報を要求します。このコードは意味を実装する関数にすぎないので、何をしたいかをすることができます。その結果、実際にはシンボリックリンクではなく、シンボリックリンクであるかのように偽装するなど、ファイルの奇妙な動作を経験することになります。sshfs
ifuse
/proc
read
/proc
重要なことは、/dev
それが一般的に最初であるということです。最新のディストリビューションでは/dev
tmpfsのようなものが一般的ですが、以前のシステムでは特別な属性なしでディスクの一般的なディレクトリであることが一般的です。鍵は、次のファイルが/dev
FIFOまたはUnixソケットに似た特殊ファイルであるデバイスノードであることです。デバイスノードには、メインデバイス番号とマイナーデバイス番号があります。これを読み書きするのはカーネルドライバを呼び出すことです。 FIFOを読み書きすることは、パイプの出力をバッファリングするためにカーネルを呼び出すのと同じです。ドライバは必要なものは何でもできますが、通常はハードドライブにアクセスしたり、スピーカーでサウンドを再生するなど、あらゆる方法でハードウェアに触れます。
元の質問に答えるには:
「ファイルが存在しますか」に関する2つの質問があります。これは、デバイスノードファイルが実際に存在するかどうか、およびそれをサポートするカーネルコードが意味があるかどうかです。前者は通常のファイルシステムと同様に解決されます。最新のシステムは、
udev
ハードウェアイベントを監視し、/dev
それに応じてデバイスノードを自動的に作成および削除するのと同様のものを使用します。ただし、古いシステムまたは軽量カスタムビルドでは、事前に作成されたすべてのデバイスノードをディスクに直接保存することができます。同時に、これらのファイルを読み取ると、メジャーおよびマイナーデバイス番号によって決定されたカーネルコードが呼び出されます。これが不合理な場合(たとえば、存在しないブロックデバイスを読み取ろうとする場合)、I / Oエラーです。どのデバイスファイルに対してどのカーネルコードを呼び出すかを把握する方法はさまざまです。などの仮想ファイルシステムでは、
/proc
独自の機能を実装しますread
。write
カーネルはマウントポイントに基づいてそのコードを呼び出し、ファイルシステムの実装は残りを処理します。デバイスファイルの場合、プライマリおよびマイナーデバイス番号に基づいて予約されます。
答え2
/dev/sda1
以下は、ほぼ最新のArch Linuxサーバー上のファイルのリストです。
% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov 9 13:26 /dev/sda1
/dev/
したがって、forのディレクトリエントリにはsda
inode番号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 */
この構造は、ファイルinodeのディスク構造を示しています。構造には興味深いものがたくさんあります。詳しく見てください。
i_mode
16ビットで、struct ext2_inode
ユーザー/グループ/その他、読み取り/書き込み/実行権限には9ビットのみを使用し、setuid、setgid、およびStickyには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」であることがわかります。 ReiserFSまたはDOSファイルシステムでファイルを開くと、カーネルが他の機能を使用してファイルを見つけてファイル内のデータを見つけるのと同じように、ファイルからデータを読み取ると、カーネルはファイル/proc
システムの種類に応じて他の操作を実行します。文書。
答え3
結局のところ、それらはすべて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
ご質問に関連するページをご覧ください。
答え4
ファイルシステム内のすべてのファイルは、ファイルI / Oを許可するという点で「実際」です。ファイルを開くと、カーネルは(オブジェクト指向プログラミングの観点から)ファイルのように動作するオブジェクトであるファイル記述子を生成します。ファイルを読み取ると、ファイル記述子は読み取りメソッドを実行し、このメソッドはファイルシステム(sysfs、ext4、nfsなど)からファイルのデータを要求します。ファイルシステムは、ユーザ空間への統合インタフェースを提供し、読み書きの処理方法を知っています。その後、ファイルシステムは別の層に要求を処理するように要求します。 ext4ファイルシステムの通常のファイルには、ファイルシステムのデータ構造ルックアップ(ディスク読み取りを含む)と、最終的にディスク(またはキャッシュ)から読み取ってデータを読み取りバッファにコピーすることが含まれます。 sysfsにあるファイルの場合、通常sprintf()がバッファに何かを書くだけです。ブロック開発ノードの場合、ディスクドライバにいくつかのブロックを読み込み、それをバッファにコピーするように要求します(メジャー番号とマイナー番号は、要求を送信するドライバをファイルシステムに通知します)。