基本概念
Linuxシステムの構成要素
Linuxシステムは、Linuxカーネル、Linuxファイルシステム、Linuxシェル、Linuxアプリケーションで構成されています。
Linuxの起動プロセス
u-bootは一般的なオープンソースのブートローダーです。その起動シーケンスは以下の通りです:
- CPUが電源を投入すると、まずboot ROM(ブートROM)のコードが実行されます。
- boot ROMは、システム内のストレージデバイス(NAND Flash、SDカードなど)をチェックし、起動に使用可能なデバイスを特定します。
- boot ROMは、利用可能なストレージデバイスからブートローダーを検索し、システムメモリにロードします。通常、ブートローダーの名前はu-bootです。
- u-bootがメモリにロードされると、CPUはu-bootのエントリーポイントにジャンプし、u-bootのコードの実行を開始します。
- u-bootは初期化プロセスを実行します。これには、DRAMの初期化、シリアルポートの設定、ネットワークカードの初期化、ストレージデバイスの初期化などが含まれます。
- u-bootはユーザー入力を待ちます。ユーザーはシリアルポートやネットワークポートを通じてu-bootの動作を制御できます。ユーザー入力を待っている間、u-bootは自動的に事前設定されたデフォルトの操作(例:カーネルの自動起動)を実行します。
- ユーザーがコマンドを入力した場合、u-bootはユーザーが指定した操作を実行します。これらの操作には、カーネルの起動、Flashへの書き込み、環境変数の変更などが含まれます。
- u-bootがカーネルを起動する必要がある場合、ストレージデバイスからカーネルイメージをロードし、DRAMに展開します。その後、u-bootはカーネル起動パラメータを設定し、カーネルのエントリーポイントにジャンプして、制御をカーネルに移譲します。
要約すると、u-bootの起動シーケンスは、boot ROMがu-bootをメモリにロードし、u-bootが初期化プロセスを実行してユーザー入力を待ち、その後ユーザーが指定した操作を実行するか、カーネルを起動することです。
LILOとは何か?
LILOはLinuxのブートローダーです。主にLinuxオペレーティングシステムを主メモリにロードし、実行を開始できるようにします。
LinuxがリアルタイムOSでない理由と、LinuxをリアルタイムOSにする方法
Linuxは設計上、ハードリアルタイムオペレーティングシステムではありません。**そのカーネルスケジューリングアルゴリズムは、優先度ベースではなく、プリエンプティブなラウンドロビンスケジューリングに基づいているためです。** これは、Linuxではタスクの応答時間と完了時間を予測できないことを意味し、リアルタイム性が非常に高いアプリケーションシナリオの要件を満たすことができないのです。
しかし、Linuxカーネルはリアルタイム性を強化するためのオプションと拡張機能を提供しており、Linuxをソフトリアルタイムオペレーティングシステムに改造することができます。最も一般的なリアルタイム性強化拡張機能は、Real-Time Patch(RT Patch)です。これはLinuxカーネルのパッチで、カーネルのリアルタイム性と予測可能性を高めることで、システムのリアルタイムパフォーマンスを向上させます。RT Patchは、カーネルのスケジューリングアルゴリズム、遅延処理、タイマー管理などを改良し、システムのリアルタイムパフォーマンスを向上させます。
RT Patchに加えて、Linuxのリアルタイムパフォーマンスを強化する他のツールやテクニックも存在します。例えば、PREEMPT_RTパッチ、IRQスレッド、コントロールグループなどです。
Linuxをリアルタイムオペレーティングシステムに改造するには、適切な構成とコンパイルが必要です。また、異なるアプリケーションシナリオや要件には、異なるリアルタイム性強化拡張機能が必要になる場合があります。したがって、特定のアプリケーションシナリオと要件に基づいて、適切なリアルタイム性強化拡張機能を選択し、適切な構成とコンパイルを行う必要があります。
Linuxにおけるデバイス
カテゴリ
- シリアルデバイス(/dev/tty*)
シリアルデバイスはシリアル通信に使用されます。RS-232、RS-485などの標準が含まれます。シリアルデバイスはLinuxシステムでは/dev/tty*の形式で存在します。シリアルデバイスの特徴は、通信速度が遅く、通信距離が短いですが、通信は安定して信頼性が高いことです。 - パラレルデバイス(/dev/lp*)
パラレルデバイスはパラレル通信に使用されます。通常、プリンターなどのデバイスに接続するために使用されます。パラレルデバイスはLinuxシステムでは/dev/lp*の形式で存在します。パラレルデバイスの特徴は、通信速度が速いですが、通信距離が短いことです。 - ハードディスクデバイス(/dev/sd*)
ハードディスクデバイスはデータを保存するために使用されます。ハードディスクドライブ(HDD)やソリッドステートドライブ(SSD)などが含まれます。ハードディスクデバイスはLinuxシステムでは/dev/sd*の形式で存在します。ハードディスクデバイスの特徴は、容量が大きく、読み書き速度が速いですが、価格が高いことです。 - 光ディスクデバイス(/dev/cdrom、/dev/dvdrom)
光ディスクデバイスはCD、DVDなどの光ディスクデータを読み取るために使用されます。光ディスクデバイスはLinuxシステムでは/dev/cdromと/dev/dvdromの形式で存在します。光ディスクデバイスの特徴は、読み取り速度が遅いですが、価格が安いことです。 - ネットワークデバイス(/dev/eth*)
ネットワークデバイスはネットワーク通信に使用されます。イーサネットカードなどが含まれます。ネットワークデバイスはLinuxシステムでは/dev/eth*の形式で存在します。ネットワークデバイスの特徴は、通信速度が速いですが、ネットワークインフラストラクチャのサポートが必要であることです。
デバイス間の違いと実現方法
これらのデバイス間の違いは主に、接続されているハードウェアが異なること、およびデータ転送速度や安定性などの特性にあります。
これらのデバイス間の通信は、Linuxカーネルが提供するデバイスドライバープログラムを通じて実現されます。デバイスドライバープログラムは、アプリケーションプログラムにインターフェースを提供し、アプリケーションプログラムがデバイスファイルを通じてデバイスの読み書き操作を実行できるようにします。
CLIとGUI
CLI:コマンドラインインターフェース(command-line interface、略してCLI)は、グラフィカルユーザーインターフェースが普及する前に最も広く使用されていたユーザーインターフェースです。
GUI:グラフィカルユーザーインターフェース(Graphical User Interface、略してGUI、またはグラフィカルユーザーインターフェース)は、グラフィカルな方法で表示されるコンピューターの操作ユーザーインターフェースを指します。
inodeとは何か?
Sector:ファイルはハードディスクに保存されます。ハードディスクの最小保存単位は「セクター」(Sector)と呼ばれます。各セクターは512バイト(0.5KBに相当)を保存します。
block:オペレーティングシステムがハードディスクを読み取る場合、セクターを一つずつ読み取るのでは効率が悪いため、一度に複数のセクターを連続して読み取ります。つまり、一度に「ブロック」(block)を読み取ります。この複数のセクターで構成される「ブロック」は、ファイルアクセスの最小単位です。「ブロック」のサイズは、最も一般的に4KB、つまり8つのセクターが連続して1つのブロックを構成します。
inode:ファイルデータはすべて「ブロック」に保存されます。したがって、明らかに、ファイルのメタ情報(ファイルの作成者、作成日、ファイルサイズなど)を保存する場所を見つける必要があります。このファイルのメタ情報を保存する領域がinodeと呼ばれます。日本語では「索引节点」と訳されます。各ファイルには対応するinodeがあり、ファイルに関する情報が含まれています。
ハードリンクとソフトリンク
ファイルの属性
ターミナルで`ls -al`コマンドを実行すると、現在のディレクトリ内のすべてのファイルとフォルダーの詳細情報が表示されます。
最初の文字はファイルタイプを示します。ディレクトリ、ファイル、またはリンクファイルなどです。
その後の9文字は3文字ずつグループ化され、最初のグループはファイル所有者の権限、2番目のグループはユーザーグループの権限、3番目のグループは他のユーザーグループの権限です(r:読み取り、w:書き込み、x:実行、-:権限なし)。
例えば、「rw-r--r--」は、ファイルの所有者はファイルに読み取りと書き込みの権限があるが、実行権限はないこと、同じユーザーグループの他のユーザーはファイルにのみ読み取り権限があること、他のユーザーもファイルにのみ読み取り権限があることを意味します。
リンク数:このノードに接続されているファイル名の数を示します。
ファイル所有者:このファイルの「所有者のアカウント名」を示します。
ファイルが属するユーザーグループ。
ファイルサイズ:このファイルのサイズを示します。デフォルトの単位はB(バイト)です。
ファイルの最終更新日時:このファイルの作成日時または最終更新日時。
ファイル名:対応するファイルのファイル名。ファイル名の前に「.」が付いている場合、これは「隠しファイル」であることを意味します。`ls -a`コマンドを実行すると、隠しファイルが表示されます。
カーネル
Linuxカーネルとは何か?
Linuxカーネルの構成
- システムコール:ユーザースペースのプログラムとカーネル間のインターフェースを提供し、アプリケーションがカーネルが提供する機能やサービスを呼び出せるようにします。
- プロセス管理:プロセスの作成、管理、スケジューリングを担当します。プロセスの作成、破棄、スケジューリングなどの機能が含まれます。
- メモリ管理:メモリリソースを管理します。物理メモリの割り当てと解放、仮想メモリのマッピングと管理などが含まれます。
- ファイルシステム:ストレージデバイスとファイルへのアクセスインターフェースを提供し、さまざまなファイルシステム形式をサポートします。
- ネットワークプロトコルスタック:さまざまなネットワークプロトコルを実装し、ネットワーク通信機能を提供します。
- デバイスドライバ:ハードウェアデバイスの抽象化と制御インターフェースを提供し、さまざまなデバイスドライバープログラムをサポートします。
システムコール
システムコールの役割
- リソースアクセスの提供:アプリケーションはシステムコールを介してオペレーティングシステムが提供するリソース(ファイルの読み書き、ネットワーク通信、デバイスアクセスなど)を要求できます。
- ユーザーモードとカーネルモードの切り替えの実現:アプリケーションは通常ユーザーモードで実行されますが、一部の操作はカーネルモードで実行する必要があります。システムコールを介して、アプリケーションは制御をカーネルモードに切り替え、オペレーティングシステムのコアが特権操作を実行できるようにすることができます。
- オペレーティングシステムサービスの提供:システムコールはオペレーティングシステムが提供するさまざまなサービスと機能をカプセル化します。アプリケーションはこれらのサービスをシステムコールを介して使用できます。
- プロセス間通信の実現:システムコールはプロセス間通信のメカニズムを提供し、異なるアプリケーション間でデータ交換と協力を行うことができます。アプリケーションはシステムコールを介してメッセージの送受信、共有メモリへのアクセスなどを行うことができます。
一般的なシステムコール関数
read()/write()
呼び出し後のカーネル実行フロー
- ユーザースペースでread()/write()システムコールを開始し、パラメータをカーネルに渡します。
- カーネルはシステムコール番号に基づいて対応するカーネル関数を見つけ、処理します(例:sys_read()/sys_write())。
- カーネルはファイル記述子に基づいて対応するファイルオブジェクトを見つけ、読み取りまたは書き込み操作を実行します。
- 読み取り操作では、カーネルはデータをファイルまたはデバイスからカーネルスペースに読み取り、ページキャッシュ層を介して管理します。
- 書き込み操作では、カーネルはデータをユーザースペースからカーネルスペースにコピーし、ファイルシステム層を介してデータをファイルまたはデバイスに書き込みます。
- カーネルは、キャッシュ管理、ブロックデバイス管理、ドライバープログラムなどのレイヤーを介してデータを処理および転送する場合があります。
- 処理が完了すると、カーネルは結果をユーザースペースに返し、ユーザースペースは次の操作を続行します。
ブートローダー
ファイル管理
ディスク関連情報
シリンダーはCylinder、ヘッドはHead、セクターはSectorです。これら3つの構造の番号がわかれば、ディスク内の特定のセクターを特定できます。
シリンダーの番号がわかれば、トラックの番号が確定します。ヘッドはどのディスク面かを特定し、セクター番号はトラック内のセクターの位置を知ることができます。これら3つの番号がわかれば、特定のディスクプレート上の特定のトラック上の特定のセクターを特定でき、現在アクセスしているセクターがわかります。
このようなアドレスは**CHSアドレス**と呼ばれ、この方法を使用することで、ディスク内の各ユニットの正確な位置を見つけることができます。
ファイルシステム
セクター、ブロック、パーティション、グループ
オペレーティングシステムはパーティションを上記のようなグループに細分化し、さらにBoot Block領域を分離します。Boot Block
グループの属性
Data blocks
Data blocksは、**グループ内でファイルの内容を保存する領域です。この領域はブロックblockを単位としており、各ブロックのサイズは4KBです。** グループの大部分を占めています。
なぜ4KB単位なのか?オペレーティングシステムとハードウェアのI/O操作の基本単位が4KBであり、4KBはオペレーティングシステムのI/Oに便利だからです。つまり、**ファイルはオペレーティングシステムでは4KB単位で保存されます。ファイルの内容が4KBに達していない場合でも、このファイルは依然として4KBのブロックを占有し、このブロックはこのファイル専用であり、他のファイルは使用できません。**
ファイルの内容が増加する過程で、ファイルも4KB単位で増加します。
inode Table
Linuxシステムにはinode構造体が存在します。この構造体はディスクファイルのさまざまな属性を保存します。
私たちは`ll`または`stat`を使用して複数または単一のファイルの属性を表示できます:
私たちが`stat`を使用して単一ファイルの詳細な属性を表示すると、ファイルには非常に多くの属性があることがわかります:File Size、Blocks、IO Block、Device、Inode、Links、Access、Uid、Gidなど。
その中には私たちがよく知っているfile(ファイル名)やAccess(権限)がありますが、まだ多くの知らないものがあります:Blocks、IO Block、Inode、Linksなど。
これらの属性はすべてLinuxシステムのinode構造体に保存されています:
これらはまだ一部ですが、当面は、**inodeは構造体であり、ファイルのすべての属性を保存している**ということを知っておけば十分です。
**inode構造体には、inodeという属性が保存されています。これは整数値であり、オペレーティングシステム内のファイルの一意の番号を示します。**
これは`stat`コマンドの出力にあるInodeという属性であり、`ll -i`でも確認できます:
inodeが何であるかがわかったので、inode Tableを見てみましょう。inode Tableは、グループ内でファイルのinode構造体を保存するためのテーブルまたは配列であり、inode Tableの各単位は1つのinode構造体を保存します。
inode構造体のサイズは128バイトなので、inode Tableの単位サイズは128バイトです。
inode構造体はファイルのすべての属性を保存していますが、ファイル名は保存していません。
ファイル名はLinuxオペレーティングシステムで属性ですか?はい、ですが、inodeにはファイル名が保存されていません。これは、Linuxの低レベルではファイル名を認識していないことを意味します。inode構造体に保存されているinode番号は、オペレーティングシステムの低レベルでのファイルの一意の実際の識別子です。
inode Table内の各セルは、ファイルのinodeを保存しているか、保存していないかの2つの状態しかありません。
inode Bitmapは、各inode IDが空きであるかどうかを示すビットマップです。使用済みであれば、再利用できません。
Block Bitmap
inode Bitmapと同様に、Block BitmapはData Blocksの占有状況を記述するために使用されます。
Group Descriptor Table
この部分は、グループ内の概要情報を記述しています:inodeの開始番号、inode Tableがどれだけ使用され、どれだけ残っているか、Data Blocksがどれだけ使用され、どれだけ残っているか、このGroupの実際のサイズはどれくらいか……
その一部の情報はグループ内の属性から計算できますが、時間コストがかかるため、統計情報を直接記録して保存する方が良いでしょう。
この部分はGDTと略称できます。
Super Block
この部分はSuper Block(スーパーブロック)と呼ばれます。実際には、そのグループに固有ではありません。
なぜなら、このブロックは、このパーティション内の最も重要な属性を記述するデータ構造であり、リアルタイムで維持する必要があるからです。
オペレーティングシステムがパーティション内の特定のグループにデータを書き込むとき、Super Blockも維持状態にあります。この時点で、書き込みプロセスと維持プロセスが意図せず中断した場合(例:デスクトップPCが突然停電)、現在維持されているSuper Blockが破損する可能性はありませんか?
パーティションにSuper Blockが1つしかなく、すでに破損している場合、このパーティションは使用できますか?このパーティションがシステムパーティションである場合、システムはどうなりますか?
したがって、Super Blockは、単一のストレージで破損して回復不能になるのを防ぐために、パーティション内に多くのバックアップを保存する必要があります。
Windowsのように、オペレーティングシステムがデータを書き込んでいる最中に突然電源が切れた場合、次回起動時に「前回のシステムは異常終了しました。どうしますか?回復して起動しますか?」という確認が表示されることがよくあります。パーティションにSuper Blockのような構造が1つしかない場合、回復は不可能です。
すべてのグループ内にSuper Blockが保存されるわけではありません。一部のグループに保存されます。
inodeはどのようにそのファイルのData Blocks部分と関連付けるのか?
Data Blocksはファイルの内容を保存しており、4KB/ブロック単位です。
inode構造体はファイルのシステムレベルのすべての属性を記述しており、その中にはファイルの内容がData Blocks内のどこに保存されているかを記述する情報が必ず含まれています。
inodeにはblock[15]のような配列構造が保存されています。その中で:
一部はファイルの内容がData Blocks内のどこに保存されているかを保存する場所です。例えば[0, 11]のような場所は、ファイルの内容に対応するData Blocksの番号を直接保存します。これが直接ブロックポインタです。
ファイルの内容が大きく、一部で記述しきれない場合、もう一部の内容があります。[12, 14]の部分は、あるData Blockを保存しますが、このブロックに保存されているのはファイルの内容ではなく、[0, 11]のように、このファイルの内容がData Blocks内の他の番号に対応するものを保存します。これには間接ブロックポインタ、または二重間接ブロックポインタ、または三重間接ブロックポインタが必要になります。
- 直接ブロックポインタ
直接ブロックポインタは、inodeがblockブロックの番号を直接記録し、blockブロックを直接指します。例えば、ファイルの属性と権限データがinode 4番に配置され、このinodeがファイルデータの実際の位置を配置するポイントが2、7、13、15の4つのblock番号である場合、オペレーティングシステムはこれに基づいてディスクの読み取り順序を並べ替えることができ、4つのblockの内容を直接読み取ることができます。データの読み取りは以下の図のようになります。 - 間接ブロックポインタ
間接ブロックポインタは、直接ブロックポインタと大差ありません。どちらもポインタですが、直接ブロックポインタは指しているblockブロックにファイルのデータが保存されているのに対し、間接ブロックポインタは指しているblockブロックをさらにポインタブロックとして使用します。したがって、間接ポインタが指しているblockブロックにはポインタ情報が保存されており、次のblockブロックに保存されているファイルデータを指します。 - 二重間接ブロックポインタ
間接ポインタブロックを理解すれば、二重間接ポインタブロックは理解しやすいです。これは間接ポインタブロックの上に、2回目に指しているblockブロックもポインタとして使用することで、より多くのblockブロックを指すことができます。 - 三重間接ブロックポインタ
三重間接ブロックポインタの原理は二重間接と同じですが、3回目に指しているblockブロックもポインタとして使用することで、さらに多くのblockブロックを指すことができます。
前述のように、直接ブロックポインタを使用するファイルの最大サイズは48KBに制限されます。ポインタブロックが4バイト必要とすると仮定すると、1つのblockブロックには4Kの保存スペースがあるため、1つのblockブロックには1024個のポインタブロックを保存できます。したがって、間接ブロックポインタを使用するファイルの最大サイズは1024*4K=4Mになり、二重間接ブロックポインタを使用するファイルの最大保存スペースは1024*1024*4K=4G、三重間接ブロックポインタを使用するファイルの最大保存スペースは1024*1024*1024*4K=4Tになります。
ファイルの作成と削除の実行フロー
ファイルシステム内のディレクトリ
私たちは、Linuxシステムではディレクトリもファイルであり、ファイル=属性+内容であることを知っています。
ディレクトリの属性は私たちが何であるかはわかっていますが、ディレクトリファイルの内容は何でしょうか?
ディレクトリにアクセスし、ディレクトリ内にファイルを作成し、ディレクトリ内のファイルを表示するには、どのような権限が必要ですか?
ディレクトリにアクセスしてディレクトリに入るには、x(実行)権限が必要です。ディレクトリ内にファイルを作成するには、w(書き込み)権限が必要です。ディレクトリ内のファイルを表示するには、r(読み取り)権限が必要です。
そして、ファイルのwとr権限は実際にはファイルの内容の読み書き権限です。つまり、**ディレクトリファイルの内容は、ディレクトリ内のファイルそのものです。**
より正確に言うと、**ディレクトリファイルの内容は、ディレクトリ内のファイルのファイル名とinode番号との間のマッピング関係です。**
同じディレクトリ内に、同じファイル名が複数存在できますか?できません。同じディレクトリ内のファイル名は一意であるため、1つのファイル名は1つのinode番号に対応します。
ファイルを作成する場合、オペレーティングシステムは何をしますか?
Linuxのinodeに関する多くの情報を紹介しましたが、ファイルを作成する際にオペレーティングシステムがどのような操作を行い、ユーザーが正しくファイルにアクセスできるようにするのでしょうか?
オペレーティングシステムの大まかな操作フローは次のようになります:
- ファイルのinodeを作成し、inodeと内容をそれぞれグループのinode TableとData Blocksに保存し、inode BitmapとBlock Bitmapの対応する内容を変更します。
- 現在のユーザーがいるディレクトリを見つけ、そのディレクトリのinodeに基づいて、ディレクトリファイルがData Blocks内のデータブロックを特定します。
- 作成したファイルのファイル名とinode番号を、ディレクトリファイルのData Blocksのデータブロックに保存し、関連するBlock Bitmapを変更します。
これにより、指定されたディレクトリ内で指定されたファイルを見つけることができます。
ファイルを削除する場合、オペレーティングシステムは何をしますか?
Linuxオペレーティングシステムはファイルを削除する際にどうしますか?
一般的に、私たちがファイルを削除するという最初の認識は、ファイルのinodeと内容をinode TableとData Blocksから削除し、inode BitmapとBlock Bitmapの対応する位置を0に設定し、ディレクトリファイルの内容データブロック内のマッピング関係を削除することです。これらを行えば、ファイルが削除されたことになります。
しかし、実際には、オペレーティングシステムはこのように操作しません。
**オペレーティングシステムはファイルを削除する際、Data Blocksに保存されているファイルの内容とinode Tableの属性を物理的に削除するのではなく、inode BitmapとBlock Bitmapのこの2つのビットマップ内の削除されたファイルの位置を0に設定するだけです。そして、ディレクトリファイルのBlock Bitmapの関連位置を0に設定します。これでファイルの削除が完了します。**
なぜなら、inode BitmapとBlock Bitmapのこの2つのビットマップは、ディスク内の実際のストレージブロックの使用状況を記述しているからです。これらのビットマップの関連位置が0であれば、対応するinode TableとData Blocksのストレージブロックには有効なデータが保存されておらず、対応する位置は直接使用できる状態であるとオペレーティングシステムは判断します。
つまり、オペレーティングシステムがファイルに対する削除操作を行うと、効果的には削除が完了します。なぜなら、オペレーティングシステムはそれらのスペースを再度使用できるからです。しかし、物理的なスペースから見ると、それらのスペース内には実際にまだ関連するファイルデータが保存されています。したがって、ファイルが削除された後、それらのスペースが再度占有されなければ、ファイルは回復できます。ファイルのinodeがわかれば、理論的には回復可能です。しかし、ファイルを削除した後、オペレーティングシステムはそれらのスペースを自由に使用できるため、実際には回復できない可能性もあります。
ソフトリンクとハードリンク
私たちがLinuxファイルシステムの関連情報を理解した後、Linuxの低レベルではファイル名という概念が存在しないことがわかりました。
オペレーティングシステムの低レベルでは、実際にはファイル名ではなく、inode番号によって識別されます。
では、ディスク内に複数のファイル名が同じinode番号にマッピングされる可能性はありませんか?
ハードリンク
ディレクトリ内のファイル名とinode番号は、指定されたデータブロック内にマッピング関係として保存されます。
オペレーティングシステムの低レベルではファイル名を認識しないため、ファイルへのアクセスや読み書きは、最終的にinode番号を通じて実現されます。
つまり、ファイル名がinode番号にマッピングされさえすれば、そのファイル名を通じて指定されたファイルにアクセスできます。同じinode番号にマッピングされる複数のファイル名が存在しても問題ありません。
ハードリンクは、異なるファイル名を同じinode番号にマッピングすることができます。
ハードリンクを作成するコマンドは:`ln 元のファイル名 新しく作成するハードリンクファイル名`
異なるファイル名が同じinodeにマッピングされていることがわかります。つまり、これらは同じファイルであり、ファイル名が異なるだけで、オペレーティングシステムはディスク上に内容が同じのファイルをもう一つ作成せず、ディレクトリのData Blocksデータブロックにマッピング関係を追加するだけです。他のデータはありません。
`ln`を実行した後、このファイルのinode番号に加えて、もう一つの変化があります:権限を示す欄の後の数字が1から2に変わりました。
これは何を意味しますか?
実際、**この数字はinode構造体が記録しているこのファイルのハードリンク数です。** ディスク内にこのinodeにハードリンクされているファイルが一つでも存在すれば、このカウントは+1されます。
このように見ると、ファイルはオペレーティングシステム内では、inode構造体+ファイルの内容として見なせます。ファイル名はユーザーが確認し、記憶するための、実際的な重要性のない「着せ替え人形」に過ぎず、ファイル名がマッピングするinode番号が、実際のファイルデータを指す最も重要なものです。つまり、**inode番号は「ポインタ」のようなものです。**
では、このハードリンク数は何の役に立つのでしょうか?
ハードリンク数は、カウントの役割を果たします。このinodeにハードリンクされているファイルがまだどこかでマッピングされている、または使用されている限り、このカウントは0ではありません。
これに対応して、このファイルのハードリンク数が0になると、このファイルはオペレーティングシステム内で存在する必要がなくなったと判断され、削除できます。
つまり、ファイルのハードリンク数が0になっている場合にのみ、ディスク内のファイルが削除されます。0でない場合、最多はそのファイル名とのマッピングを解除したに過ぎません。
ハードリンクは何の役に立つのでしょうか?
この質問に答えるには、まずディレクトリファイルと通常ファイルを作成します:
なぜこうするのでしょうか?
通常ファイルが作成された後、実際のファイルにマッピングされているファイル名は一つだけです。
しかし、ディレクトリファイルは異なります:
これが、現在のディレクトリ内の実行可能ファイルを実行する際に`./`を接頭辞として使用する必要がある理由です。
ソフトリンク
ソフトリンクはハードリンクと比較すると、特に注意すべき点はほとんどありません。
ソフトリンクを作成するコマンドも`ln`ですが、オプション`-s`を追加する必要があります。これはsoft(ソフト)と見なせます。つまり、`ln -s`はソフトリンクの作成を意味します。
ハードリンクとは異なり、ソフトリンクは新しいinodeを持つ新しいファイルを生成します。
ソフトリンクには特別な注意点はありません。LinuxのソフトリンクはWindowsのショートカットと見なすことができます。
ソフトリンクが作成した新しいファイルの内容は、リンク先の元のファイルのパスです。
ソフトリンクとハードリンクはどちらも、unlinkコマンドでリンクを解除できます。
プロセス管理
ネットワークプログラミング
シェル
GCC
GDB
GDBの起動
gdb ファイル名
ブレークポイントの設定
(gdb) b 行番号
(gdb) b ファイル名:行番号