LinuxにおけるI/Oデバイス管理について
LinuxにおけるI/Oデバイス管理について学習したため、そのまとめとして個々に整理する。
sysfsファイルシステム
- Linuxにおける特殊ファイルシステムの一種であり、一般的には
/sys
ディレクトリにマウントされている。 - procファイルシステム同様、ユーザーモードのアプリケーションからカーネル内部のデータにアクセスするために設計されたものであるが、procファイルシステムよりも、接続されているデバイスやバスについてより構造化されている。以下、sysfsに含まれる代表的なディレクトリを記載する。
kオブジェクト
- Linuxにおけるデバイスドライバモデルを実装するために使用されるデータ構造。
- 各kオブジェクトは、それぞれsysfsのディレクトリと対応している。
- バス・デバイス・ドライバのディスクリプタなどをそれぞれ「コンテナ」という概念で扱い、
kobject
構造体によって表される。
デバイスファイル
- UNIX系オペレーティングシステムの特性上、あらゆるものをファイルとして扱うことを基本としており、デバイスの入出力に関してもファイルへの読み書きと同様に行えるように設計されている。
- このような、デバイスとのやり取りに使用されるファイルをデバイスファイルと呼び、各デバイスファイルへの読み書きは対応するデバイスドライバへのデータの受け渡しと等価となる。
デバイスドライバ
動的リンクについて (Linux)
Linuxの動的リンクについて学習したため、そのまとめとしてここに整理する。
動的リンクとは
- プログラムとライブラリを連結させる方法の一つで、予めコンパイルされ所定の場所に置かれているオブジェクトファイル(共有ライブラリ)を読み込むように連結させる方法。
- コンパイル後の実行ファイルには、ライブラリ自体のコードは含まれず、共有ライブラリをロードし呼び出す処理が含まれる。
- 正反対の連結方法として静的リンクという方法が存在し、プログラムのコンパイル時にライブラリを直接埋め込んだ状態で実行ファイルを生成する。
動的リンクのメリット
- ライブラリ自体のコードが含まれないため、静的リンクよりもファイルサイズが小さくなる。
- ライブラリを実行ファイルに直接埋め込まないため、ライブラリのアップデートやリプレイスが静的リンクに比べ容易に行える(静的リンクの場合は再コンパイルが必要)。
動的リンクのデメリット
- ライブラリの有無など、プログラムの実行環境に依存する(実行環境に共有ライブラリが存在しない場合など実行できない)。
共有ライブラリの検索
動的リンクによってプログラムをコンパイルする際、共有ライブラリは以下の順序で検索される。
環境変数
LD_LIBRARY_PATH
で指定されているパスの配下- 設定ファイル
/etc/ld.so.cache
内に記載されているパスの配下 /lib
,/usr/lib
の配下
動的リンクでコンパイルされた実行ファイルについて
- Linuxにおいて、実行ファイルは
ELF
という形式に基づいて生成される。(ELFに関しては別記事にて整理) - ライブラリ呼び出す処理は、
PLT (Procedure Linkage Table)
内のエントリを介して呼び出すように抽象化されており、ライブラリの関数名の末尾に@plt
が付与されている。 PLT
自体は.plt
セクションに配置されており、各エントリ内ではGOT (Global Offset Table)
と呼ばれる「プログラム実行時に共有ライブラリをロードしたメモリのアドレス等を管理しているテーブル」からアドレスを取得し呼び出している。
共有ライブラリのロード
Linuxにおけるファイルシステムについて
Linuxにおけるファイルシステムについて学習したため、そのまとめとしてここに整理する。
ファイルシステムとは
Linuxで主に使用されるファイルシステム
スーパーブロック
inode領域
- すべてのinodeがテーブル形式で管理されている領域
データブロック
- ファイルやディレクトリの実際のデータが保存されている領域
inode
- ファイル・ディレクトリと一対一で結びつく、一意なデータ構造
- ファイルタイプや所有者番号、実際にデータが管理されているディスク上の位置やサイズなどといった情報を保持している
ディレクトリの実態
- ファイルと同様にinodeが割り当てられinode領域上に管理され、データブロック内に実際のデータが保存されている
- 保持しているデータは、自身の子であるファイルのファイル名とinode番号のペアである
A20ゲートについて
A20ゲートについて学習したため、そのまとめとしてここに整理する。
A20ゲートとは
背景
- 従来の8086プロセッサは16bitCPUであったため、レジスタの幅は16bitであり参照できるメモリ空間にも制限があった。(216 = 65,536bytes = 64KB)
- この制限以上のメモリ空間を参照するため、2つのレジスタを使用しそれぞれ「セグメント」「オフセット」といった情報を保持し、最大1MBのメモリ空間への参照を可能としていた。(segment << 4 + offset = 216 * 24 = 64KB * 16 = 1024KB = 1MB)
- 1MBのメモリ空間を参照するために、8086プロセッサには20本(1MB = 220)のアドレスバスが用意されており、それぞれA0 ~ A19とされていた。
- その後、8086よりもアドレスバスの幅が拡張された80286(24bit)や80386(32bit)が登場し、より広いメモリ空間を参照できるようになったが、アドレスバスの数の差により8086との互換性がなくなり、80286や80386で動かせるプログラムが8086では動かせなくなってしまった。(80286や80386で表すことができるアドレスを8086で表そうとすると20bitではオーバーフローし、正しいメモリアドレスを参照できないため)
- このため、A20以降のアドレスバス(21番目以降のアドレスバス)を有効にするかどうかを制御する回路(A20ゲート)が追加され、1MB以上のメモリ空間を参照するためにはこの回路を有効化することでより大きなメモリ空間を参照することとし、16bitプロセッサとの互換性が維持された。
有効化する方法
- キーボードコントローラから
- キーボードと直接関係はないが、当時空いていたポートがキーボードコントローラに存在していたため割り当てられたそう
- BIOS割り込み(INT 15)から
Multiboot specificationについて
Multiboot specificationについて学習したため、そのまとめとしてここに整理する。
Multiboot specification
- ブートローダからカーネルをロードする方法について規定した仕様
- この仕様に従って構成されているブートローダ・カーネルであれば、どのような組み合わせでも起動可能
- OS開発者は、OSイメージの先頭部分(Multiboot Header)をMultiboot specificationに準拠した形で構成し、ブートローダ開発者はMultiboot specificationに対応したOSイメージを読み込むように実装する必要がある
背景
- 従来、ブートローダからカーネルをロードする方法については標準化されておらず、それぞれのOSが開発者によって独自に開発されたブートローダを持っていた。
- このため、OSをインストールするたびにブートローダも再インストールする必要があり、複数のOSが共存することを困難にしていた。
- そこで、このMultiboot specificationが発案され、ブートローダ開発者・OS開発者はこの仕様に準拠することでこのような問題を解決することができた
技術的な仕様
- Multiboot header構成
- magic (0 ~ 3byte)
- ブートローダから、OSイメージがMultiboot specificationに対応しているかを判断するためのフィールド。
- flags (4 ~ 7byte)
- OSイメージが必要とする機能を、ブートローダ側で初期化するために指定するフィールド。
- checksum (8 ~ 11byte)
- magicとflagsの値を合計した値
- header_addr (12 ~ 15byte)
- flagsの16bitがセットされているときのみ有効
- load_addr (16 ~ 20byte)
- flagsの16bit目がセットされているときのみ有効
- load_end_addr (21 ~ 23byte)
- flagsの16bit目がセットされているときのみ有効
- bss_end_addr (24 ~ 27byte)
- flagsの16bit目がセットされているときのみ有効
- entry_addr (28 ~ 31byte)
- flagsの16bit目がセットされているときのみ有効
- mode_type (32 ~ 35byte)
- flagsの2bit目がセットされているときのみ有効
- width (36 ~ 39byte)
- flagsの2bit目がセットされているときのみ有効
- height (40 ~ 43byte)
- flagsの2bit目がセットされているときのみ有効
- depth (44 ~ 47byte)
- flagsの2bit目がセットされているときのみ有効