OS

概要

初心者から大学院レベルまでの包括的解説

現代のコンピュータシステムは、アプリケーションからクラウドインフラ、モバイル端末、IoT までのすべてが OS の上に成り立っています。この章では、OS の理論・実装・歴史・最新動向を体系的に整理します。

要点
この章は、OS を「プロセス・メモリ・ファイル・I/O・ネットワークをどう安全かつ効率よく共有するか」という視点で理解するための全体地図です。定義や理論だけでなく、Linux を軸に実装や観察のしかたまでつなげます。

この章の対象

この章は次の読者を想定しています。

  • 初心者向け: OS の基本概念から学びたい方
  • 開発者向け: システムプログラミング・パフォーマンス改善に取り組む方
  • インフラ/SRE 向け: Linux カーネル・コンテナ・クラウドを深く理解したい方
  • 研究者・学生向け: OS 設計の理論的基盤を押さえたい方

OSとは何か

オペレーティングシステム(Operating System, OS) は、コンピュータのハードウェアとソフトウェアの資源を管理し、プログラムが実行するための共通サービスを提供するシステムソフトウェアである。OSの本質は以下の三つの側面に凝縮される。

  1. リソース管理者(Resource Manager)CPU、メモリ、ディスク、ネットワーク、周辺機器を公平かつ効率的に配分する。
  2. ハードウェア抽象化層(Hardware Abstraction Layer) — 多様なハードウェアの違いを隠蔽し、統一的なインターフェースを提供する。
  3. 仮想マシン提供者(Virtual Machine Provider) — 各プロセスに「自分専用のコンピュータ」という幻想を与え、保護・分離を実現する。

キーコンセプト: OSは「ユーザーと機械の仲介者」であり、同時に「ハードウェアの複雑性を隠蔽するレイヤー」であり、さらに「各プロセスに独立した仮想世界を提供するハイパーバイザ的存在」でもある。これら三つの役割を統合的に担う点が、OSを他のソフトウェアから際立たせる。

現代のOSは単なる「PCを動かす土台」にとどまらず、クラウド、コンテナ、モバイル、組み込み、リアルタイム制御、さらにはAI推論基盤に至るまで、情報社会の根幹を支える巨大な技術スタックである。Linux カーネルも、数千万行規模のコードと多数の開発者による長年の分散開発の上に成り立つ、世界最大級のオープンソース基盤の一つである。


目次

  1. OSの定義と哲学
  2. OSの主要機能
  3. OSのアーキテクチャ
  4. カーネルモードとユーザーモード
  5. システムコールとABI
  6. Linuxアーキテクチャの詳細
  7. コアコンポーネント
  8. ブートプロセスと初期化
  9. プロセス管理
  10. スレッドと並行性
  11. CPUスケジューリング詳細
  12. 同期機構とプロセス間通信
  13. デッドロック・飢餓・レースコンディション
  14. メモリ管理
  15. ファイルシステムとI/O
  16. ストレージ管理とRAID
  17. デバイス管理とドライバ
  18. ネットワーキング
  19. セキュリティ
  20. 仮想化
  21. コンテナ技術
  22. デスクトップOSの詳細比較
  23. モバイルOS
  24. リアルタイムOSと組み込みOS
  25. 分散OS・クラウドOS
  26. OSのパフォーマンス分析とチューニング
  27. OSの歴史
  28. 現代的トレンドと将来展望
  29. 実践リファレンス
  30. 参考資料

OSの定義と哲学

初心者向けメモ
OS とは何かを「教科書的定義」と「実用上の役割」の両方から把握する章です。ここでは「リソース管理者」「ハードウェア抽象化層」「仮想マシン提供者」の3つの視点で OS を捉えます。

形式的定義

Silberschatz は OS を次のように定義している:

“An operating system is a program that manages the computer hardware. It also provides a basis for application programs and acts as an intermediary between the computer user and the computer hardware.”

Tanenbaum はよりプラグマティックに、OS を「拡張機械(Extended Machine)」と「リソース管理者(Resource Manager)」の二重の観点から定義する。

  • 拡張機械としてのOS:生のハードウェア(レジスタ、割り込み、DMA、ディスクジオメトリ)は複雑で危険なため、OS はこれらを抽象化し、プログラマが扱いやすい「仮想計算機」を提供する。read(fd,buf,n)read(fd, buf, n) というシステムコールは、内部的にはセクタ計算、キャッシュ参照、DMA設定、割り込み待機を経て実行されるが、プログラマからは単なる関数呼び出しに見える。
  • リソース管理者としてのOS:複数の競合するプロセスが CPU、メモリ、I/O を共有する際、公平性・効率・保護を担保するのが OS の責務である。

三位一体の役割

graph TB A["オペレーティングシステム"] B["リソース管理者"] C["ハードウェア抽象化層"] D["仮想マシン提供者"] A --> B A --> C A --> D B --> B1["CPU時間の配分(スケジューリング)"] B --> B2["メモリ割り当て(仮想メモリ・ページング)"] B --> B3["ディスク/ストレージ管理(ファイルシステム)"] B --> B4["I/O制御(デバイスドライバ、割り込み)"] B --> B5["ネットワーク帯域制御(QoS)"] C --> C1["複雑さの隠蔽(システムコール)"] C --> C2["統一インターフェース(POSIX、Win32)"] C --> C3["ポータビリティ(HAL、KMI)"] D --> D1["独立した仮想アドレス空間"] D --> D2["プロセス間の隔離と保護"] D --> D3["時分割による並行性の幻想"]

OSの設計哲学

UNIX哲学は現代OSの根幹を形作っている:

  1. Do one thing and do it well — ツールは一つのことを上手にやる。
  2. Write programs to work together — プログラムは協働できるよう設計する(パイプ)。
  3. Handle text streams as universal interface — テキストストリームをユニバーサルなインターフェースとする。
  4. Everything is a file — すべてはファイルである(デバイス、ソケット、プロセス情報まで)。

この哲学は Linux、macOS (XNU/Darwin)、BSD 系、さらには Android にまで受け継がれている。一方 Windows は COM/OLE/NT Object Manager に代表される「すべてはオブジェクトである」という異なる抽象を採用している。

なぜOSが必要か — 歴史的動機

1950年代、初期コンピュータ(ENIAC、EDSAC)にはOSが存在しなかった。プログラムはバイナリとして直接ロードされ、プログラマがハードウェアを手作業で制御した。1960年代にバッチ処理システム(FMS, IBSYS)が登場し、1969年の Unix 誕生で「マルチユーザー・マルチタスキング・階層ファイルシステム」が一般化した。OS が必要とされたのは以下の技術的圧力による:

  • ハードウェア利用率:人間のオペレータが磁気テープを装填していた時代、CPU 利用率は 1% 未満だった。バッチ処理とスプーリングでこれを劇的に改善する必要があった。
  • 多重プログラミング:I/O 待ち中に CPU が遊ぶのを避けるため、複数プログラムを同時にメモリに載せる仕組みが必要となった。
  • 保護:共有環境で一つのプログラムが他を破壊しないよう、ハードウェアとソフトウェアによる保護機構が必要となった。
  • 利便性:パンチカードや磁気テープの直接操作は誤りが多く、ファイル・ディレクトリといった抽象が不可欠だった。

OSの主要機能

初心者向けメモ
OS が提供する機能は 10 以上ありますが、「プロセス」「メモリ」「ファイル」「I/O」「ネットワーク」の 5 つを押さえればほぼ全体像が見えます。

1. プロセス管理(Process Management)

OS はプロセスの生成・終了・状態遷移・スケジューリング・プロセス間通信を管理する。Linux では fork()exec()wait()exit() という古典的な UNIX API に加え、clone()posixspawn()posix_spawn()vfork()、さらに名前空間を扱う unshare()setns() がある。Windows では CreateProcess()WaitForSingleObject() など独自 API を用いる。

2. メモリ管理(Memory Management)

仮想メモリシステム、ページング、スワッピング、メモリ保護、共有メモリを担う。現代OSは以下のような階層化されたメモリ管理を行う:

役割 代表的技術
MMU 仮想→物理変換 ページテーブル、TLB、EPT、Intel PML5
カーネル層 ページ割り当て、回収 バディ、スラブ、SLUB、LRU list
プロセス層 仮想アドレス空間管理 VMA (vm_area_struct)、mmap
ランタイム層 ヒープ管理 malloc (ptmalloc2, jemalloc, tcmalloc, mimalloc)

3. ファイルシステム・ストレージ管理

ファイルの作成・読み書き・メタデータ管理・アクセス制御、ディスクスペースの割り当て、ジャーナリング、暗号化、スナップショットなど。Linux では VFS (Virtual File System) 抽象により、ext4、XFS、Btrfs、ZFS、NFS、FUSE など多様な実装を統一的に扱う。

4. 入出力管理(I/O Management)

デバイスドライバ、割り込みハンドラ、バッファリング、スプーリング、非同期I/O (AIO, io_uring, IOCP)、DMA の制御。ここで スプーリング は「すぐ処理できない入出力要求をいったんキューにためること」、DMA は「CPU を介さずにデバイスがメモリへ直接読み書きすること」を指す。Linux カーネルでは block layer、net layer、char device という区分でドライバが組織化される。

5. ネットワーキング

TCP/IP スタック、ソケットAPI、ルーティング、パケットフィルタリング(Netfilter, eBPF, pf)、QoS、仮想ネットワーク(VLAN, VXLAN, overlay)。ここで VLAN は 1 本の物理ネットワークを論理的に分割する仕組み、VXLAN はその仮想ネットワークを IP 網の上にトンネルとして重ねる仕組みである。Linux の Netfilter はカーネル内パケットフィルタ基盤で、iptablesnftables はその上でルールを定義するための仕組みである。

6. セキュリティと保護

認証(PAM, Kerberos)、認可(DAC, MAC, RBAC, ABAC)、監査(auditd, ETW)、暗号化(dm-crypt, BitLocker, FileVault, APFS encryption)、サンドボックス(seccomp, AppArmor, SELinux, Windows AppContainer)。認可方式のうち DAC は所有者が権限を決める方式、MAC は OS 側の強制ルールで制御する方式、RBAC は役割ベース、ABAC は属性ベースの制御である。

7. ユーザーインターフェース

CLI(bash, zsh, fish, PowerShell, cmd)、GUI(X11, Wayland, Quartz Compositor, Windows DWM)、API(POSIX, Win32, Cocoa/UIKit)という三層のインターフェースを提供する。たとえば Wayland は Linux 系の新しい表示プロトコル、Quartz Compositor は macOS の画面合成基盤、DWM は Windows の Desktop Window Manager である。

8. 時刻管理とタイマ

クロックソース(TSC, HPET, ACPI PM Timer, ARM Generic Timer)、タイマ(hrtimer, timerfd, CreateTimerQueue)、NTP 同期、タイムゾーン、うるう秒処理。ここで TSC は CPU 内部の高速カウンタ、HPET は高精度イベントタイマで、OS は用途に応じて使い分ける。RTOSではナノ秒オーダーの確定的タイマが要求される。

9. 電源管理

ACPI(Advanced Configuration and Power Interface)、CPU 周波数スケーリング(cpufreq, Intel P-state)、サスペンド/ハイバーネーション(S3/S4)、モバイルOSでの Doze モード、iOS Background App Refresh 制御など。ACPI は電源管理やデバイス構成を OS とファームウェアの間で受け渡す標準仕様で、Intel P-state は CPU の性能状態を細かく調整する仕組みである。

10. エラーハンドリング・ログ・診断

例外処理、パニック/BSoD、クラッシュダンプ、カーネルログ(dmesg, journald, Event Viewer, Console.app)、トレーシング(ftrace, eBPF, DTrace, ETW, os_log)、プロファイリング(perf, Instruments, WPA)。


OSのアーキテクチャ

初心者向けメモ
「モノリシック」「マイクロカーネル」「ハイブリッド」の3つが主要パターンです。Linux はモノリシック、macOS/Windows はハイブリッドという程度を押さえれば十分です。

OS カーネルの設計は歴史上、複数の異なる哲学のもとで発展してきました。性能・信頼性・保守性・セキュリティのトレードオフが異なります。

1. モノリシックカーネル(Monolithic Kernel)

すべてのOSサービス(メモリ管理、プロセス管理、ファイルシステム、デバイスドライバ、ネットワーク)が単一のアドレス空間で特権モード実行される。

【図1】モノリシックカーネルの構造:

graph TB Apps["ユーザアプリケーション"] subgraph Kernel["モノリシックカーネル(全機能が単一アドレス空間)"] PM["プロセス管理"] MM["メモリ管理"] FS["ファイルシステム"] DD["デバイスドライバ"] NS["ネットワークスタック"] IH["割り込みハンドラ"] IPC["IPC"] CR["暗号化"] end HW["ハードウェア"] Apps -.システムコール.-> Kernel Kernel -.関数コール・直接参照.-> HW

長所:

  • 関数呼び出しで全機能にアクセス可能 → 極めて高速
  • キャッシュ効率が良い
  • 実装が単純明快(大まかには)

短所:

  • 一つのバグ(NULL ポインタ参照、メモリ破壊)がカーネル全体をクラッシュさせる
  • デバイスドライバはカーネル空間で動くため、品質の悪いドライバが致命的
  • コード量が増すと保守が困難(Linux は既に 3,000 万行超)

代表例: Linux、FreeBSD、OpenBSD、NetBSD、クラシックUnix、MS-DOS

Linux は厳密にはモノリシックだが、**ローダブルカーネルモジュール(LKM)**による動的拡張をサポートし、モジュラモノリシック(modular monolithic)と呼ばれる。LKM は「あとから差し込めるカーネル部品」のようなもので、起動時に必要最低限のカーネルしかメモリに置かず、modprobe で実行時にドライバをロードする。

2. マイクロカーネル(Microkernel)

カーネルは最小限の機能(IPCスレッド管理、基本的メモリ管理、タイマ)のみを実装し、ファイルシステム・ネットワーク・デバイスドライバはユーザースペースの サーバプロセス として実行する。IPC(Inter-Process Communication) はプロセス間通信のことで、メッセージ送受信や共有メモリなどを通じて別プロセス同士が連携する仕組みを指す。

【図2】マイクロカーネル構造:

この図では、「特権の小さいマイクロカーネル」と「ユーザ空間のサーバ群」が IPC でつながる、という分離のしかたを見る。

graph TB subgraph UserSpace["ユーザースペース(特権なし)"] FS["ファイルサーバ"] Net["ネットワークサーバ"] DD["デバイスドライバ"] App["アプリプロセス"] end subgraph Micro["マイクロカーネル(最小限の特権)"] IPC["IPC / メッセージパッシング"] SM["スレッド・アドレス空間プリミティブ"] IR["ハードウェア割り込みルーティング"] end HW["ハードウェア"] FS <-.IPC.-> IPC Net <-.IPC.-> IPC DD <-.IPC.-> IPC App <-.IPC.-> IPC Micro --> HW

長所:

  • 信頼性:一つのサーバが落ちても他は生存し、再起動で復旧可
  • セキュリティ:特権コードが小さく監査しやすい(seL4 は形式検証済み)
  • モジュール性:サーバを独立して開発・交換可能
  • マルチサーバ・分散化との親和性

短所:

  • IPC オーバーヘッド:関数呼び出しがメッセージ送受信になり、コンテキストスイッチが頻発
  • 初期のマイクロカーネル(Mach 2.5)は性能で悪評を得た
  • 単純なファイルI/Oでも複数のコンテキストスイッチが発生

代表例:

  • QNX Neutrino:自動車(CarPlay相互運用、BMW iDrive等)、医療機器
  • Minix 3:Tanenbaum が教育・研究用に開発、Intel ME(Management Engine)にも採用された
  • seL4:C 実装と仕様の整合性を大規模に形式検証した、代表的なマイクロカーネル
  • GNU Hurd:長年開発中の GNU マイクロカーネル
  • L4 系統(L4, Fiasco, NOVA, Pistachio, OKL4)

3. ハイブリッドカーネル(Hybrid Kernel)

モノリシックとマイクロカーネルの中間。Mach 的な IPC・メッセージパッシングをカーネル内部構造として持ちつつ、性能のためファイルシステムやネットワークもカーネル空間に取り込む。

代表例:

  • Windows NT(Windows 2000/XP/Vista/7/8/10/11 の基盤)— NT カーネル + Executive + サブシステム
  • macOS / iOS / iPadOS / watchOS / tvOS(XNU = “X is Not Unix”)— Mach + BSD + I/O Kit
  • BeOS / Haiku
  • ReactOS(Windows NT 互換のオープンソース)

【図3】XNU の内部構造:

この図では、macOS / iOS の XNU が MachBSDI/O Kit を重ね合わせたハイブリッド構造になっている点を見る。

graph TB subgraph XNU["XNU Kernel"] BSD["BSD 層 / POSIX API、プロセス、VFS、ソケット"] Mach["Mach 層 / タスク、スレッド、IPC、VM"] IOKit["I/O Kit / C++ ドライバフレームワーク"] LK["libkern / Platform Expert / C++ ランタイム、アーキ固有"] end BSD --- Mach Mach --- IOKit IOKit --- LK

【図4】Windows NT の内部構造:

この図では、Windows がユーザモードのサブシステムと Executive 群、さらに HAL を分けている点に注目すると把握しやすい。

graph TB UM["ユーザモード(サブシステム) / Win32, POSIX, WSL, OS/2(歴代), WinRT / smss.exe, csrss.exe, services.exe, lsass.exe"] EX["Executive(カーネルモード) / Object Manager, Process Manager, Memory Manager / I/O Manager, Security Reference Monitor / Configuration Manager, Cache Manager"] MK["Microkernel (ntoskrnl.exe) / スレッドスケジューリング、割り込み、例外、DPC"] HAL["HAL (Hardware Abstraction Layer)"] HW["ハードウェア"] UM -.NtXxx システムコール.-> EX EX --> MK MK --> HAL HAL --> HW

4. 層型カーネル(Layered Kernel)

Dijkstra の THE OS (1968) が提唱した設計。各層が下位層のみを呼び出し、逆方向の依存を禁止する。

【図5】層型カーネル(THE OS):

graph TB L5["Layer 5: ユーザープログラム"] L4["Layer 4: I/O バッファリング"] L3["Layer 3: オペレータコンソールデバイスドライバ"] L2["Layer 2: メモリ管理"] L1["Layer 1: CPU スケジューリング"] L0["Layer 0: ハードウェア"] L5 --> L4 --> L3 --> L2 --> L1 --> L0

教育的価値は高いが、層の厳密な区切りが実装と性能を犠牲にするため、純粋な層型OSは現代では稀。ただし MulticsOS/2 は層型の影響を強く受けた。

5. エクソカーネル(Exokernel)

MIT の Frans Kaashoek らが 1990年代に提唱。「カーネルは抽象化を提供せず、物理リソースへの保護された直接アクセスのみを提供する」という極端な設計哲学。ファイルシステムやネットワークプロトコルはユーザライブラリ(libOS)として実装される。

意図: アプリケーションが自分に最適な抽象を選べるようにする。DB サーバは専用ファイルシステム libOS を使い、Web サーバは独自 TCP スタックを使える。

代表例: MIT Exokernel(XOK, Aegis, ExOS)、Nemesis(Cambridge)。商用成功には至らなかったが、UnikernelUser-mode drivers、さらには io_uring のゼロコピー設計に思想的影響を残した。

6. ユニカーネル(Unikernel)

アプリケーション・ランタイム・OS カーネルを単一のバイナリにコンパイルし、ハイパーバイザ上で直接動作させる。プロセス分離もユーザ/カーネルモードもない — 一つのアドレス空間に全てが存在する。

代表例: MirageOS(OCaml)、IncludeOS(C++)、HalVM(Haskell)、Rumprun、OSv、Solo5。

利点: 起動時間が短く、攻撃表面が小さく、バイナリサイズやメモリ使用量も抑えやすい。軽量 VM やサーバレス実行基盤と設計上の問題意識が近く、特に Firecracker のようなマイクロ VM 系の文脈で比較対象として語られることが多い。なお、Cloudflare Workers は unikernel ではなく V8 Isolate ベースである。

7. マルチカーネル(Multikernel) / 分散OS

Barrelfish(ETH Zurich × Microsoft Research)は、NUMA やヘテロ構成のメニーコア時代に向けて「コア間で状態を共有せず、メッセージパッシングのみで協調する分散OS」を提案。マルチコア時代のスケーラビリティ課題への応答。

8. アーキテクチャ比較マトリックス

アーキテクチャ 性能 信頼性 保守性 セキュリティ 代表例
モノリシック ★★★★★ ★★ ★★ ★★★ Linux, BSD
マイクロカーネル ★★★ ★★★★★ ★★★★ ★★★★★ QNX, Minix, seL4
ハイブリッド ★★★★ ★★★★ ★★★ ★★★★ Windows NT, XNU
層型 ★★ ★★★ ★★★★ ★★★ THE, Multics
エクソカーネル ★★★★★ ★★★ ★★ ★★★★ XOK, Nemesis
ユニカーネル ★★★★★ ★★★ ★★ ★★★★ MirageOS, IncludeOS

カーネルモードとユーザーモード

現代CPUは少なくとも二つの特権レベル(プロテクションリング)を提供し、OS はこれを利用して自身と他プロセスを保護する。x86-64 は Ring 0〜Ring 3 の4段階を提供するが、実際は Ring 0(カーネル)と Ring 3(ユーザ)しか使われない。ARM は EL0(ユーザ)〜EL3(Secure Monitor / TrustZone)まで4レベル。RISC-V は M / S / U モード。

特権レベルの意味

stateDiagram-v2 [*] --> ユーザモード ユーザモード --> カーネルモード: システムコール (syscall/int 0x80) ユーザモード --> カーネルモード: 割り込み (タイマ、I/O) ユーザモード --> カーネルモード: 例外 (ページフォルト、SIGSEGV) カーネルモード --> ユーザモード: sysret / iret note right of ユーザモード: 特権命令禁止 ハードウェアI/O禁止 ページテーブルで制限 note right of カーネルモード: 全特権命令実行可 全物理メモリアクセス可 直接アクセス可

ユーザモードで禁止される代表的な命令(x86-64):

  • HLT(CPUハルト)
  • CLI/STI(割り込みフラグ制御)
  • IN/OUT(I/Oポート直接アクセス)
  • INVLPG(TLB無効化)
  • LGDT/LIDT(記述子テーブルロード)
  • WRMSR/RDMSR(一部の MSR アクセス)
  • CR0/CR3/CR4 などの制御レジスタへの書き込み

これらを実行しようとするとユーザモードでは一般保護例外(#GP)が発生し、カーネルが SIGILL や SIGSEGV を送出する。

モード遷移のコスト

モード切替(ユーザ→カーネル→ユーザ)は単なるジャンプではなく、レジスタ保存、スタック切替、場合によっては TLB や分岐予測器のフラッシュを伴う。典型的な syscall のオーバーヘッドは 100〜500 ns 程度だが、Meltdown/Spectre 脆弱性対策(KPTI: Kernel Page-Table Isolation) を有効にすると倍増することがある。

この遷移コストを避ける工夫:

  • vDSO(Virtual Dynamic Shared Object):Linux で gettimeofday()clockgettime()clock_gettime()getcpu() などの頻繁に呼ばれる関数をユーザ空間にマップし、カーネルに遷移せず実行する。
  • io_uring:システムコール境界を跨がない共有リングバッファでI/Oを発行・完了通知する。
  • eBPF:小さなサンドボックスプログラムをカーネル内で実行し、ユーザ空間に戻る頻度を減らす。
  • ユーザ空間ドライバ(DPDK, SPDK):NIC や NVMe を直接ユーザ空間にマップし、カーネルを通さずパケット・I/Oを処理する。

システムコールとABI

システムコール(syscall)は、ユーザプログラムがカーネルに処理を依頼するための公式インターフェースである。

Linux x86-64 の syscall 規約

x86-64 では、Linux は syscall 命令を使う新しい規約を採用している:

レジスタ 用途
RAX システムコール番号(例:read = 0、write = 1、openat = 257)
RDI 第1引数
RSI 第2引数
RDX 第3引数
R10 第4引数(関数呼び出し規約とは異なるので注意)
R8 第5引数
R9 第6引数
RAX(戻り値) 返り値、負数はエラー(-errno)

例:write(1, "hello\n", 6) を直接 syscall で呼ぶ x86-64 アセンブリ:

    mov rax, 1          ; syscall number: write
    mov rdi, 1          ; fd: stdout
    lea rsi, [rel msg]  ; buf
    mov rdx, 6          ; count
    syscall             ; kernel に制御を移す

msg: db "hello",0x0a

システムコール数

  • Linux 6.x(x86-64):約 450 種類
  • FreeBSD 14:約 580 種類
  • macOS(XNU):数百(BSD syscalls + Mach traps + machine-dependent)
  • Windows NT Native API:約 450 種類(NtCreateFile など)

Linux のシステムコール一覧は /usr/include/asm/unistd64.h/usr/include/asm/unistd_64.hman 2 syscalls で確認できる。

POSIX とABI

**POSIX(Portable Operating System Interface)**は IEEE が制定するUnix系OSの標準API。POSIX.1 は基本API(fork, exec, open, read, write)を、POSIX.1b はリアルタイム拡張(schedsetschedulersched_setscheduler, shmopenshm_open)を、POSIX.1c は pthread をカバーする。

ABI(Application Binary Interface)ISA・OSごとに異なり、関数呼び出し規約・システムコール規約・構造体レイアウト・実行ファイル形式(ELF, Mach-O, PE)を定める。同じOSでも ABI が異なれば実行できない(Linux x86-64 と Linux ARM64 は互換性なし)。

高速呼び出し機構の進化

  1. int 0x80(i386 時代)— ソフトウェア割り込み。遅い。
  2. SYSENTER/SYSEXIT(Pentium II、Intel)— 専用命令で高速化。
  3. SYSCALL/SYSRET(AMD64、Intel 64)— 現代のx86-64で標準。
  4. vDSO(上述)— 一部システムコールをユーザ空間で完結。
  5. io_uring(Linux 5.1, 2019)— バッチ化された非同期I/O。

Linuxアーキテクチャの詳細

Linux は1991年にフィンランドのヘルシンキ大学の学生 Linus Torvalds によって開発開始された。現在の Linux カーネルは世界最大級のオープンソースプロジェクトであり、おおむね次のような規模感で語られる。

  • ソースコード:数千万行規模
  • コントリビュータ:長期累計で非常に多数
  • リリース頻度:9〜10週間ごと
  • メンテナ:Linus Torvalds が BDFL、各サブシステムに lieutenants
  • 開発言語:C(主)、アセンブリ、Rust(2022年より部分的に導入)

Linuxシステムの階層

【図6】Linuxシステムの階層構造:

graph TB App["ユーザアプリケーション / Firefox, Vim, Python, Nginx, Docker, etc."] Lib["システムライブラリ / glibc, musl, libstdc++, libssl, libcrypto"] subgraph Kernel["Linux カーネル"] PM["プロセス管理"] MM["メモリ管理"] VFS["仮想ファイルシステム (VFS)"] NS["ネットワークスタック"] IPC["IPC"] SEC["セキュリティ (LSM)"] DD["デバイスドライバ・カーネルモジュール"] end HW["ハードウェア / CPU, RAM, ディスク, NIC, GPU, 周辺機器"] App -.ライブラリコール.-> Lib Lib -.システムコール.-> Kernel Kernel --> HW

主要サブシステム

1. プロセス・スケジューラ (kernel/sched/)

Linux 2.6.23以降は CFS(Completely Fair Scheduler) が通常プロセスをスケジュールしてきた。CFS は赤黒木で “virtual runtime (vruntime)” をキーにプロセスを順序付け、最小 vruntime を持つプロセスを次に実行する。

Linux 6.6(2023年10月)からは EEVDF(Earliest Eligible Virtual Deadline First)スケジューラ が CFS を置き換えた。EEVDF は Peter Zijlstra 博士らによって実装され、リクエスト遅延の予測可能性を向上させる。

リアルタイムプロセスは SCHEDFIFOSCHED_FIFOSCHEDRRSCHED_RRSCHEDDEADLINESCHED_DEADLINE の各ポリシーで別系統にスケジュールされる。

2. メモリ管理 (mm/)

  • バディアロケータ:物理ページを2の冪乗サイズで管理。
  • スラブアロケータ(SLAB/SLUB/SLOB):小さなオブジェクトを効率的に管理。Linux では SLUB が標準。
  • デマンドページングスワップページキャッシュTransparent Huge Pages(THP)NUMA policymemcg (cgroup memory controller)
  • mmapbrk/sbrkmremapmadvise

3. 仮想ファイルシステム (VFS, fs/)

Sun Microsystems が1985年に NFS のため導入した設計を Linus が採用。struct inodestruct dentrystruct filestructsuperblockstruct super_block が抽象化の核となる。これにより ext4、XFS、Btrfs、ZFS、NFS、FUSE、tmpfs、procfs、sysfs、debugfs、cgroupfs が統一 API で利用可能。

4. ネットワークスタック (net/)

  • L2〜L4(Ethernet / IP / TCP / UDP / SCTP / DCCP)
  • Netfilter(iptables、nftables、conntrack)
  • Netlink ソケット(ユーザ空間↔カーネル通信)
  • XDP(eXpress Data Path)— NIC ドライバ直下で eBPF を動かし超低遅延
  • io_uring ネットワーク操作
  • TLS offload(kTLS)

5. ブロック層 (block/, drivers/md/)

  • I/O スケジューラ:mq-deadline、kyber、bfq、none
  • マルチキュー block layer(blk-mq)
  • Device Mapper(LVM、dm-crypt、dm-raid)
  • md(ソフトウェア RAID)

6. デバイスドライバ (drivers/)

カーネルソースの過半を占める最大サブシステム。USB、PCI、SCSI、NVMe、ネットワーク、グラフィックス(DRM/KMS)、サウンド(ALSA)、入力(evdev)など。

7. セキュリティ (LSM: Linux Security Module)

フック型のセキュリティ拡張機構。SELinuxAppArmorTOMOYOYamaLandlockSMACK などの「スタック可能な」セキュリティモジュールを挿入できる。

Linux ディストリビューション

Linux カーネル単体では OS として動かない。シェル、ユーティリティ、パッケージマネージャ、デスクトップ環境などを組み合わせた ディストリビューション が「ユーザが使うLinux」である。

【図7】主要 Linux ディストリビューション系統図:

graph LR Linux["Linux カーネル"] Linux --> Debian["Debian 系"] Linux --> RH["Red Hat 系"] Linux --> Arch["Arch 系"] Linux --> SUSE["SUSE 系"] Linux --> Others["その他"] Debian --> DebianD["Debian"] Debian --> Ubuntu["Ubuntu"] Ubuntu --> Mint["Linux Mint"] Ubuntu --> Pop["Pop!_OS"] Ubuntu --> Flavors["Kubuntu / Xubuntu / Lubuntu"] Ubuntu --> Ele["elementary OS"] Debian --> Kali["Kali Linux"] RH --> Fedora["Fedora"] RH --> RHEL["RHEL"] RH --> CentOS["CentOS Stream"] RH --> Rocky["Rocky / AlmaLinux"] RH --> AWS["Amazon Linux"] Arch --> ArchL["Arch Linux"] Arch --> Manjaro["Manjaro"] Arch --> Endeavour["EndeavourOS"] SUSE --> openSUSE["openSUSE"] SUSE --> SLES["SLES"] Others --> Gentoo["Gentoo"] Others --> Slack["Slackware"] Others --> Nix["NixOS"] Others --> Alpine["Alpine"] Others --> Android["Android"]

コアコンポーネント

カーネル(Kernel)

OSの中核。ハードウェアに直接触れる最も特権的なソフトウェア。カーネルが提供する主要サービスは以下に集約される。

mindmap root((カーネル)) CPU管理 スケジューリング プロセス生成・終了 コンテキストスイッチ 割り込み処理 メモリ管理 仮想メモリ ページング スワップ メモリ保護 NUMA I/O管理 デバイスドライバ 割り込みハンドラ DMA ブロック層 キャラクタ層 ファイルシステム VFS ext4/xfs/btrfs ジャーナリング ページキャッシュ ネットワーク TCP/IP ソケット Netfilter eBPF/XDP セキュリティ LSM ユーザ/グループ/UID Capabilities 名前空間 cgroups IPC パイプ シグナル 共有メモリ セマフォ メッセージキュー ソケット

シェル(Shell)

シェルはユーザとカーネルの仲介者。コマンド解析、変数展開、ワイルドカード展開(グロブ)、ヒストリ、ジョブ制御、パイプ/リダイレクト、関数定義、スクリプト実行を担う。

シェル 起源 特徴 デフォルト採用例
sh (Bourne Shell) 1977, AT&T POSIX 標準 /bin/sh(多くの最小環境)
bash (Bourne Again Shell) 1989, GNU sh 拡張、豊富な機能 Linux 多数、macOS 〜10.14
csh / tcsh 1978 C 風文法 FreeBSD の root
ksh (Korn Shell) 1983 先進的機能 AIX、Solaris
zsh 1990 補完強化、テーマ(Oh My Zsh) macOS 10.15〜、Kali
fish 2005 初心者向け、設定不要で高機能 ポータブル
PowerShell 2006, Microsoft オブジェクト指向、.NET 統合 Windows、クロスプラットフォーム
cmd.exe 1987 Windows 伝統 Windows
nushell 2019, Rust製 構造化データ指向 モダン代替

システムライブラリ

glibc(GNU C Library)

Linux の標準 C ライブラリ。POSIX・ISO C・XSI 準拠の API を提供し、システムコールのラッパ(open, read, fork, pthreadcreatepthread_create など)、文字列操作、数学関数、ロケール、DNS レゾルバ、ダイナミックローダ(ld-linux.so)を含む。

主要な派生/代替:

  • musl libc:軽量・簡潔、Alpine Linux で採用。
  • uClibc / uClibc-ng:組み込み向け。
  • Bionic:Android 用 libc(glibc ではなく、BSD ベース)。
  • Newlib:RTOS 向け。
  • ucrt (Universal CRT):Windows 10 以降の CRT。

C++ 標準ライブラリ

libstdc++(GNU)、libc++(LLVM)、Microsoft STL。C++20/23 の <thread><thread><atomic><atomic><filesystem><filesystem><coroutine><coroutine> などを提供。

その他重要ライブラリ

  • libssl / libcrypto(OpenSSL、LibreSSL、BoringSSL)
  • libcurllibnghttp2
  • zlibliblzmalibzstd(圧縮)
  • libX11libwayland-client(GUI)
  • systemd クライアントライブラリ(libsystemd)

システムユーティリティとデーモン

Linux の典型的な常駐プロセス:

flowchart TB S["systemd (PID 1) init プロセス (カーネルの親)"] S --> J["systemd-journald 構造化ログ"] S --> U["systemd-udevd デバイスホットプラグ"] S --> L["systemd-logind ユーザセッション管理"] S --> N["systemd-networkd ネットワーク設定"] S --> R["systemd-resolved DNS"] S --> T["systemd-timesyncd NTP (簡易)"] S --> NM["NetworkManager ネットワーク管理 (GUI系)"] S --> SSH["sshd SSH サーバ"] S --> C["cron / systemd.timer 定期実行"] S --> RS["rsyslog 伝統的 syslog"] S --> CU["cups 印刷"] S --> A["avahi-daemon mDNS (Bonjour)"] S --> B["bluetoothd Bluetooth"] S --> P["pulseaudio / pipewire オーディオ"] S --> X["X11 / Wayland compositor GUI"] S --> PD["polkit / dbus 権限・バス"] S --> CT["containerd / dockerd コンテナ"]

macOS では launchd(PID 1)がこれらをすべて統合している。Windows では services.exe がサービスマネージャを担う。


ブートプロセスと初期化

電源ボタンを押してからログインプロンプトが現れるまで、OS は複雑な一連の初期化を行う。

UEFI ブートの流れ(現代的 x86-64 PC)

この図では、「ファームウェア → ブートローダ → カーネル → init/systemd」という主な責務の受け渡しを見る。

sequenceDiagram participant PSU as 電源 participant CPU as CPU participant UEFI as UEFI Firmware participant ESP as EFI System Partition participant GRUB as GRUB2 bootloader participant Kernel as Linux Kernel participant systemd as systemd PSU->>CPU: 電源ON、リセット解除 CPU->>UEFI: リセットベクタから実行 UEFI->>UEFI: POST(Power-On Self Test) UEFI->>UEFI: ハードウェア初期化(RAM、PCIe) UEFI->>ESP: /EFI/BOOT/BOOTX64.EFI 読み込み UEFI->>GRUB: 制御移行 GRUB->>GRUB: メニュー表示、設定読み込み GRUB->>Kernel: vmlinuz、initramfs ロード Kernel->>Kernel: アーキ初期化、MMU 有効化 Kernel->>Kernel: ドライバ読み込み、ファイルシステムマウント Kernel->>systemd: /sbin/init (=systemd) 実行 systemd->>systemd: unit file 読み込み、サービス起動 systemd->>systemd: target 達成(multi-user.target, graphical.target)

詳細フェーズ

Phase 1: ファームウェア(UEFI / BIOS)

  • BIOS(Basic Input/Output System、1981〜):16bit リアルモードで起動、512バイトの MBR を読み込む。現代ではレガシー扱い。
  • UEFI(Unified Extensible Firmware Interface、2005〜):モジュラー、GPT パーティション対応、セキュアブート、ネットワーク起動、GUI 提供、Boot Manager を内蔵。ARM、x86-64、RISC-V で標準。
  • Coreboot / LinuxBoot:オープンソースファームウェア。Google Chromebook で採用。

Phase 2: ブートローダ

ブートローダ 対象 特徴
GRUB2 Linux 主流 マルチブート、スクリプト
systemd-boot Linux モダン シンプル、UEFIネイティブ
rEFInd Mac マルチブート UEFI グラフィカル
Windows Boot Manager (bootmgr) Windows BCD 設定
iBoot iPhone/iPad SecureBoot
bootrom + iBSS + iBEC iOS 多段階チェーン
U-Boot 組み込み ARM, RISC-V 定番
SYSLINUX / ISOLINUX / PXELINUX 特殊用途 ライブCD、PXE ブート

ここで ESP(EFI System Partition) は UEFI 用の起動ファイルを置く専用パーティション、initramfs は本番のルートファイルシステムをマウントする前に一時的に使う最小 Linux 環境である。

Phase 3: カーネルのロードと初期化

  1. 展開vmlinuz は通常 gzip/xz/zstd 圧縮された bzImage で、先頭の decompressor が自身を展開する。
  2. アーキテクチャ初期化arch/x86/boot/compressed/head64.Sarch/x86/boot/compressed/head_64.Sstartkernel()start_kernel() へ。
  3. メモリマップ取得:e820 テーブル(BIOS)または EFI memory map から物理メモリを把握。
  4. ページテーブルセットアップ:Identity mapping → カーネル仮想アドレス空間構築。
  5. startkernel()start_kernel()(init/main.c):各サブシステム初期化 — スケジューラ、割り込み、RCU、タイマ、コンソール、rest_init()、kernel_init スレッド起動。
  6. initramfs:一時ルートファイルシステム。ドライバをロードし、真のルートを見つけてマウント。
  7. init プロセスの起動:PID 1 として /sbin/init(systemd、OpenRC、SysV init)を exec

Phase 4: ユーザ空間初期化(systemd)

systemd は依存関係グラフで並列にサービスを起動する。主な単位:

  • .service — サービス(デーモン)
  • .target — グループ化(ランレベル相当:graphical.targetmulti-user.targetrescue.target)
  • .socket — ソケット起動
  • .timer — cron 代替
  • .mount / .automount — ファイルシステム
  • .path — パス監視による起動
  • .slice — cgroup ツリー

macOS のブート

Power On
  → Boot ROM (UEFI 互換、Apple Silicon では iBoot)
  → LLB (Low-Level Bootloader)
  → iBoot
  → Kernel Cache (prelinkedkernel / immutablekernel)
  → XNU (Mach + BSD)
  → launchd (PID 1)
  → System Services (mDNSResponder, WindowServer, loginwindow)
  → ユーザログイン → Finder, Dock, SystemUIServer

Apple Silicon(M1/M2/M3/M4)では Secure Enclave、Boot Policy、Signed System Volume(SSV)による厳格なセキュアブート。LocalPolicy に署名されない限り実行不可。

Windows のブート

Power On
  → UEFI firmware
  → Windows Boot Manager (bootmgfw.efi)
  → winload.efi(OS loader)
  → NTOSKRNL.EXE(カーネル)
  → HAL、ドライバ(BOOT_START)
  → Session Manager (smss.exe, PID 4)
  → Local Security Authority (lsass.exe)
  → Win Logon (winlogon.exe)
  → Service Control Manager (services.exe)
  → ログイン → explorer.exe

プロセス管理

初心者向けメモ
プロセスは「実行中のプログラム」です。複数のプロセスが同時に動いて見えるのは、OS が高速で切り替えて(コンテキストスイッチ)いるからです。

プロセスとは

プロセス は実行中のプログラムの動的実体であり、以下を保持する:

  • アドレス空間:テキスト(コード)、データ、BSS、ヒープ、スタック、メモリマップ領域
  • 実行コンテキスト:レジスタ(PC、SP、汎用、浮動小数点、SIMD)、モード情報
  • リソース:オープンファイル(ファイルディスクリプタ)、ソケット、シグナルマスク
  • プロパティ:PID、PPID、UID/GID、優先度、CPU 時間、作業ディレクトリ、環境変数
  • 状態:実行中、実行可能、ブロック中、停止中、ゾンビ

Linux のプロセス構造体 taskstructtask_struct

include/linux/sched.h に定義された、Linux で最大級の構造体(数千行、1万行超のこともある)。主要フィールド:

struct task_struct {
    unsigned int            __state;        // TASK_RUNNING, TASK_INTERRUPTIBLE, ...
    pid_t                   pid, tgid;      // PID とスレッドグループID
    struct task_struct      *parent;
    struct list_head        children, sibling;
    struct mm_struct        *mm;            // メモリ記述子(ページテーブル等)
    struct fs_struct        *fs;            // ルート/作業ディレクトリ
    struct files_struct     *files;         // ファイルディスクリプタテーブル
    struct signal_struct    *signal;
    struct sighand_struct   *sighand;
    const struct cred       *cred;          // UID/GID/capabilities
    struct sched_entity     se;             // CFS/EEVDF 用
    struct sched_rt_entity  rt;             // リアルタイム用
    struct sched_dl_entity  dl;             // DEADLINE 用
    int                     prio, static_prio, normal_prio;
    unsigned int            rt_priority;
    unsigned int            policy;         // SCHED_NORMAL, SCHED_FIFO, ...
    cpumask_t               cpus_mask;      // CPU アフィニティ
    u64                     utime, stime;   // ユーザ/システムCPU時間
    struct nsproxy          *nsproxy;       // 名前空間
    struct css_set          *cgroups;       // cgroup 所属
    // ... 数百のフィールド
};

プロセス状態遷移

この図では、プロセスが「実行可能」「実行中」「待ち」「停止」「ゾンビ」をどう行き来するかを流れで押さえる。

stateDiagram-v2 [*] --> 新規生成: fork()/clone() 新規生成 --> 実行可能: スケジューラキューに追加 実行可能 --> 実行中: CPU に割り当て 実行中 --> 実行可能: タイムスライス消化、高優先プロセス到着 実行中 --> 割り込み可能待ち: wait()、read() 等 実行中 --> 割り込み不可待ち: ディスクI/O待ち等 実行中 --> 停止: SIGSTOP、デバッガ 割り込み可能待ち --> 実行可能: シグナル、I/O完了 割り込み不可待ち --> 実行可能: I/O完了 停止 --> 実行可能: SIGCONT 実行中 --> ゾンビ: exit() ゾンビ --> [*]: 親が wait() で回収

Linux の状態コード(ps の STAT 列):

  • R — Running (実行中 or 実行可能)
  • S — Sleeping (割り込み可能)
  • D — Uninterruptible sleep (通常ディスクI/O、kill できない)
  • T — Stopped (SIGSTOP 後)
  • t — Tracing stop (デバッガ)
  • ZZombie (終了したが親が wait していない)
  • I — Idle kernel thread

プロセス生成:fork と exec

UNIX の美しい設計:

このコードでは、「まず fork() で親子に分かれ、その後に子だけが exec() で別プログラムへ置き換わる」という UNIX 流の基本形を見る。

#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>

int main(void) {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // 子プロセス
        execlp("/bin/ls", "ls", "-l", NULL);
        perror("exec failed");  // exec が成功すればここには来ない
        return 1;
    } else {
        // 親プロセス
        int status;
        waitpid(pid, &status, 0);
        printf("child exited with %d\n", WEXITSTATUS(status));
    }
    return 0;
}

fork() は親プロセスのほぼ完全なコピーを作り、exec() は現在のプロセスを別のプログラムで置き換える。この分離により、子プロセスのファイルディスクリプタやシグナルハンドラを exec 前に調整する柔軟性が得られる(シェルのリダイレクトはこれを利用)。

Copy-on-Write(COW)

素朴な fork() はアドレス空間全体をコピーするため高コスト。現代OSは Copy-on-Write でこれを最適化する:

  1. fork() 時、親子ともにページテーブルは同じ物理ページを指す。
  2. ただしエントリは読み取り専用にマーク。
  3. どちらかが書き込もうとするとページフォルト(#PF, write protect violation)発生。
  4. カーネルが当該ページのコピーを作り、書き込んだプロセスのページテーブルを新ページにリダイレクト。
  5. 読み取りのみのページは永遠に共有(典型的には共有ライブラリやテキスト領域)。

多くの fork() の後にすぐ exec() が呼ばれるケースでは、COW により実際のコピーはほとんど発生しない。

プロセス階層と init

Unix では全プロセスが唯一の祖先 PID 1(init/systemd)に辿り着く木構造を成す。親プロセスが子より先に終了した場合、孤児(orphan)プロセスは init に再親子付けされ、ゾンビ回収は init の責任となる。

Windows のプロセスモデル

Windows のプロセスは以下の点で Unix と異なる:

  • fork() がないCreateProcess() は一度に新プログラムを起動する。
  • プロセス作成が高コスト:スレッド作成の方が推奨される(Windows での軽量並行処理の伝統)。
  • Job Object:プロセスグループを包括的に管理。cgroup 的役割。
  • プロセスのハンドル:オブジェクトマネージャで管理、参照カウント。

スレッドと並行性

初心者向けメモ
スレッドは「プロセスの中で並行に走る軽量な実行単位」です。プロセスより起動が速く、メモリを共有できるため、並列処理や非同期 I/O の基盤になります。

スレッドとは

スレッド は同一プロセスのアドレス空間を共有する実行の流れ。プロセスが「家」なら、スレッドは「その中で同時に活動する人々」。

特性 プロセス スレッド
アドレス空間 独立 共有
ファイルディスクリプタ 独立 共有
スタック 一つ 各スレッド固有
レジスタ 一つ 各スレッド固有
シグナルマスク 共有 各スレッド固有
生成コスト 高(数ms〜数十ms) 低(数μs〜数百μs)
コンテキストスイッチ 重い(アドレス空間切替あり) 軽い
通信 IPC(パイプ、ソケット、共有メモリ) 直接メモリアクセス
安全性 独立で頑健 共有ゆえ競合リスク

カーネルスレッド vs ユーザスレッド

  • カーネルスレッド(1:1 モデル):OS が各スレッドをスケジュール。真の並列性を活用可能。Linux pthread、Windows thread、Java (from JVM), .NET はこれ。
  • ユーザスレッド(N:1 モデル):ユーザ空間ライブラリがスケジュール。I/Oブロックで全スレッドが停止する欠点。初期の Java green threads、Ruby 1.8。
  • ハイブリッド(M:N モデル):ユーザスレッドを少数のカーネルスレッドにマップ。Solaris の LWP、Go の goroutines、Erlang の processes、Rust の async タスクはこれに近い。
  • 軽量スレッド / ファイバー:協調的スケジューリング、ユーザが yield する。Windows Fiber、Project Loom (Java 21+)、Kotlin Coroutine。

POSIX Threads(pthread)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *worker(void *arg) {
    int id = *(int*)arg;
    printf("Thread %d running on TID %ld\n", id, (long)pthread_self());
    sleep(1);
    return NULL;
}

int main(void) {
    pthread_t th[4];
    int ids[4] = {0,1,2,3};
    for (int i = 0; i < 4; i++)
        pthread_create(&th[i], NULL, worker, &ids[i]);
    for (int i = 0; i < 4; i++)
        pthread_join(th[i], NULL);
    return 0;
}

pthread API は以下を提供:

  • pthreadcreatepthread_create, pthreadjoinpthread_join, pthreaddetachpthread_detach, pthreadexitpthread_exit
  • pthreadmutextpthread_mutex_t, pthreadcondtpthread_cond_t, pthreadrwlocktpthread_rwlock_t, pthreadbarriertpthread_barrier_t, pthreadspinlocktpthread_spinlock_t
  • pthreadkeycreatepthread_key_create(スレッドローカルストレージ)
  • pthreadsetaffinitynppthread_setaffinity_np(CPU アフィニティ)
  • pthreadsetcancelstatepthread_setcancelstate, pthreadsetcanceltypepthread_setcanceltype

Linux におけるスレッド実装の歴史

  1. LinuxThreads(1996〜):各スレッドが別 PID、シグナル扱いに難あり。
  2. NGPT (Next Generation POSIX Threads):IBMの試み、失敗。
  3. NPTL (Native POSIX Thread Library, 2003〜):1:1 モデル、clone() + futex 活用。現行標準。

NPTL では clone(CLONEVMCLONEFSCLONEFILESCLONESIGHANDCLONETHREADCLONESYSVSEMCLONESETTLSCLONEPARENTSETTIDCLONECHILDCLEARTID,...)clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, ...) で軽量スレッドを生成。

並行性 vs 並列性

  • 並行性(Concurrency):複数の処理が論理的に同時進行(時分割でも可)。
  • 並列性(Parallelism):複数の処理が物理的に同時実行(マルチコア必須)。

Rob Pike の箴言:「Concurrency is not parallelism.」Go の goroutine は「並行」を、複数コアで実行されれば「並列」にもなる。

メモリモデル

マルチコア CPU では、各コアに別キャッシュがあるため、プログラムの書いた順と、他コアから見える書き込み順が一致しない場合がある。これを定義するのがメモリモデル

  • Sequential Consistency(SC):直感的だが性能ペナルティ大。
  • Total Store Order(TSO):x86-64 が採用。store → load のリオーダリングのみ許す。
  • Release Consistency / Acquire-Release:ARM、RISC-V が採用。明示的バリア必要。

C11 / C++11 は memoryorderseqcstmemory_order_seq_cstacquirereleaserelaxedconsume を提供。プログラマが原子操作に明示的にメモリ順序を指定する。

std::atomic<int> flag{0};
std::atomic<int> data{0};

// スレッドA
data.store(42, std::memory_order_relaxed);
flag.store(1, std::memory_order_release);  // release: これ以前の書き込みが見える保証

// スレッドB
while (flag.load(std::memory_order_acquire) == 0);  // acquire: これ以降の読み込みがリリース以前の書き込みを見る保証
assert(data.load(std::memory_order_relaxed) == 42);

Futex — Linux の同期プリミティブ基盤

Futex (Fast Userspace muTEX) は Linux 2.5.7 (2002) で導入。ユーザ空間の整数変数を使い、コンテンションがない場合はカーネル遷移なく mutex を取得できる。コンテンション時のみ futex() syscall でカーネルに待機をキューイング。

glibc の pthreadmutextpthread_mutex_t、Rust の std::sync::Mutex、Go のチャネル、Java の LockSupport.park/unpark は内部で futex を使う。


CPUスケジューリング詳細

CPU スケジューラは「次にどのプロセス/スレッドを実行するか」を決める。現代OSには、通常プロセス用、リアルタイム用、アイドル用など複数のスケジューリングクラスが共存する。

スケジューリング目標とトレードオフ

目標 意味 対立する目標
公平性(Fairness) すべてのプロセスに妥当な CPU を配分 スループット
スループット(Throughput) 単位時間あたり完了タスク数 応答性
応答性(Responsiveness) ユーザ入力への低遅延 スループット
ターンアラウンド時間 ジョブ投入〜完了までの時間 優先度
待ち時間(Wait time) 実行可能キューでの待機時間
CPU利用率 CPU が busy な割合 省電力
省電力 モバイル/IoT では最優先 性能
予測可能性 RTOS では決定性 平均性能

古典的アルゴリズム

1. FCFS(First Come First Served)

到着順に実行、ノンプリエンプティブ。実装簡単だが convoy 効果(大きなジョブが小さなジョブをブロック)で平均待ち時間悪化。

2. SJF / SRTF(Shortest Job First / Shortest Remaining Time First)

最短の次 CPU バーストを持つプロセスを選ぶ。平均待ち時間最小(証明可)だが、実際の CPU バースト長は事前に分からず推定が必要。指数移動平均で過去バーストから予測する:

τn+1=αtn+(1α)τn\tau_{n+1} = \alpha t_n + (1-\alpha) \tau_n

ここで tnt_n は直近バースト実測、τn\tau_n は推定値、α[0,1]\alpha \in [0,1]

3. ラウンドロビン(RR)

各プロセスに固定タイムクォンタム q を与え、使い切ったらキュー末尾に戻す。q が小さすぎると切替オーバーヘッド、大きすぎると応答性悪化。典型的 q=10q = 10 ms〜 100 ms。

4. 優先度ベース

各プロセスに優先度を付与、高優先を選択。starvation(飢餓) 防止のため aging で待機中の優先度を徐々に上げる。

5. 多段フィードバックキュー(MLFQ)

複数のキューを優先度別に並べ、タイムクォンタムを使い切ったら一段下のキューへ。I/O バウンドは高優先、CPU バウンドは低優先に自然に分化する。Solaris と古い Windows、Mac OS X の原型。

Linux の現代的スケジューラ

CFS(Completely Fair Scheduler, 2007〜2023)

Ingo Molnár による設計。赤黒木(rbtreerb_tree)で vruntime(virtual runtime)をキーに実行可能タスクを順序付ける。vruntime は「優先度差を補正した仮想的な実行時間」で、最小 vruntime のタスクを次に実行する。

理想:n プロセスが完全公平に CPU を共有するとき、各プロセスの実行時間は T/n になる。CFS はこれを近似する。

重み(weight)は nice 値から決まる:nice=0 → 1024、nice=-20 → 88761、nice=19 → 15。vruntime は実行時間を重みで補正した値:

\text{vruntime} += \text{delta\_exec} \times \frac{\text{NICE\_0\_LOAD}}{\text{weight}}

EEVDF(Earliest Eligible Virtual Deadline First, Linux 6.6〜)

Peter Zijlstra らによる後継。各リクエスト(=タイムスライス)に仮想デッドラインを割り当て、eligible なタスクの中でデッドラインが最も早いものを選ぶ。ここで eligible は「今この時点で実行候補にしてよい」という意味で、レイテンシ要求(schedsetattrsched_setattrschedruntimesched_runtime 指定)を尊重しやすい。

リアルタイムクラス

  • SCHEDFIFOSCHED_FIFO:優先度内 FIFO、自発的 yield まで実行。リアルタイム。
  • SCHEDRRSCHED_RR:FIFO にタイムスライス追加。
  • SCHEDDEADLINESCHED_DEADLINE:EDF + CBS(Constant Bandwidth Server)で (runtime, deadline, period) を指定。Hard RT タスクに適する。
  • SCHEDOTHERSCHED_OTHER (=SCHED_NORMAL):CFS/EEVDF で管理。
  • SCHEDBATCHSCHED_BATCH:CPUバウンドでレイテンシ不要。
  • SCHEDIDLESCHED_IDLE:最低優先度、他が何もないとき。

マルチコア・スケーラビリティ

現代の Linux はコアごとに per-CPU ランキュー を持ち、互いに独立にスケジュールする。ランキュー は「その CPU で実行待ちしているタスクの待ち行列」のことで、負荷分散(load balancing) はペリオディックに動き、アンバランスを検知したら タスクマイグレーション で再配置する。

関連概念:

  • CPU affinity(schedsetaffinitysched_setaffinity, taskset)
  • isolcpus カーネルパラメータ(特定コアをスケジューラから除外)
  • cgroup cpuset(cgroup で CPU 集合を制限)
  • NUMA awareness(同一ノード内のコア優先選択、remote memory アクセスを避ける)

macOS のスケジューラ

Mach ベースの優先度スケジューラ。Grand Central Dispatch(GCD)の QoS クラス(user-interactive, user-initiated, utility, background)がシステム全体の優先度に反映される。M1 以降は E-cores(efficiency)P-cores(performance) のヘテロジニアス設計でスケジューラが電力最適化を行う。

Windows のスケジューラ

32段階の優先度(0〜31)。0〜15 が通常クラス、16〜31 がリアルタイムクラス。priority boost により I/O 完了直後やフォアグラウンドウィンドウのスレッドに一時的に優先度を上げる。


同期機構とプロセス間通信

マルチプロセス・マルチスレッド環境では、共有資源への同時アクセスを調整する仕組みが不可欠。

基本同期プリミティブ

1. ロック(Mutex: Mutual Exclusion)

最も基本的。クリティカルセクションに一度に一つのスレッドしか入れない。

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
// クリティカルセクション
pthread_mutex_unlock(&lock);

実装は futex + atomic CAS ベース。競合がなければカーネル遷移なし。

2. スピンロック

ロック取得までビジーループ(CPU を回して待つ)。カーネル内の短時間クリティカルセクションで使う。ユーザ空間では通常推奨されない(CPU 無駄、電力浪費)。

void spin_lock(atomic_int *lock) {
    while (atomic_exchange(lock, 1) == 1) {
        // pause 命令で電力削減
        __builtin_ia32_pause();
    }
}

3. リーダライタロック(rwlock)

複数リーダ同時可、ライタは排他。読み多数、書き少数のケースで有効。

4. セマフォ

Dijkstra が 1965 年に提案。P() (wait) で減算、V() (signal) で加算。0以上の整数でリソース数を管理。

  • バイナリセマフォ:mutex 相当
  • カウンティングセマフォ:リソースプール管理

POSIX: seminitsem_init, semwaitsem_wait, sempostsem_post。SystemV: semget, semop

5. 条件変数(Condition Variable)

「ある条件が真になるまで待つ」。必ず mutex と組み合わせて使う。

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  c = PTHREAD_COND_INITIALIZER;
int ready = 0;

// 待機側
pthread_mutex_lock(&m);
while (!ready) pthread_cond_wait(&c, &m);  // mutex を解放して wait
// ここでは mutex 再取得済み、ready が真
pthread_mutex_unlock(&m);

// 通知側
pthread_mutex_lock(&m);
ready = 1;
pthread_cond_signal(&c);  // または pthread_cond_broadcast
pthread_mutex_unlock(&m);

while (!ready)spurious wakeup 対策で必須。

6. バリア

N スレッドが揃うまで全員待機。並列計算のフェーズ同期に使う。

7. モニタ

高水準同期抽象。Java の synchronized、C# の lock、Python の threading.Condition が該当。

8. RCU(Read-Copy-Update)

Linux カーネル内で広く使われる。読み手はロックなし、書き手は新しいコピーを作って公開後、古いコピーを grace period 後に削除。読み支配的なワークロードで極めて高速。

プロセス間通信(IPC)

プロセス間はアドレス空間が独立しているため、専用の通信機構が必要。

1. パイプ(Pipe)

ls -l | grep "^d" | wc -l

UNIX の美しい発明。無名パイプ pipe(2)pipe(2) と名前付きパイプ mkfifo(3)mkfifo(3)。単方向、バッファリング、EOF 伝達。

2. シグナル

非同期イベント通知。SIGTERM(終了要求)、SIGKILL(強制終了、ハンドル不可)、SIGSEGV(メモリ違反)、SIGINT(Ctrl-C)、SIGCHLD(子プロセス状態変化)、SIGUSR1/2(ユーザ定義)など。

#include <signal.h>
void handler(int sig) { /* ... */ }
signal(SIGINT, handler);  // 古い API
// モダンには sigaction() を使う

シグナルハンドラ内で使える関数は async-signal-safe に限られる(printf は不可、write は可)。

3. 共有メモリ

複数プロセスが同一物理ページを自アドレス空間にマップ。最速の IPC だが同期は別途必要。

  • POSIX 共有メモリshmopenshm_open + mmap
  • SystemV 共有メモリshmget + shmat(レガシー)
  • memfd_create / memfd_secret(Linux)
  • ハイブリッドアプローチ:io_uring の SQE/CQE リングバッファも共有メモリ

4. メッセージキュー

  • POSIX mqueuemqopenmq_open, mqsendmq_send, mqreceivemq_receive
  • SystemV msgmsgget, msgsnd, msgrcv

5. ソケット

  • UNIXドメインソケット:同一マシン上の IPC、高速
  • TCP/UDP ソケット:ネットワーク越し
  • Netlink ソケット:Linux カーネル↔ユーザ空間

6. D-Bus

Linux デスクトップ(GNOME/KDE)および systemd で使われる高水準 IPC。オブジェクト、メソッド、シグナル、プロパティの概念を提供。gdbusbusctldbus-send

7. Mach Messages(macOS/iOS)

XNU のマイクロカーネル的基盤。ポートとメッセージで通信。XPC、NSXPCConnection の基盤。

8. Windows IPC

  • 名前付きパイプ(\\.\pipe\name)
  • Mailslot
  • 共有メモリ(File Mapping)
  • COM / DCOM
  • RPC
  • WM_COPYDATA(GUI ウィンドウメッセージ)
  • Windows Sockets (Winsock)

デッドロック・飢餓・レースコンディション

デッドロック(Deadlock)

二つ以上のプロセスが互いに相手の保有リソースを待ち、全員が進まなくなる状態。

【図8】デッドロックの循環待ち:

graph LR A["Process A / 保有: Lock1 / 待機: Lock2"] B["Process B / 保有: Lock2 / 待機: Lock1"] L1["Lock1"] L2["Lock2"] A -->|保有| L1 B -->|保有| L2 A -.待機.-> L2 B -.待機.-> L1

Coffman 条件

デッドロックが起こるには次の4つが同時成立する必要がある:

  1. Mutual Exclusion(相互排除):リソースは一度に一つのプロセスしか保有できない。
  2. Hold and Wait(保有と待機):既にリソースを保有しつつ、別のリソースを待つ。
  3. No Preemption(非奪取):リソースを強制的に取り上げることはできない。
  4. Circular Wait(循環待ち):プロセス間で循環的な待ち関係がある。

デッドロック対策

予防(Prevention):4条件のいずれかを崩す

  • 相互排除を崩す:リソースを共有可能にする(常に可能とは限らない)
  • 保有と待機を崩す:全リソースを最初に一括取得(lockallthenproceed()lock_all_then_proceed())
  • 非奪取を崩す:待機時に保有リソースを解放、再取得時にやり直し
  • 循環待ちを崩す:リソースに全順序を定義し、番号の昇順でしか取得しない → Linux カーネルの lockdep が自動検証

回避(Avoidance):実行時チェック

  • Banker’s Algorithm(Dijkstra, 1965):リソース要求時、安全状態が保てるかシミュレート。安全状態 = 全プロセスが満足する実行順序が存在する状態。要求プロセス数・リソース種類・数すべて事前判明が前提で、汎用 OS では使いにくい。

検出と回復(Detection & Recovery):定期的にリソース要求グラフを走査し、サイクルを検出したら回復措置

  • プロセスの強制終了
  • ロールバック(DB は普遍的にこれを行う)
  • 資源の強制解放

無視(Ostrich Algorithm):多くの汎用OS(Linux, Windows)は「起きたら困るけど滅多にないから対処しない」方針。Tanenbaum はこれを「ダチョウ法」と命名。

Linux の lockdep

Linux カーネルは CONFIGLOCKDEPCONFIG_LOCKDEP でコンパイルすると、実行時にすべてのロック取得順序を記録し、潜在的デッドロックパターン(循環)を検出して警告する。これにより広範なカーネルロックのバグが発見された。

飢餓(Starvation)

優先度の低いタスクが、高優先タスクに常に追い抜かれて永遠に実行されない状態。エイジング(aging) = 待機時間に応じて優先度を動的に上げる、で緩和。

優先度逆転(Priority Inversion)

低優先プロセスが持つロックを高優先プロセスが待つ間、中優先プロセスが割り込んで CPU を奪う現象。

歴史的事件:火星探査機 Mars Pathfinder(1997) でこれが発生し、タイムアウトによるシステムリセットが多発した。VxWorks の priority inheritance protocol を有効にして解決。

対策:

  • Priority Inheritance:ロック保有者を一時的に最高待機者の優先度まで引き上げ。
  • Priority Ceiling:各ロックに最高優先度を割り当て、取得者はそれに昇格。

POSIX では pthreadmutexattrsetprotocol(PTHREADPRIOINHERIT)pthread_mutexattr_setprotocol(PTHREAD_PRIO_INHERIT) で指定可能。

レースコンディション(Race Condition)

複数スレッドの実行順序によって結果が変わる、バグの温床。

int counter = 0;
// 10 スレッドが各 100000 回 counter++ したら 1,000,000 になるはず?
// → ならない。counter++ は load, add, store の3命令で、
//    スレッド間で織り交ざると失われる更新が発生

対策:

  • アトミック操作(__atomic_add_fetch, std::atomic)
  • ミューテックス
  • ロックフリー構造(CAS ベース)
  • ミュータブルな共有状態を避ける(関数型、Rust 所有権)

TOCTOU(Time-of-check to time-of-use)

「チェックした時と使う時の間で状態が変わる」タイプの脆弱性。

if (access(file, W_OK) == 0) {  // チェック時は OK
    fd = open(file, O_WRONLY);  // 攻撃者が symlink に差し替えたら?
    write(fd, data, n);
}

対策:openat(ONOFOLLOW)openat(O_NOFOLLOW)、ハンドルベース API、capabilities。


メモリ管理

初心者向けメモ
プロセスが触れる「アドレス」は本当のメモリ位置ではなく「仮想アドレス」です。OS と MMU(メモリ管理ユニット)が協力して、仮想→物理への変換、分離、保護、拡張(スワップ)を実現しています。

現代 OS のメモリ管理は、ハードウェア(MMU, TLB, cache)との連携で成立する巨大なサブシステムです。

メモリ階層

レジスタ          < 1 ns   B 単位      各コア内
L1 キャッシュ       ~1 ns   32 KB       各コア内
L2 キャッシュ       ~4 ns   256 KB〜1 MB 各コア内
L3 キャッシュ      ~10 ns   数MB〜数十MB  CPU ソケット内共有
DRAM             ~80 ns   GB〜TB       ソケット越しアクセスは遅い (NUMA)
NVDIMM/Optane   ~300 ns   TB          永続、廃番
SSD (NVMe)      ~10 μs   TB          ブロックデバイス
SSD (SATA)      ~100 μs  TB
HDD             ~10 ms   TB          シーク遅延大
Tape / クラウド   ~秒〜分   PB

この階層は locality of reference の原理に基づく:

  • 時間局所性:最近使ったデータは近く使われる
  • 空間局所性:あるアドレスを使ったら周辺も使う

キャッシュと仮想メモリシステム(ページキャッシュ、スワップ)はこの仮定で設計されている。

仮想メモリ

各プロセスに、物理メモリとは独立した仮想アドレス空間(x86-64 は 48bit = 256TB、最新 LA57 で 57bit = 128PB)を提供。MMU が仮想→物理変換を行う。

利点

  • プロセス間分離(互いのメモリを破壊できない)
  • 物理メモリより大きな仮想空間(スワップ、オーバーコミット)
  • 連続的なアドレス空間(断片化された物理メモリを統合)
  • 共有メモリ(同一物理ページを複数プロセスにマップ)
  • COW、デマンドページング、メモリマップトファイル

ページング

仮想アドレス空間を固定サイズ(典型的に 4KB)のページに、物理メモリを同サイズのフレームに分割。ページテーブルで対応関係を保持。

4 段ページテーブル(x86-64, 48bit)

 48bit 仮想アドレス = | 9 | 9 | 9 | 9 | 12 |
                      PML4 PDPT PD  PT オフセット
                      
 CR3 → PML4 → PDPT → PD → PT → 物理ページフレーム番号

各レベルは 512 エントリ(9bit)、各エントリは 8 バイト(64bit)。5 段(LA57) は Ice Lake 以降で利用可、128PB まで対応。

TLB(Translation Lookaside Buffer)

MMU に内蔵された「最近の翻訳結果キャッシュ」。TLB ミスすると 4 回(もしくは 5 回)のメモリアクセスでページテーブルをウォーク(遅い)。Intel x86-64 の TLB は典型的に L1 dTLB が 64 エントリ、L2 STLB が 1024〜2048 エントリ。

TLB シュートダウン:あるコアがページテーブルを更新したとき、他コアの TLB も無効化する IPI(Inter-Processor Interrupt)が必要。マルチコアでは意外に高コスト。

Huge Pages(大ページ)

通常 4KB の代わりに 2MB や 1GB のページを使うと、TLB エントリで大きな領域をカバーでき、ミスが減る。

  • Linux の THP(Transparent Huge Pages):自動で昇格
  • 明示的 hugetlbfs/proc/sys/vm/nrhugepages/proc/sys/vm/nr_hugepages で予約
  • Windows Large PagesVirtualAlloc(MEMLARGEPAGES)VirtualAlloc(MEM_LARGE_PAGES)

データベース(PostgreSQL の hugepages=onhuge_pages = on、MySQL)や JVM(-XX:+UseLargePages)で有効化するとパフォーマンス改善が見られる。

デマンドページング

プロセス起動時に全ページを物理メモリにロードせず、アクセスされた時にはじめてフォルト経由でロード。未使用コードや初期化データは永遠にロードされない可能性があり、メモリ効率的。

ページ置換アルゴリズム

物理メモリが逼迫したとき、どのページをディスクに追い出すか?

アルゴリズム 概要 評価
FIFO キュー順、古い方から 単純、Belady’s anomaly あり
OPT(最適) 最も遠い将来に使うページ 理論上最適、実装不可
LRU(最近最少使用) 最も古くアクセスされたページ 近似最適、コスト高
Clock / Second-chance 参照ビットで近似 LRU 実装簡単、Linux の基礎
LFU(最少頻度使用) アクセス回数最少 古いけど重要なページが追い出される
ARC(Adaptive Replacement Cache) IBM 特許、LRU + LFU ハイブリッド ZFS で使用
2Q, CAR, LIRS 近似 ARC 各種 DB エンジン

Linux は 2 Q (active/inactive list) + WorkingSet refault + reclaim で実装。

Working Set と スラッシング

Working Set:時刻 t から過去 Δ\Delta 時間にアクセスされたページ集合 W(t,Δ)W(t, \Delta)

スラッシング:物理メモリが全プロセスの working set 総和より小さく、ページフォルトとディスクI/Oが頻発して CPU がほぼ idle になる状態。

対策:

  • メモリ追加
  • プロセスをスワップアウト(サスペンド)
  • swappiness パラメータ調整
  • OOM killer(Linux の最後の手段)

メモリアロケータ

物理メモリ層:バディアロケータ

ページを 2^n ページの塊(order-n block)で管理。要求時は最小の十分な塊を取り、必要なら分割。解放時は buddy(兄弟)が free なら統合。

  • 外部断片化を大幅に削減
  • 最大 order は CONFIG_FORCE_MAX_ZONEORDER(通常 10、4MB 塊まで)
  • cat /proc/buddyinfo で確認可能

スラブアロケータ(SLAB / SLUB / SLOB)

同サイズのオブジェクト(taskstructtask_struct, inode, dentry, skbuffsk_buff 等)を効率管理。kmalloc / kmemcacheallockmem_cache_alloc の基盤。

  • SLAB:Jeff Bonwick @ Sun の原型。キャッシュフレンドリだが複雑・メタデータ大
  • SLUB(現 Linux 標準, 2008〜):Christoph Lameter 作、シンプル・高速
  • SLOB:メモリ制約組み込み向け、極小

ユーザ空間の malloc 実装

実装 特徴 採用
ptmalloc2 glibc 標準、ロック競合あり Linux デフォルト
tcmalloc Google、Thread-Caching Chromium、多くの Google 系
jemalloc Facebook、フラグメンテーション低 FreeBSD、Firefox、Rust 旧版
mimalloc Microsoft、Research Microsoft 系、一部性能クリティカル
rpmalloc Rampant Pixel、ロックレス ゲームエンジン
snmalloc Microsoft Research、モダン 研究

NUMA(Non-Uniform Memory Access)

マルチソケットサーバでは、各ソケットにローカル RAM があり、リモートソケットの RAM へのアクセスは数倍遅い。

Socket 0                     Socket 1
  CPU 0,1,2,3,...              CPU 8,9,10,11,...
   ↕ local memory (速)          ↕ local memory (速)
   Node 0 RAM                   Node 1 RAM
         ↕ UPI/Infinity Fabric (遅)

Linux の NUMA 対応:

  • numactl コマンド、libnuma
  • カーネルパラメータ:numa=offnuma=off
  • mempolicy:MPOLBINDMPOL_BIND, MPOLPREFERREDMPOL_PREFERRED, MPOLINTERLEAVEMPOL_INTERLEAVE
  • numastatnumactl --hardware
  • Transparent NUMA balancing (auto-migrate pages)

Copy-on-Write、Zero-Fill、Demand-Zero

  • Zero-fill on demandmmap(MAPANONYMOUS)mmap(MAP_ANONYMOUS) した領域は全て zeropagezero_page を指す。書き込み時に初めて実メモリ割り当て。
  • COWfork 後の書き込みで初めてコピー。
  • Deduplication (KSM - Kernel Samepage Merging):仮想化ホスト等で同一内容のページを自動統合。

メモリ統計観察

free -h                    # 全体
cat /proc/meminfo          # 詳細
vmstat 1                   # 時系列
ps -o pid,rss,vsz,cmd      # プロセス別
pmap -x <pid>              # プロセス詳細マップ
smem -rs rss               # swap 含む
slabtop                    # スラブキャッシュ
cat /proc/buddyinfo        # バディ状態
cat /proc/zoneinfo         # ゾーン別
cat /proc/pagetypeinfo     # 断片化
perf mem record            # メモリアクセスプロファイル

ファイルシステムとI/O

初心者向けメモ
Unix 系 OS では「すべてはファイル」という哲学が貫かれており、通常のファイルもデバイスも、ソケットも、パイプも同じ API(`open`/`read`/`write`/`close`)で扱えます。

ファイルとディレクトリ

ファイル:名前のついたバイトシーケンスに属性(所有者、権限、タイムスタンプ)を付けたもの。

ディレクトリ:ファイル名→inode の対応表。ディレクトリ自体もファイルの一種(type=directory)。

Unix のファイル階層(FHS)

FHS(Filesystem Hierarchy Standard) は、Unix/Linux 系で「どの種類のファイルをどこに置くか」をそろえるための慣習・標準である。

flowchart TB R["/ ルート"] R --> BIN["bin/"] R --> BOOT["boot/"] R --> DEV["dev/"] R --> ETC["etc/"] R --> HOME["home/"] R --> LIB["lib/"] R --> LIB64["lib64/"] R --> MEDIA["media/"] R --> MNT["mnt/"] R --> OPT["opt/"] R --> PROC["proc/"] R --> ROOTD["root/"] R --> RUN["run/"] R --> SBIN["sbin/"] R --> SRV["srv/"] R --> SYS["sys/"] R --> TMP["tmp/"] R --> USR["usr/"] R --> VAR["var/"] USR --> UB["bin/"] USR --> UL["lib/"] USR --> ULO["local/"] USR --> US["share/"] USR --> USC["src/"] VAR --> VLOG["log/"] VAR --> VC["cache/"] VAR --> VLIB["lib/"] VAR --> VS["spool/"]

inode

Unix ファイルシステムの中核データ構造。各ファイルに一意の inode 番号があり、メタデータとデータブロック位置を保持する。名前そのものはディレクトリ側にあり、inode は「その実体情報」を持つ。

【図20】inode の構造:

この図では、ファイル名そのものは inode に入らず、inode 側には属性とデータ位置が入る、という役割分担を見る。

graph LR Inode["inode #54321"] Inode --> T["ファイルタイプ / regular, directory, symlink / char dev, block dev, socket, fifo"] Inode --> M["モード / rwxr-xr-x = 0755"] Inode --> O["所有者 UID / GID"] Inode --> L["ハードリンク数"] Inode --> S["サイズ(バイト)"] Inode --> TS["タイムスタンプ / atime, mtime, ctime, btime"] Inode --> BP["ブロックポインタ"] BP --> D["直接ポインタ × 12 / ext4: 先頭 48KB"] BP --> I1["単間接ポインタ"] BP --> I2["二重間接ポインタ"] BP --> I3["三重間接ポインタ"] Inode --> X["拡張属性 (xattr)"]

ハードリンク:複数のディレクトリエントリが同じ inode を指す(ln src dst)。 シンボリックリンク:パス名を格納した特殊ファイル(ln -s src dst)。

stat コマンドで詳細確認、ls -i で inode 番号表示。

ext4 / XFS / Btrfs / ZFS / APFS / NTFS の比較

ここで ジャーナリング は「更新前後の記録を先に残して、障害時に整合性を戻しやすくする仕組み」、CoW(Copy-on-Write) は「上書きせず新しい場所へ書いてから差し替える方式」、VSS は Windows の Volume Shadow Copy Service でスナップショット機能を指す。

特徴 ext4 XFS Btrfs ZFS APFS NTFS
開発元 Linux コミュニティ SGI→Linux Oracle→Linux Sun→OpenZFS Apple Microsoft
ジャーナリング CoW CoW CoW
最大ファイル 16 TiB 8 EiB 16 EiB 16 EiB 8 EiB 16 TB
最大FS 1 EiB 8 EiB 16 EiB 256 ZiB 8 EiB 256 TB
スナップショット VSS
RAID 内蔵
圧縮 lz4, zlib
重複排除
暗号化 fscrypt 実験 EFS
チェックサム メタデータ メタデータ メタデータ
検証 fsck.ext4 xfs_repair btrfs check zpool scrub fsck_apfs chkdsk
主な用途 汎用Linux 大容量・並列 モダンLinux エンタープライズ macOS/iOS Windows

ジャーナリングファイルシステム

クラッシュ時のメタデータ不整合を防ぐ。書き込みをジャーナル(ログ)に記録してからコミット。クラッシュ後はジャーナルを再生して整合性回復。

ext4 のモード:

  • journal:データもメタデータもジャーナル(安全、遅い)
  • ordered(デフォルト):メタデータのみジャーナル、ただしデータを先にディスクに書く
  • writeback:メタデータのみ、データ順序保証なし(最速、データ不整合リスク)

Copy-on-Write ファイルシステム

Btrfs、ZFS、APFS が採用。書き込みは既存ブロックを上書きせず、新ブロックに書き、メタデータを原子的に更新。

利点

  • クラッシュ耐性(常に古いバージョンがディスクにある)
  • スナップショットが O(1)
  • 圧縮・暗号化・チェックサム・重複排除と相性が良い

欠点

  • 断片化しやすい(特にランダム更新)
  • メタデータオーバーヘッド

ページキャッシュとバッファキャッシュ

Linux はディスク I/O をページキャッシュで透過的にキャッシュする。read() した内容は RAM に保持され、同じ領域の次の read() は RAM から返す。free -hbuff/cache 列がこれ。

Write-back cachewrite() で RAM に書き、後で flushd/pdflush/bdi-flush がディスクに書く。sync/fsync/fdatasync/msync で強制フラッシュ。

Direct I/O(ODIRECTO_DIRECT):ページキャッシュを迂回してディスクに直接 I/O。DBMS など自前キャッシュを持つアプリケーションで使う。

I/O モデル

1. 同期ブロッキング I/O

ssize_t n = read(fd, buf, count);  // データ来るまでブロック

シンプルだが、並行接続数だけスレッドが必要(C10K 問題)。

2. 同期ノンブロッキング I/O

fcntl(fd, F_SETFL, O_NONBLOCK);
while (read(fd, buf, count) < 0 && errno == EAGAIN) {
    // ビジーループ(非効率)
}

3. I/O 多重化(Multiplexing)

一つのスレッドで複数 fd を監視:

  • select:古い、fd 数に上限(FD_SETSIZE=1024)
  • poll:上限なし、fd 毎にコピー発生
  • epoll(Linux):O(1)、level/edge triggered、カーネルで状態保持
  • kqueue(BSD/macOS):汎用イベント通知(fd、ファイル変更、シグナル、タイマ)
  • IOCP(Windows):Completion Port、非同期完了通知

4. シグナル駆動 I/O

SIGIO で通知(あまり使われない)。

5. 非同期 I/O(AIO)

  • POSIX AIO:Linux 実装は貧弱でほとんど使われない
  • Linux native AIO (libaio):O_DIRECT 専用、制限多
  • io_uring(2019〜):SQE/CQE 共有リングバッファ、バッチ化、zero-copy、現代的
  • IOCP(Windows):成熟した非同期モデル

io_uring の設計

Jens Axboe による Linux の革新的非同期 I/O API。

struct io_uring ring;
io_uring_queue_init(32, &ring, 0);

// 提出
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, 4096, offset);
io_uring_submit(&ring);

// 完了待ち
struct io_uring_cqe *cqe;
io_uring_wait_cqe(&ring, &cqe);
// cqe->res が結果
io_uring_cqe_seen(&ring, cqe);

特徴:

  • システムコール回数が激減(バッチ提出、バッチ取得)
  • SQ_POLL でカーネルスレッドが busy poll し、ユーザは syscall なしで I/O 発行可
  • ファイル、ソケット、タイマ、fsyncacceptsend/recv など幅広くサポート
  • IOSQEIOLINKIOSQE_IO_LINK で依存チェーンを形成

メモリマップトファイル(mmap)

ファイルをプロセスのアドレス空間にマップし、ポインタアクセスで読み書き。

int fd = open("data.bin", O_RDWR);
void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
// addr を通して直接操作
*(int*)addr = 42;
msync(addr, size, MS_SYNC);  // ディスクに同期
munmap(addr, size);

メリット:ページキャッシュをそのまま利用、大きなファイルも効率的、複数プロセス共有可。 デメリット:予期せぬページフォルト、SIGBUS(ファイル縮小時)、エラーハンドリングが面倒。

pseudo filesystem(疑似FS)

物理ストレージなしに情報を提供:

  • procfs(/proc):プロセスごとの情報(/proc/<pid>/status/proc/<pid>/status)、カーネル情報
  • sysfs(/sys):デバイスツリー、カーネルパラメータ
  • tmpfs(/tmp, /run, /dev/shm):RAM ベースのファイルシステム
  • devtmpfs, devfs:デバイスノード
  • cgroup2fs(/sys/fs/cgroup):cgroup 階層
  • debugfs(/sys/kernel/debug):デバッグ用
  • configfs、securityfs、pstore、bpf、tracefs

FUSE(Filesystem in Userspace)

ユーザ空間でファイルシステムを実装できるフレームワーク。SSHFS、NTFS-3G、S3FS、rclone、Google Drive FS 等で使われる。


ストレージ管理とRAID

ディスクの物理構造

HDD(Hard Disk Drive)

回転する磁気ディスク、機械式ヘッド。

  • シーク時間(ヘッド移動):5〜15 ms
  • 回転遅延(セクタが下に来る):3〜6 ms(7200rpm で平均 4.2ms)
  • 転送時間:データをヘッドが読む
  • IOPS:100〜200 程度

最適化:エレベータスケジューラ(C-SCAN)、ディスクキャッシュ、書き込み結合。

SSD(Solid State Drive)

NAND フラッシュメモリ、機械部品なし。

  • 読み込み:25〜100 μs
  • 書き込み:200〜500 μs(消去は ms 単位)
  • IOPS:数万〜100万(NVMe)
  • 問題:書き換え回数制限(TLC 数千回、QLC 数百回)、書き込み増幅、GC

対策:TRIM(解放済みブロック通知)、ウェアレベリング(均等消耗)、over-provisioningSLC cache

I/O スケジューラ(Linux)

ディスクからの I/O 要求を並べ替え、マージする。

  • noop / none:並べ替えなし。SSD 向き。
  • mq-deadline:期限ベース。汎用、デフォルト。
  • kyber:低遅延向け、マルチキュー。
  • bfq (Budget Fair Queueing):プロセス公平性、デスクトップ向き。

/sys/block/sda/queue/scheduler で確認・変更。

RAID(Redundant Array of Independent Disks)

複数ディスクを組み合わせて、性能や冗長性を向上。

RAID Level 方式 最小枚数 容量 性能 冗長性
RAID 0 ストライピング 2 100% 読書両倍 なし
RAID 1 ミラーリング 2 50% 読倍、書同等 1台障害OK
RAID 5 パリティ分散 3 (N-1)/N 読高、書中 1台障害OK
RAID 6 二重パリティ 4 (N-2)/N 読高、書低 2台障害OK
RAID 10 1+0 4 50% 両高 各ミラーで1台
RAID Z1/Z2/Z3 ZFS 3/4/5 類似5/6 両中 1/2/3台

ハードウェア RAID vs ソフトウェア RAID

  • ハードウェア RAID:専用コントローラカード、BBU(Battery Backup Unit)でキャッシュ保護、OS から見えない
  • ソフトウェア RAID:Linux の md、FreeBSD の geom、Solaris の ZFS / Vinum

LVM(Logical Volume Manager)

物理ボリューム(PV)→ ボリュームグループ(VG)→ 論理ボリューム(LV)の階層で柔軟な管理。

物理ディスク (sda)   (sdb)
     ↓               ↓
Physical Volume  Physical Volume  
     \           /
    Volume Group "vg_data"
     /           \
Logical Volume   Logical Volume
   "lv_root"      "lv_home"
     ↓               ↓
Filesystem        Filesystem
(ext4)            (xfs)

スナップショット、リサイズ、シンプロビジョニング(lvcreate --thin)、RAID もサポート。

分散ファイルシステム・オブジェクトストレージ

  • NFS(Network File System, Sun 1984):標準、古典的
  • SMB/CIFS(Samba):Windows 相互運用
  • Lustre:HPC、数千ノード
  • GlusterFS:オブジェクト、スケール
  • Ceph:分散オブジェクト、ブロック、ファイル
  • HDFS(Hadoop):ビッグデータ、大ブロック
  • S3:Amazon、事実上の標準オブジェクト API
  • MinIO、GCS、Azure Blob

デバイス管理とドライバ

デバイスの分類

Linux カーネルはデバイスを以下のクラスに分ける:

  • キャラクタデバイス(char device):バイト単位、シーケンシャル(ターミナル、シリアル、サウンド)
  • ブロックデバイス(block device):固定サイズブロック、ランダムアクセス(ディスク、SSD)
  • ネットワークデバイス(net device):パケット(NIC)。/dev に現れない、特別扱い。

デバイスファイル

Unix では全てがファイル。/dev/ に:

/dev/sda, /dev/sda1     SATA/SCSI/SAS/USB 接続ディスク
/dev/nvme0n1, /dev/nvme0n1p1  NVMe
/dev/tty0〜tty6          仮想コンソール
/dev/ttyS0, /dev/ttyUSB0 シリアル、USBシリアル
/dev/null                ビットバケット
/dev/zero                無限の 0
/dev/random, /dev/urandom 暗号論的乱数
/dev/input/eventN        入力デバイス
/dev/fb0                 フレームバッファ
/dev/dri/card0           DRM(Direct Rendering Manager、GPU)
/dev/snd/                ALSA サウンド

udev と sysfs

ホットプラグイベント(USB 挿入、デバイス電源投入)を検知し、/dev ノード作成・パーミッション設定・ユーザ通知。

sysfs(/sys)がデバイスツリーを表現し、カーネル↔ユーザ空間の構造化インターフェースとなる。

Linux のドライバモデル

【図9】Linux ドライバモデル階層:

graph TB US["ユーザ空間 / open, read, write, ioctl, mmap"] VFS["VFS / ブロック層 / ネットワークスタック"] DD["デバイスドライバ / file_operations / block_device_operations"] BUS["バスドライバ (PCI, USB, I2C, SPI)"] HW["ハードウェア"] US -.syscall.-> VFS VFS --> DD DD -.ハードウェア操作.-> BUS BUS --> HW

カーネルモジュール

Linux の多くのドライバは .ko ファイルとしてビルドされ、起動後に動的にロード可能。

lsmod                # ロード中モジュール
modinfo <mod>        # モジュール情報
modprobe <mod>       # 依存関係解決してロード
rmmod <mod>          # アンロード
dmesg | tail         # ロード時のログ

割り込み処理

上位ハーフ(Top Half)

割り込みハンドラ本体。割り込み禁止で動く最小限の処理。レジスタ読み、ハード状態クリアのみ。

下位ハーフ(Bottom Half)

時間のかかる処理は後で実行。以下のメカニズム:

  • Softirq:静的、高速、ネットワーク処理など
  • Tasklet:softirq 上の軽量 API、廃止予定
  • Workqueue:kworker カーネルスレッドで実行、スリープ可能

MSI / MSI-X(Message Signaled Interrupts)

PCI Express 時代の割り込み。専用ライン不要、デバイスが特定メモリアドレスに書き込むことで割り込み通知。ベクタ数が多く、マルチコア負荷分散に適する。

DMA(Direct Memory Access)

CPU を介さずにデバイスがメモリに直接 R/W。大容量転送で CPU 負荷を回避。

IOMMU(Intel VT-d、AMD-Vi、ARM SMMU)で DMA にも仮想アドレスを使い、保護・仮想化を実現。


ネットワーキング

ネットワークスタック

OSI / TCP/IP の5層モデル:

【図10】TCP/IP ネットワーク階層:

graph TB L7["L7 アプリケーション層 / HTTP, DNS, SSH, SMTP"] L4["L4 トランスポート層 / TCP, UDP, QUIC"] L3["L3 ネットワーク層 / IPv4, IPv6, ICMP"] L2["L2 データリンク層 / Ethernet, Wi-Fi"] L1["L1 物理層 / 銅線、光ファイバ、電波"] L7 --> L4 --> L3 --> L2 --> L1

ソケット API

Berkeley Sockets(1983 年の BSD 4.2 から)が業界標準。

// TCP サーバの骨格
int srv = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
struct sockaddr_in addr = {
    .sin_family = AF_INET,
    .sin_port = htons(8080),
    .sin_addr.s_addr = INADDR_ANY
};
bind(srv, (struct sockaddr*)&addr, sizeof(addr));
listen(srv, 128);

while (1) {
    int cli = accept(srv, NULL, NULL);
    char buf[4096];
    ssize_t n = read(cli, buf, sizeof(buf));
    write(cli, buf, n);
    close(cli);
}

Linux の TCP/IP スタック

カーネル内 net/ipv4/, net/ipv6/, net/core/ にある。主要コンポーネント:

  • sk_buff(socket buffer, “skb”):パケットの内部表現。
  • Qdisc(Queuing Discipline):送信キュー管理(fq_codel, cake, htb)。
  • Netfilter:パケットフィルタリングフック(iptables, nftables)。
  • Traffic Control (tc):帯域制御、シェーピング、ポリシング。
  • ConntrackNAT、接続追跡。
  • XFRM:IPsec。

TCP の制御アルゴリズム

輻輳制御が実装で選択可能:

  • Reno / NewReno:古典
  • Cubic(Linux デフォルト 2008〜)
  • BBR(Google, 2016〜):帯域・RTT ベース、広く採用
  • BBRv2, BBRv3
  • Vegas, Westwood, Hybla, HSTCP
sysctl net.ipv4.tcp_congestion_control    # 確認
sysctl -w net.ipv4.tcp_congestion_control=bbr  # 設定

eBPF(extended Berkeley Packet Filter)

Linux カーネルに小さな「安全な仮想マシン」を埋め込み、ユーザ空間の C/Rust プログラムをカーネル内で実行する革新的機構。

主な用途:

  • パケットフィルタリング:cgroup eBPF, tc eBPF
  • XDP(eXpress Data Path):NIC ドライバ直下で実行、低遅延ルータ・ファイアウォール
  • トレーシング:kprobe, uprobe, tracepoint (bpftrace, bcc)
  • セキュリティ:Seccomp BPF、Cilium(Kubernetes ネットワークセキュリティ)、Falco
  • 可観測性:Pixie、Parca、Pyroscope
SEC("xdp")
int xdp_drop_icmp(struct xdp_md *ctx) {
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end) return XDP_ABORTED;
    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > data_end) return XDP_ABORTED;
    if (ip->protocol == IPPROTO_ICMP) return XDP_DROP;
    return XDP_PASS;
}

名前空間とネットワーク分離

Linux の network namespace により、プロセス群ごとに独立した NIC、ルーティングテーブル、iptables を持てる。Docker、Kubernetes、VPN クライアント(Tailscale, WireGuard)で使用。

ip netns add myns
ip netns exec myns ip link   # 分離された lo のみ見える
ip link add veth0 type veth peer name veth1
ip link set veth1 netns myns

QUIC と HTTP/3

  • QUIC(RFC 9000, 2021):UDP ベース、TLS 1.3 統合、0-RTT、head-of-line blocking 除去
  • HTTP/3(RFC 9114, 2022):QUIC 上の HTTP
  • Linux カーネルは 2024 年から QUIC 対応を段階的に導入

セキュリティ

初心者向けメモ
OS のセキュリティは「多層防御(defense in depth)」の原則に立っています。認証・認可・サンドボックス・暗号化・監査を重ねがけして、どこかが破られても他で食い止めます。

OS のセキュリティは多層防御(defense in depth)が原則です。単一の防壁に依存せず、複数の独立した層で攻撃者を遅延・検出します。

基本的脅威モデル

  • 不正アクセス:許可されない読み書き・実行
  • 権限昇格:一般ユーザから root への昇格、サンドボックス脱出
  • 機密性破壊:データの盗難、パスワード漏洩
  • 完全性破壊:データ・コード改ざん、rootkit
  • 可用性破壊:DoS、クラッシュ、資源枯渇
  • 否認:操作の否認(監査ログで防御)

アクセス制御モデル

DAC(Discretionary Access Control)

Unix の rwx パーミッションが典型。所有者がアクセス権を自由に設定できる。

flowchart TB F["-rw-r--r-- 1 alice users 4096 Apr 10 12:34 file.txt"] F --> T["file type"] F --> O["所有者権限"] F --> G["グループ権限"] F --> U["その他ユーザ権限"] F --> OW["所有者: alice"] F --> GR["グループ: users"]

拡張:ACL(setfacl, getfacl)で個別ユーザ・グループに細かい権限付与。

MAC(Mandatory Access Control)

システム管理者のポリシーが強制され、所有者でも変更できない。

  • SELinux(NSA 開発、Red Hat 系):タイプ強制、ロールベース、マルチレベル
  • AppArmor(Canonical, SUSE):パスベース、プロファイル単位、学習モードあり
  • TOMOYO Linux:パスベース、日本 NTT 開発
  • SMACK:シンプル、Tizen で使用

RBAC(Role-Based Access Control)

ロールを介して権限を管理。SELinux の一部、Kubernetes RBAC など。

Capabilities

Linux では伝統的な「root or not」を分解し、個別権限(CAP_NET_BIND_SERVICE、CAP_SYS_ADMIN、CAP_CHOWN、CAP_KILL など 41 種類)に分離。必要な capability のみを付与できる。

setcap 'cap_net_bind_service=+ep' /usr/bin/myserver
# root 権限なしで <1024 のポートにバインド可

サンドボックス機構

seccomp BPF

許可するシステムコールを BPF フィルタで制限。許可外のシステムコールを呼ぶとカーネルが SIGKILL / SIGSYS で強制終了。Chrome、Docker、systemd、Firefox で使用。

struct sock_filter filter[] = {
    BPF_STMT(BPF_LD|BPF_W|BPF_ABS, offsetof(struct seccomp_data, nr)),
    BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_execve, 0, 1),
    BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
    BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
};

名前空間(Linux namespaces)

プロセスごとに独立した「見える世界」を提供。コンテナの基盤。

名前空間 分離対象 関連 syscall
PID プロセスID空間 clone(CLONE_NEWPID)
NET ネットワーク clone(CLONE_NEWNET)
MNT マウントポイント clone(CLONE_NEWNS)
UTS ホスト名、ドメイン名 clone(CLONE_NEWUTS)
IPC System V IPC、POSIX msgqueue clone(CLONE_NEWIPC)
USER UID/GID、capability clone(CLONE_NEWUSER)
CGROUP cgroup ビュー clone(CLONE_NEWCGROUP)
TIME boot time, monotonic time clone(CLONE_NEWTIME)

Landlock(Linux 5.13〜)

アプリケーション自身が「私はこれ以上のファイルアクセスは不要」と宣言できる、unprivileged sandbox。

macOS Sandbox(SBPL)

Scheme 風 DSL でポリシーを記述。/System/Library/Sandbox/Profiles/ 以下に OS 全体のプロファイル。Mac App Store アプリは必須。

Windows AppContainer、Integrity Level

UWP アプリケーション、ブラウザ(Edge)のレンダラプロセスで使われる。

メモリ保護機構

ASLR(Address Space Layout Randomization)

スタック、ヒープ、共有ライブラリ、実行ファイルのロードアドレスをランダム化。攻撃者が ROP ガジェットのアドレスを事前に知ることを困難に。

Linux: /proc/sys/kernel/randomizevaspace/proc/sys/kernel/randomize_va_space (0/1/2) Windows: Vista 以降デフォルト macOS: デフォルト有効

KASLR(Kernel ASLR)

カーネル自体のロードアドレスをブート毎にランダム化。Meltdown 攻撃で回避されたため、KPTI(Kernel Page Table Isolation) と組み合わせる。

DEP / NX(Data Execution Prevention / No-eXecute)

データ領域(スタック、ヒープ)を実行不可にマーク。スタックバッファオーバーフローからのシェルコード実行を防止。x86 の NX ビット、ARM の XN ビット。

Stack Canary / Stack Protector

関数の戻りアドレスの前に「カナリア値」を置き、関数終了時にチェック。バッファオーバーフローを検出。GCC の -fstack-protector-strong、Windows の /GS

CFI(Control Flow Integrity)

間接ジャンプ・間接コールが合法的なターゲットであることを検証。Clang CFI、Intel CET(Control-flow Enforcement Technology)、ARM BTI(Branch Target Identification)、ARM PAC(Pointer Authentication)。

SMEP / SMAP(Supervisor Mode Execution/Access Prevention)

カーネルモードからユーザ空間のコードを実行/データを読むことを禁止。ret2usr 攻撃の防止。

認証

  • パスワード:shadow ファイル(/etc/shadow)にソルト付きハッシュ(SHA-512、yescrypt)
  • PAM(Pluggable Authentication Modules):統一認証基盤
  • LDAP / Active Directory:集中認証
  • Kerberos:チケットベース SSO
  • TPM(Trusted Platform Module):ハードウェア鍵ストア
  • FIDO2 / WebAuthn:フィッシング耐性、パスキー
  • Biometrics:指紋(Touch ID、Windows Hello)、顔認証

暗号化

フルディスク暗号化

  • Linux: LUKS + dm-crypt(AES-XTS)
  • Windows: BitLocker(AES-XTS、TPM と連携)
  • macOS: FileVault(AES-XTS)
  • iOS: Data Protection(per-file key、ハードウェアエンクレーブ)

ファイルシステム暗号化

  • fscrypt(Linux ext4, F2FS):per-file、per-directory
  • eCryptfs(スタック型)
  • APFS encryption(macOS、per-volume)
  • EFS(NTFS、per-file)

セキュアブート

UEFI Secure Boot:ブートローダ、カーネルが認証された署名鍵で署名されているかを検証。

チェーン:UEFI → Platform Key (PK) → KEK → db → Bootloader → Kernel。Linux では shim が Microsoft 署名を受け、GRUB → カーネルへ署名チェーンを伸ばす。

Measured Boot:各段階のハッシュを TPM の PCR に記録。後で検証可能。

カーネルエクスプロイト対策

  • KASLR + FGKASLR:関数ごとにランダム化
  • stack canary
  • SLAB_HARDENED / freelist randomization
  • heap spray 防止(slab cookie)
  • signed modules:カーネルモジュールの改ざん防止
  • lockdown mode:ロックダウンカーネル(IMA/EVM による)
  • CONFIG_FORTIFY_SOURCE
  • KSPP(Kernel Self-Protection Project) による継続的強化

仮想化ベースセキュリティ

  • Intel SGX(Enclave):分離された実行環境、ただし 2022 年に段階的廃止
  • Intel TDX(Trust Domain Extensions):VM 単位の機密計算
  • AMD SEV/SEV-ES/SEV-SNP:暗号化 VM メモリ
  • ARM CCA(Confidential Compute Architecture):Realm
  • Windows VBS / Credential Guard:Hyper-V で分離したセキュリティ VM
  • Apple Secure Enclave:T2 チップ、M シリーズ内蔵

仮想化

初心者向けメモ
仮想化は「1 台の物理マシンで複数の OS を同時に動かす」技術です。クラウドの基盤はすべてこれです。コンテナよりも分離が強く、オーバーヘッドは少し大きくなります。

仮想化の種類

Type-1 ハイパーバイザ(Bare Metal)

ハードウェア直上で動作。OS なしで動く。

  • VMware ESXi:エンタープライズデファクト
  • Microsoft Hyper-V:Windows Server 統合、Azure 基盤
  • Xen:AWS EC2 初期、現在は Nitro に移行、NetBSD 由来
  • KVM(Kernel-based Virtual Machine):Linux カーネルに統合、Type-1 相当
  • Proxmox VEoVirtOpenStack(管理基盤)

Type-2 ハイパーバイザ(Hosted)

ホスト OS 上で動作。

  • VMware Workstation / Fusion
  • Oracle VirtualBox
  • Parallels Desktop(Mac)
  • QEMU(ユーザモード)
  • UTM(QEMU フロントエンド、macOS)

仮想化技術の分類

完全仮想化(Full Virtualization)

ゲスト OS は未改変で動く。x86 は元来仮想化困難な 17 個の特権命令があったが、バイナリトランスレーション(VMware 初期)、次いでハードウェア支援(Intel VT-x、AMD-V)で解決。

準仮想化(Paravirtualization)

ゲスト OS が「自分は VM 上にいる」と認識し、ハイパーバイザ用 API(hypercall)を使う。Xen PV が代表。

ハードウェア支援仮想化

  • Intel VT-x (VMX):ルート / ノンルートモード、EPT(Extended Page Table)
  • AMD-V (SVM):NPT(Nested Page Table)
  • ARM Virtualization Extensions:EL2
  • RISC-V H extension

KVM のアーキテクチャ

【図11】KVM 仮想化スタック:

graph TB Guest["Guest OS / Linux, Windows, BSD, ..."] QEMU["QEMU / デバイスエミュレーション(ユーザ空間)"] KVM["KVM(Linux カーネルモジュール) / VM 実行制御、EPT/NPT 管理"] HW["ホスト CPU ハードウェア / Intel VT-x / AMD-V"] Guest --> QEMU QEMU -.dev/kvm ioctl.-> KVM KVM -.VT-x / AMD-V.-> HW

メモリ仮想化

  • シャドウページテーブル:VMM がゲスト PT のシャドウを維持(古い手法)
  • EPT/NPT:二段変換、ハードウェア支援(現行)
  • Balloon driver:ゲストから「不要メモリ」を回収
  • KSM(Kernel SamePage Merging):ホストで同一内容ページ統合
  • Memory overcommitment:ゲスト合計 > 物理

CPU 仮想化

  • VMCS(VM Control Structure):VM 状態を保持
  • VM-Entry / VM-Exit:ホスト ↔ ゲスト遷移
  • CPU pinning:仮想 CPU を物理コアに固定
  • Nested virtualization:VM の中に VM

I/O 仮想化

  • Emulated devices(e1000, rtl8139):遅い
  • Virtio:準仮想化、virtio-net, virtio-blk, virtio-scsi, virtio-fs
  • PCI passthrough:デバイスを直接ゲストに割り当て(IOMMU 必須)
  • SR-IOV:1 物理 NIC を複数 VF(Virtual Function)に分割

マイクロVM と現代的仮想化

VM 起動時間を秒以下にし、関数実行や高密度サンドボックスに使う:

  • Firecracker(AWS、Rust 製):Lambda、Fargate の基盤。125 ms で起動
  • Cloud Hypervisor(Intel、Rust 製)
  • Kata Containers:Docker/Kubernetes で軽量VM をコンテナ代わりに
  • Apple Hypervisor.frameworkMicrosoft Hypervisor Platform

コンテナ技術

初心者向けメモ
コンテナは「軽量な仮想化」です。ホスト OS のカーネルを共有するため、仮想マシンより起動が速く、1 台で数百〜数千動かせます。Docker と Kubernetes が現代のクラウドの事実上の標準です。

コンテナとは

プロセス単位の軽量仮想化。完全なゲスト OS なし、ホストカーネル共有。起動数十ミリ秒、オーバーヘッド最小。

Linux コンテナの基盤

1. 名前空間(Namespaces)

(セキュリティ章参照)プロセスから「見える世界」を制限。

2. cgroups(Control Groups)

CPU、メモリ、I/O、ネットワーク、PID 数、デバイスアクセスを制限・計測。

  • cgroup v1(階層ごとに別マウント):古い
  • cgroup v2(統一階層):現行、systemd, Kubernetes で推奨
# cgroup v2 での memory 制限
echo "1G" > /sys/fs/cgroup/mygroup/memory.max
echo $ > /sys/fs/cgroup/mygroup/cgroup.procs

3. Capabilities

(セキュリティ章参照)root 権限を分解。

4. Seccomp

(セキュリティ章参照)syscall フィルタ。

5. Union Filesystems(OverlayFS, aufs, btrfs subvol)

レイヤー化されたファイルシステム。Docker image の base/layer/container の基盤。

OCI(Open Container Initiative)標準

  • Runtime Specification:コンテナの実行方法(runc、crun、youki、runsc/gVisor)
  • Image Specification:イメージフォーマット(config.json + layers)
  • Distribution Specification:レジストリ API

コンテナランタイムの階層

【図12】コンテナランタイムの階層:

graph TB Orch["オーケストレータ / Kubernetes, Nomad, Swarm"] HiRT["高レベルランタイム / containerd, CRI-O, Podman"] LoRT["低レベルランタイム / runc, crun, youki (Rust) / runsc (gVisor), kata-runtime"] Kernel["Linux カーネル / namespaces, cgroups, seccomp"] Orch -.CRI.-> HiRT HiRT -.OCI Runtime Spec.-> LoRT LoRT -.clone, unshare, etc.-> Kernel

Docker

2013 年、Solomon Hykes らが dotCloud で開発。コンテナを「クラウド時代のデプロイメント単位」として普及させた。

主要機能:

  • Dockerfile:イメージビルドレシピ
  • Image layers:差分ベース、共有
  • Docker Hub:パブリックレジストリ
  • Docker Compose:複数コンテナのオーケストレーション
  • Docker Swarm:クラスタリング(Kubernetes に市場で敗北)

Kubernetes

Google の内部システム Borg/Omega に触発され、2014 年に発表。現在 CNCF が保守する事実上のクラウドオーケストレータ標準。

【図16】Kubernetes 主要コンポーネント:

graph TB subgraph CP["Control Plane"] API["kube-apiserver / REST API、全体の中心"] ETCD["etcd / 分散 KV ストア、状態保持"] SCH["kube-scheduler / Pod → Node 配置"] CM["kube-controller-manager / Deployment, ReplicaSet 等"] CCM["cloud-controller-manager"] end subgraph WN["Worker Node"] KBL["kubelet / Pod 管理、CRI 経由"] KP["kube-proxy / Service 実装"] RT["Container Runtime / containerd / CRI-O"] end KBL -.通信.-> API KP -.通信.-> API KBL --> RT

リソース種別:Pod, ReplicaSet, Deployment, StatefulSet, DaemonSet, Job, CronJob, Service, Ingress, ConfigMap, Secret, PersistentVolume, PersistentVolumeClaim, Namespace, Role, ClusterRole, NetworkPolicy など。

代替・周辺

  • Podman:デーモンレス、rootless、systemd 統合
  • LXC / LXD:OS コンテナ(≒軽量 VM)、Canonical
  • rkt:CoreOS、終息
  • Nixery, Bazel:再現可能ビルド
  • gVisor(Google):ユーザ空間カーネル、セキュリティ特化
  • Kata Containers:VM と見分けつかない強い分離

デスクトップOSの詳細比較

初心者向けメモ
世界で使われているデスクトップ OS は事実上 Windows、macOS、Linux の 3 つです。それぞれ設計哲学・ターゲット層・パッケージ管理が大きく異なります。

Windows

Microsoft が 1985 年に MS-DOS 上のシェルとして発売。1995 の Windows 95 で大衆化、2000 年の Windows NT ベース化でモダン OS に。

Windows のエディションと歴史

【図17】Windows 系統図:

graph LR W["Windows 系統"] W --> N9x["9x 系(終了)"] W --> NT["NT 系(現行)"] W --> Svr["Server 系"] W --> Emb["組み込み"] W --> Mob["モバイル(消滅)"] N9x --> W95["Windows 95 (1995)"] N9x --> W98["Windows 98"] N9x --> WME["Windows ME"] NT --> NT31["Windows NT 3.1 (1993)"] NT --> W2K["Windows 2000"] NT --> XP["Windows XP (2001, 長寿命)"] NT --> Vista["Windows Vista"] NT --> W7["Windows 7 (2009, 最人気)"] NT --> W8["Windows 8 / 8.1"] NT --> W10["Windows 10 (2015)"] NT --> W11["Windows 11 (2021)"] Svr --> Srv["Windows Server 2003/2008/2012/2016/2019/2022/2025"] Emb --> Iot["Windows Embedded/IoT"] Mob --> WP["Windows Phone 7/8/10"]

Windows 11 の技術的特徴

  • NT kernel(ntoskrnl.exe):ハイブリッドカーネル
  • WSL2:軽量 Hyper-V VM で Linux カーネル統合
  • DirectX 12 Ultimate、DirectStorage:GPU 最適化
  • Windows Package Manager (winget)
  • WinGet、PowerShell 7、Windows Terminal:モダン CLI
  • TPM 2.0 + Secure Boot 必須:ハードウェアベースセキュリティ
  • ARM64 対応強化:Qualcomm Snapdragon X Elite
  • Copilot 統合:AI アシスタント
  • Pluton セキュリティプロセッサ

Windows ファイルシステム

  • FAT12/16/32/exFAT:互換性、USB メモリ、SD カード
  • NTFS:メインシステム、ACL、EFS、ジャーナリング、VSS
  • ReFS(Resilient File System):Windows Server 向け、破損耐性、チェックサム

macOS

NeXTSTEP(1989)→ Rhapsody → Mac OS X 10.0(2001)→ macOS Sequoia 15(2024)と進化。

macOS の技術スタック

【図13】macOS 技術スタック:

graph TB UI["ユーザインターフェース / Aqua, SwiftUI, AppKit (Cocoa), UIKit"] AS["アプリケーションサービス / Core Animation, Core Data, Core Text, ImageKit"] GM["グラフィックス・メディア / Quartz, Metal, Core Graphics, AVFoundation, AudioToolbox"] SI["システムインターフェース / Foundation, libSystem (libc, libm, libpthread)"] K["カーネル (XNU) / Mach + BSD + I/O Kit"] UI --> AS --> GM --> SI --> K

Apple Silicon 移行

2020 年 M1 発表以降、Intel から Apple 設計 ARM64 チップへ完全移行。

  • M1 → M1 Pro/Max/Ultra → M2 → M3 → M4(2024)
  • Rosetta 2:Intel バイナリの動的バイナリ翻訳、ほぼネイティブ性能
  • ユニファイドメモリ:CPU/GPU/Neural Engine が同一 RAM を共有
  • Secure Enclave:T2 チップを統合
  • Virtualization.framework, Hypervisor.framework

ファイルシステム:APFS

2017 年の macOS High Sierra で HFS+ を置換。

  • Copy-on-Write
  • スナップショット、Time Machine 統合
  • Native encryption
  • Space sharing(複数ボリュームがプールを共有)
  • Crash protection
  • iOS/iPadOS/tvOS/watchOS でも使用

Linux デスクトップ

デスクトップ市場では Windows や macOS に比べると少数派だが、開発用途、研究用途、Steam Deck(Arch ベース SteamOS)などの登場で注目度は高まっている。

デスクトップ環境

DE ベース 特徴
GNOME GTK ミニマル、Wayland ネイティブ、Mutter
KDE Plasma Qt 高カスタマイズ、高機能
XFCE GTK 軽量
LXQt Qt 超軽量
Cinnamon GTK Linux Mint 製、伝統的
MATE GTK GNOME 2 フォーク
Budgie GTK 洗練されたデザイン
COSMIC Rust/Iced System76、次世代
Pantheon GTK elementary OS
Hyprland, Sway wlroots タイル型 Wayland

表示サーバ

  • X11 (X Window System):1984 年、レガシーだがまだ主流
  • Wayland:2008 年、モダン、X11 置換進行中
  • Mir:Canonical、一時期推奨、現在は組み込み特化

三大OSの決定的違い

ファイル階層

概念 Windows macOS Linux
ルート C:\ / /
ユーザホーム C:\Users\alice /Users/alice /home/alice
一時 C:\Windows\Temp, %TEMP% /tmp, $TMPDIR /tmp
プログラム C:\Program Files /Applications /usr/bin, /opt
設定 レジストリ, %APPDATA% ~/Library/Preferences /etc, ~/.config
ログ Event Viewer ~/Library/Logs, /var/log /var/log, journald
パス区切り \ / /
ケース 非感度 非感度(オプションで感度) 感度あり

パッケージ管理

OS システム サードパーティ
Windows winget, MSIX Chocolatey, Scoop, Microsoft Store
macOS App Store Homebrew, MacPorts, Nix
Linux apt (Debian), dnf (RH), pacman (Arch), zypper (SUSE), emerge (Gentoo), nix (NixOS), portage, xbps (Void), apk (Alpine) Flatpak, Snap, AppImage, pip, npm

シェル

OS デフォルト その他利用可
Windows 11 PowerShell 7 cmd, Git Bash, WSL (bash)
macOS 10.15+ zsh bash, fish, tcsh
多くの Linux bash zsh, fish, dash, nushell

使用シーンの適性

  • Windows:ゲーミング、エンタープライズ、MS Office、Adobe、DirectX ゲーム
  • macOS:クリエイティブ(Logic Pro, Final Cut)、iOS 開発、モバイルファースト、BSD/Unix 系開発、統合された体験
  • Linux:サーバ、Web 開発、データサイエンス、カーネル研究、クラウド、組み込み、カスタマイズ性重視

モバイルOS

初心者向けメモ
モバイル OS は Android と iOS が中心です。Android は Linux カーネルベース、iOS は XNU ベースで、どちらも省電力・セキュリティ・バッテリー管理に特化した設計です。

Android

Google 主導、Open Handset Alliance 発足(2007)、2008 年に HTC Dream 発売。現在は世界で最も広く使われているモバイル OS の一つである。

Android のアーキテクチャ

【図14】Android アーキテクチャ:

この図では、Android が「アプリ層 → フレームワーク → ランタイム / ネイティブライブラリ → HAL → Linux カーネル」という多層構造で成り立つ点を見る。

graph TB App["Android アプリケーション (APK) / Gmail, Maps, YouTube, サードパーティ"] FW["Java API Framework / Activity, Service, ContentProvider, View / Notification, Package, Resource Manager"] Native["Native C/C++ Libs / Bionic libc, SQLite, WebKit / OpenGL ES, Media Framework"] ART["Android Runtime (ART) / Dalvik の後継、AOT + JIT、ガベコレ"] HAL["Hardware Abstraction Layer (HAL) / Audio, Bluetooth, Camera, Sensors, Radio"] Kernel["Linux Kernel (LTS + Android patches) / Binder IPC、低メモリキラー、ANR、SELinux / wakelocks、ashmem、gralloc"] App --> FW FW --> Native FW --> ART Native --> HAL ART --> HAL HAL --> Kernel

Android の特徴

  • Binder IPC:マイクロカーネル風の高速 IPC、全システムサービスの通信基盤
  • Zygote:アプリ起動高速化のため、ART の warm コピーを fork
  • Android Runtime (ART):Dalvik を 5.0 (Lollipop) で置換、AOT + プロファイルガイド JIT
  • SELinux Enforcing:5.0 から必須
  • Scoped Storage(Android 11+):アプリごとのストレージ分離
  • Project Mainline:モジュール式システムコンポーネント更新
  • Generic Kernel Image (GKI):ベンダとの ABI 分離

ここで ANRApplication Not Responding の略で、アプリが一定時間応答しないときの警告である。wakelock は端末を不用意にスリープさせないための仕組み、gralloc は GPU/表示系バッファの割り当て基盤である。GKI は Android カーネルの共通部分を標準化し、端末ベンダ固有部分と分離しやすくする取り組みを指す。

Android バージョン

バージョン コードネーム
4.0 Ice Cream Sandwich 2011
4.4 KitKat 2013
5.0 Lollipop 2014
6.0 Marshmallow 2015
7.0 Nougat 2016
8.0 Oreo 2017
9.0 Pie 2018
10 (英語圏外ドロップ) 2019
11 2020
12/12L 2021/2022
13 2022
14 2023
15 2024
16 2025

AOSP と派生

  • AOSP(Android Open Source Project):ベース
  • Google Android:GMS(Google Mobile Services)+ AOSP
  • Samsung One UIOnePlus OxygenOSXiaomi HyperOSOPPO ColorOSHUAWEI EMUI/HarmonyOS:カスタム ROM
  • LineageOS、GrapheneOS、CalyxOS:プライバシー・カスタム志向
  • Amazon Fire OSKai OS:分岐

iOS / iPadOS

Apple が 2007 年発表、iPhone 専用から iPad(iPadOS 13+)、Apple Watch(watchOS)、Apple TV(tvOS)、Vision Pro(visionOS)へと拡張。

iOS のアーキテクチャ

【図15】iOS アーキテクチャ:

graph TB CT["Cocoa Touch / UIKit, SwiftUI, Foundation, MapKit, GameKit"] MD["Media / Core Animation, Metal, AVFoundation"] CS["Core Services / Core Data, CloudKit, Core Location"] CO["Core OS / libSystem, Security, drivers"] K["XNU Kernel / Mach + BSD + IOKit + iOS-specific additions"] CT --> MD --> CS --> CO --> K

iOS のセキュリティ機構

  • Secure Boot Chain:Boot ROM → LLB → iBoot → Kernel、各段階で署名検証
  • Secure Enclave Processor (SEP):指紋、Face ID、鍵保管
  • Data Protection:per-file AES-256 暗号化、4 段階保護クラス
  • Code Signing:全実行コードは Apple 署名が必要
  • Sandboxing:全アプリは厳格なサンドボックス内で動作
  • App Transport Security (ATS):TLS 強制
  • Privacy Controls:アプリごとの権限(位置、写真、マイク、Bluetooth、トラッキング)
  • Jailbreak:Secure Boot チェーンを破る攻撃、コミュニティは衰退

iPadOS の独自性

  • Stage Manager:ウィンドウマネージャ
  • Scribble、Apple Pencil 統合
  • マウス/トラックパッド対応
  • Swift Playgrounds でのアプリ開発
  • 外部ディスプレイ対応

HarmonyOS、OpenHarmony

Huawei が米国制裁後に独自開発。初期は Android フォーク、現在は完全独立(LiteOS / Linux カーネル、マイクロカーネル設計)。中国市場で急成長。

Tizen、KaiOS

  • Tizen:Samsung テレビ、ウェアラブル
  • KaiOS:フィーチャーフォン(Jio Phone)、低スペック市場

リアルタイムOSと組み込みOS

リアルタイムOS(RTOS)とは

時間制約が正しさの一部となるシステム向け OS。「正しい結果を出す」だけでなく「決められた時間内に出す」が要件。

分類

  • ハードリアルタイム:期限超過 = システム失敗。例:ABS、エアバッグ、航空機制御、心臓ペースメーカ
  • ソフトリアルタイム:期限超過 = 品質低下だが許容。例:動画再生、VoIP、ゲーム

RTOS の要件

  • 決定性:割り込み遅延、タスク切替時間が予測可能
  • 優先度ベーススケジューリング:厳密
  • 優先度継承プロトコル:優先度逆転回避
  • 高速コンテキストスイッチ:μs オーダー
  • 小さなフットプリント:数KB〜数MB
  • 静的解析可能性:WCET(Worst-Case Execution Time)の見積り

主要RTOS

RTOS 開発元 用途
QNX Neutrino BlackBerry 自動車(BMW、Audi、Ford)、原発制御
VxWorks Wind River 火星探査機、B-52、F-35
FreeRTOS AWS IoT、Arduino、ESP32
Zephyr Linux Foundation IoT、ウェアラブル
RTEMS 米 OAR 航空宇宙、CERN
ThreadX / Azure RTOS Microsoft IoT、産業機器
Micrium µC/OS Silicon Labs 組み込み全般
Mbed OS Arm ARM マイコン
Integrity / Integrity-178B Green Hills DO-178B 認証、軍事
Contiki 無線センサネットワーク
TinyOS IoT 学術
NuttX Apache ドローン(PX4)、ウェアラブル

PREEMPT_RT(Linux のリアルタイムパッチ)

Linux カーネルに RT 性を加えるパッチセット。2005 年頃から Ingo Molnár らが開発し、2024 年にメインラインにマージされた。

  • カーネルの多くの spinlocktspinlock_trtmutexrt_mutex に置換(優先度継承対応)
  • 割り込みをスレッド化
  • RCU の RT 対応
  • threadirqs 機能

産業ロボット、3D プリンタ(LinuxCNC)、オーディオワークステーション、株取引システム等で使用。

組み込みLinux

  • Yocto Project / OpenEmbedded:カスタム Linux ディストリ構築フレームワーク
  • Buildroot:軽量、シンプル
  • Ubuntu Core:スナップベース、IoT
  • Raspberry Pi OS(旧 Raspbian):Pi 公式
  • OpenWrt / LEDE:ルータ向け

分散OS・クラウドOS

分散OSの系譜

1980〜90 年代に多くの分散OSが研究された。

  • Amoeba(Tanenbaum):マイクロカーネル、ケーパビリティ
  • Plan 9 from Bell Labs(Unix の設計者たち):「全てはファイル」を徹底
  • Inferno(Plan 9 継承、Java 代替を狙った)
  • SpriteLOCUSMach(CMU、NeXT 経由で macOS へ)

これらは商用的成功は限定的だったが、概念は現代のクラウド・分散システムに継承。

クラウドOS / データセンターOS

  • Kubernetes:事実上のクラウドOS、宣言的 API
  • HashiCorp Nomad:軽量、非 K8s
  • Mesos(D3OS):Twitter、Uber、Airbnb で使用、現在は衰退
  • Google Borg(内部):K8s の先祖
  • Apache YARN / HDFS:Hadoop エコシステム
  • AWS Firecracker + Lambda/Fargate:サーバレス
  • Nomad、Azure Service Fabric、Google Anthos

サーバレス / FaaS

関数単位で実行単位を抽象化。コードだけアップロードし、OS やインフラは管理しない。

  • AWS Lambda(2014):代表的な初期サーバレス基盤
  • Google Cloud Functions, Cloud Run
  • Azure Functions
  • Cloudflare Workers(V8 Isolate ベースのエッジ実行環境)
  • Knative(Kubernetes 上のサーバレス)

OSのパフォーマンス分析とチューニング

4つのゴールデンシグナル

  • レイテンシ(Latency):1 リクエストの遅延
  • トラフィック(Traffic):単位時間あたりの要求数
  • エラー率(Errors)
  • 飽和度(Saturation):リソース使用率、キュー深さ

USE メソッド(Brendan Gregg)

すべてのリソースについて:

  • Utilization:使用率
  • Saturation:待ち行列
  • Errors:エラー数

Linux の観測ツール

CPU/プロセス
  top, htop, atop, btop      — 概観
  ps, pgrep                  — プロセスリスト
  pidstat                    — プロセス別統計
  mpstat                     — CPU別統計
  uptime                     — load average
  vmstat                     — 仮想メモリ統計
  perf                       — ハードウェアカウンタ、CPUプロファイル
  ftrace                     — カーネルトレース
  eBPF (bpftrace, bcc tools) — 万能トレース

メモリ
  free, vmstat
  /proc/meminfo, /proc/buddyinfo, /proc/slabinfo
  slabtop
  pmap, smem
  numastat

ディスク
  iostat, iotop
  dstat
  ioping, fio
  blktrace

ネットワーク
  ss (socket stats)
  ip route, ip addr
  ifstat, nstat
  tcpdump, tshark
  iperf3, netperf
  ethtool

高度
  perf top, perf record, perf report, perf trace
  bpftrace
  SystemTap (廃れつつある)
  LTTng

Brendan Gregg の 60 秒分析

1.  uptime
2.  dmesg | tail
3.  vmstat 1
4.  mpstat -P ALL 1
5.  pidstat 1
6.  iostat -xz 1
7.  free -m
8.  sar -n DEV 1
9.  sar -n TCP,ETCP 1
10. top

チューニング

カーネルパラメータ

/etc/sysctl.confsysctl -w

net.core.somaxconn=65535            # TCP accept queue
net.ipv4.tcp_tw_reuse=1             # TIME_WAIT 再利用
net.ipv4.tcp_fin_timeout=30
net.ipv4.ip_local_port_range=1024 65535
vm.swappiness=10                    # スワップ積極性
vm.dirty_ratio=20                   # dirty ページ上限
fs.file-max=2097152
kernel.pid_max=4194304

ulimit

ソフト / ハードリミット:

ulimit -n 65535    # file descriptor limit
ulimit -u 32768    # process limit
ulimit -s 8192     # stack size KB

/etc/security/limits.conf で永続化。

CPU ガバナー

cpupower frequency-info
cpupower frequency-set -g performance  # performance, powersave, ondemand, schedutil

OSの歴史

初心者向けメモ
OS の歴史はハードウェアの進化と歩調を合わせて発展してきました。バッチ処理 → タイムシェアリング → PC → モバイル → クラウド → AI 統合という大きな流れを押さえれば十分です。

OS の歴史はコンピュータハードウェアの進化と不可分です。五世代に分けて辿ります。

第0世代(1940年代後半〜1950年代前半):OSなき時代

ENIAC(1945)EDSAC(1949)UNIVAC I(1951)。プログラマが物理的にパッチボードを配線し、バイナリを手入力。オペレータが磁気テープを装填し、CPU 使用率は極端に低かった。プログラム同士の切替に数時間かかることもあった。

第1世代(1950年代後半〜1960年代):バッチ処理

IBM 709, 7090、後継 IBM System/360(1964) が業界を席巻。

  • モニタプログラム:ジョブの連続実行を管理(IBSYS, FMS)
  • JCL(Job Control Language):ジョブ記述言語
  • スプーリング:Simultaneous Peripheral Operation On-Line、I/O と CPU の並行化
  • MULTICS(1964〜、MIT+Bell Labs+GE):タイムシェアリング、階層ファイルシステム、仮想メモリの先駆者
  • CTSS(MIT、1961):最初期の本格タイムシェアリングシステム
  • OS/360:System/360 用、360万行コード、Fred Brooks の「人月の神話」はこの経験

第2世代(1970年代):UNIXの誕生とマイコン

UNIX:1969 年 Ken Thompson、Dennis Ritchie(Bell Labs)。MULTICS から撤退したチームが PDP-7 で独自開発。

  • 1969: Unix 第 1 版、アセンブリ
  • 1973: Unix を C で書き直し(初の移植性あるOS)
  • 1975: Version 6、大学へ配布開始
  • 1978: Version 7、UNIX の黄金版
  • 1977: BSD (Berkeley Software Distribution) フォーク開始
  • 1983: System V、AT&T 商用 Unix

BSD Unix:カリフォルニア大学バークレー校、TCP/IP、vi、csh、sendmail を産んだ。

CP/M(1974, Gary Kildall):8ビットマイコン用 OS、後の DOS の原型。

Apple DOS, Apple II(1977):パーソナルコンピュータ革命。

第3世代(1980年代):PC 時代

MS-DOS(1981):IBM PC 用。マイクロソフトが Seattle Computer Products から QDOS を購入し改造。CP/M 風。

Macintosh(1984):Apple が Xerox Alto/PARC の研究を元に、一般消費者向け GUI OS を商用化。System 1 → System 7 → Mac OS 9。

AmigaOSAtari TOSMS OS/2(IBM+MS、後の Windows NT の土台)、Windows 1.0 (1985) → 3.0 (1990):MS-DOS 上の GUI シェル。

Minix(1987, Tanenbaum):教育用マイクロカーネル UNIX クローン。Linus Torvalds が Linux 作成の引き金となる。

GNU プロジェクト(1983, Richard Stallman):「自由なUnix」を目指す。GCC、Bash、Emacs、glibc を生んだが、カーネル GNU Hurd は完成せず。

第4世代(1990年代):Linux、Windows 95、Unix分散

Linux:1991 年 8 月 25 日、Linus Torvalds が comp.os.minix に投稿した「Hello everybody out there using minix - I’m doing a (free) operating system (just a hobby…)」が始まり。1994 年に 1.0 リリース、GPL ライセンス。GNU ユーザ空間と組み合わせた GNU/Linux ディストリビューション(Slackware 1993、Debian 1993、Red Hat 1994、SuSE 1994)が普及。

Windows NT 3.1(1993):Dave Cutler(VMS 設計者)率いる新カーネル。

Windows 95(1995):Windows 3.1 + Windows NT の融合、大ヒット。

BeOS(1995):革新的だった商用 OS、Apple に買収される可能性もあったが、結局 NeXT が選ばれ撤退。現代に Haiku として継承。

Mac OS X 10.0 (2001):NeXTSTEP をベース、Apple が Mach + BSD + Cocoa で完全再設計。

Java OS、JavaOS:Sun が仕掛けた「Java ベース OS」は失敗。

第5世代(2000年代〜現在):モバイル、クラウド、コンテナ、AI

2007: iPhone2008: Android:モバイル OS 時代到来。

2008: Google Chrome OS:Web ベース。

2013: Docker:コンテナ大衆化。

2014: Kubernetes:クラウドオーケストレーション標準。

2020: Apple Silicon(M1):Mac 完全 ARM 移行。

2022: Rust in Linux:Linux カーネルに初めて C 以外の言語が入る。

2023: Windows 11 AI 統合、Copilot

2024〜: Generative AI 統合 OS:Microsoft Copilot+, Apple Intelligence, Android AI 機能。

詳細年表(選抜)

timeline title OS年表 1945 : ENIAC 1956 : GM-NAA I/O (最初期バッチOS) 1961 : CTSS (MIT) 1964 : Multics 開発開始, OS/360 1969 : UNIX (Ken Thompson, Dennis Ritchie) 1973 : UNIX を C 言語化 1977 : BSD Unix (UC Berkeley) 1981 : MS-DOS 1.0 1984 : Macintosh System 1.0 1987 : Minix 1.0 1991 : Linux 0.01 1993 : Windows NT 3.1, Debian, Slackware 1995 : Windows 95 2000 : Windows 2000 2001 : Mac OS X 10.0 2005 : Ubuntu 5.04 2007 : iPhone (iOS) 2008 : Android 1.0 2013 : Docker 2014 : Kubernetes 2015 : Windows 10 2020 : Apple Silicon M1 2021 : Windows 11 2023 : Linux 6.0+ Rust サポート 2024 : Android 15, iOS 18, macOS Sequoia 2025 : Android 16, iOS 19, AI統合強化

現代的トレンドと将来展望

Rust in the Kernel

2022 年、Linux 6.1 で初めて Rust のサポートが入った。段階的に:

  • 6.1: 基本インフラ
  • 6.2: Rust バインディング
  • 6.6: NVMe ドライバ実装進行
  • 今後:ネットワークドライバ、ファイルシステム

Rust の 所有権・借用チェック が、メモリ安全性の多くのバグ(UAF、buffer overflow)を排除する。Google の Android チームが主導。

カーネル バイパス I/O

従来のカーネル経由 I/O はオーバーヘッドが問題。解決策:

  • DPDK(Data Plane Development Kit):NIC を直接ユーザ空間にマップ
  • SPDK(Storage Performance Development Kit):NVMe 直接アクセス
  • VPP(Vector Packet Processing):Cisco 系
  • RDMA(Remote Direct Memory Access):InfiniBand、RoCE

Unikernel / MicroVM の復権

FaaS、エッジコンピューティング、WebAssembly ランタイム統合により、極小・高速起動 OS が再び注目。

WebAssembly System Interface(WASI)

WASM をブラウザ外で動かすための API。ポータブル、サンドボックス、高速。「OS 非依存のアプリコンテナ」となりうるか。

機密計算(Confidential Computing)

  • Intel TDXAMD SEV-SNPARM CCA:VM メモリをハードウェア暗号化
  • Google Cloud Confidential VMAzure Confidential ComputingAWS Nitro Enclaves
  • 金融、ヘルスケア、主権クラウドで需要増

メモリタイプの多様化

  • CXL(Compute Express Link):メモリをネットワーク的にプールし、複数 CPU で共有
  • HBM3/HBM4DDR6:帯域爆増
  • Persistent Memory(3D XPoint、終息)NVRAM

AI / LLM 統合 OS

  • Apple Intelligence:M/A シリーズ Neural Engine + プライベートクラウド
  • Microsoft Copilot+ PC、RecallNPU 必須化
  • Android AICore、Gemini Nano:オンデバイス LLM
  • GPU/NPU スケジューラ:Linux DRM、Windows WDDM、macOS Metal の拡張

サステナブルコンピューティング

電力効率、カーボンアウェアスケジューリング、再生可能エネルギーへの移行。

量子コンピューティング対応OS

量子コンピュータの制御システム(IBM Qiskit、Google Cirq など)はクラシック OS 上で動くが、将来的には量子・クラシックハイブリッドのための新たな抽象が必要となる可能性。


実践リファレンス

必須 Linux コマンド

ファイル操作

ls -la                   # 詳細リスト
cp -r src/ dst/          # 再帰コピー
mv old new               # 移動/改名
rm -rf dir/              # 再帰削除(注意)
ln -s target link        # シンボリックリンク
find / -name "*.conf"    # 検索
locate file              # インデックス検索(mlocate)
stat file                # メタデータ
file file                # 種類判定
tree /etc                # ツリー表示

テキスト処理

cat, less, more, head, tail
grep "pattern" file
sed 's/foo/bar/g' file
awk '{print $1, $NF}' file
sort | uniq -c | sort -rn
cut -d: -f1 /etc/passwd
tr 'a-z' 'A-Z'
wc -l file
diff -u f1 f2

プロセス・ジョブ

ps aux                   # 全プロセス
pgrep -f pattern
kill -TERM <pid>
killall <name>
top / htop / btop
jobs, fg, bg, nohup, disown

ネットワーク

ip addr, ip route, ip link
ss -tulpn                # ソケット統計
dig +short example.com
curl -v https://example.com
wget -r -np
ssh user@host -L 8080:localhost:80
rsync -avz src/ user@host:dst/
nc -lvnp 4444            # netcat

パッケージ管理

# Debian/Ubuntu
apt update && apt upgrade
apt install <pkg>
apt search <pattern>

# RedHat/Fedora
dnf install <pkg>
dnf search <pattern>

# Arch
pacman -Syu
pacman -S <pkg>
yay -S <aur-pkg>

# macOS
brew install <pkg>
brew upgrade

# Windows
winget install <id>
choco install <pkg>

システム情報

uname -a
hostnamectl
lscpu, lsmem, lsblk, lspci, lsusb
uptime, w
who, last
dmesg | tail
journalctl -xe
systemctl status <svc>

重要なシステムコール一覧(Linux, x86-64)

番号 名前 説明
0 read ファイルから読む
1 write ファイルに書く
2 open(legacy)/ 257 openat ファイル開く
3 close fd 閉じる
9 mmap メモリマップ
10 mprotect 保護変更
11 munmap アンマップ
12 brk ヒープ拡張
13 rt_sigaction シグナルハンドラ設定
22 pipe パイプ作成
32 dup fd 複製
39 getpid プロセスID取得
41 socket ソケット作成
42 connect 接続
43 accept 受入
44 sendto UDP送信
45 recvfrom UDP受信
56 clone プロセス/スレッド生成
57 fork プロセス生成
59 execve プログラム実行
60 exit プロセス終了
61 wait4 子プロセス待機
62 kill シグナル送信
63 uname システム情報
78 getdents ディレクトリ読む
79 getcwd 現在ディレクトリ
202 futex 高速ユーザ空間 mutex
218 set_tid_address TID アドレス設定
231 exit_group スレッドグループ終了
232 epoll_wait I/O イベント待ち
233 epoll_ctl epoll 制御
257 openat ディレクトリ相対 open
262 newfstatat stat
281 epoll_pwait signal mask 付き epoll_wait
291 epoll_create1 epoll 作成
318 getrandom 暗号論的乱数
425 io_uring_setup io_uring 初期化
426 io_uring_enter io_uring 実行
427 io_uring_register io_uring 登録
435 clone3 拡張 clone
437 openat2 拡張 openat
439 faccessat2 拡張 access

完全なリストは ausyscall --dump/usr/include/asm/unistd64.h/usr/include/asm/unistd_64.h

signal 一覧

番号 名前 デフォルト 説明
1 SIGHUP Term ハングアップ、設定再読込に慣例
2 SIGINT Term Ctrl-C
3 SIGQUIT Core Ctrl-\、コアダンプ
4 SIGILL Core 不正命令
5 SIGTRAP Core デバッガ
6 SIGABRT Core abort(3)
7 SIGBUS Core バスエラー
8 SIGFPE Core 浮動小数点例外
9 SIGKILL Term 強制終了(ハンドル不可)
10 SIGUSR1 Term ユーザ1
11 SIGSEGV Core セグフォルト
12 SIGUSR2 Term ユーザ2
13 SIGPIPE Term 閉じたパイプ書込
14 SIGALRM Term alarm(2)
15 SIGTERM Term 終了要求(捕捉可)
17 SIGCHLD Ign 子プロセス状態変化
18 SIGCONT Cont 再開
19 SIGSTOP Stop 停止(ハンドル不可)
20 SIGTSTP Stop Ctrl-Z
23 SIGURG Ign 帯域外データ
24 SIGXCPU Core CPU時間制限超過
25 SIGXFSZ Core ファイルサイズ制限超過

補足

第6章 オペレーティングシステム

初心者向けメモ
OS は「アプリとハードウェアの仲介者」です。プロセス・メモリ・ファイル・デバイスという 4 つの主要機能と、アプリから OS を呼び出すシステムコールの概念を掴みます。
要点
OS は、CPU 時間、メモリ、ファイル、デバイスを複数のプログラムで安全に共有するための仕組みです。本章ではブラックボックスに見える OS の役割を分解して見ます。

この章が実務で役立つ場面

  • プロセス異常終了、OOM、権限エラーの調査
  • ファイル I/O やソケット I/O の理解
  • コンテナや Linux 上のアプリの挙動理解

6.1 OS の役割

OS は、アプリケーションとハードウェアの間に立ち、

  • プロセス管理
  • メモリ管理
  • ファイル管理
  • デバイス管理

を行います。

【図11】OS の立ち位置:

flowchart TB A["アプリケーション"] --> B["システムコール"] B --> C["OS"] C --> D["CPU / メモリ / ディスク / NIC"]

6.2 プロセスとスレッド

プロセス

独立した実行単位です。通常は独自の仮想メモリ空間を持ちます。実行中の位置を表すプログラムカウンタやスタックポインタ、レジスタ群といった「いまどこを実行しているか」の状態も含めて考えます。

スレッド

同じプロセス内で資源を共有しながら並行に動く実行単位です。複数のスレッドは同じコード領域やヒープを共有できますが、それぞれが自分のレジスタ状態やスタックを持ちます。

【図12】プロセス内のスレッド構造:

flowchart TB A["プロセス"] --> B["スレッド1"] A --> C["スレッド2"] A --> D["共有メモリ・共有資源"]

直感としては、

  • プロセス = ひとつの独立した作業部屋
  • スレッド = その部屋の中で同時に動く作業者

です。部屋が分かれていれば勝手に机の上を触られにくい一方、同じ部屋の作業者どうしは速く連携できる代わりに、ぶつかりやすくもなります。

6.3 システムコール

アプリケーションは、OS の機能を直接たたくのではなく、システムコールを通じて使います。

例:

  • open
  • read
  • write
  • fork
  • exec

fork は現在のプロセスを複製して子プロセスを作る操作です。Linux では copy-on-write が使われるので、「最初から全部のメモリを丸ごとコピーする」と理解すると少しずれます。まずは同じ内容を共有し、書き込みが起きたところから実体化していきます。

exec は「いまのプロセスの中身を別のプログラムに入れ替える」操作です。新しいプログラムでスタックやヒープも初期化されます。Unix 系でよく見る forkexec という流れは、

  1. まず子プロセスを作る
  2. その子を別プログラムへ置き換える

という二段階です。

【図13】fork と exec の流れ:

flowchart LR A["親プロセス"] --> B["fork"] B --> C["子プロセス作成"] C --> D["exec"] D --> E["別プログラムとして実行開始"]

6.3.1 ファイル記述子という共通の窓口

Unix 系 OS では、ファイル、パイプ、ソケットなど多くの資源が「ファイル記述子」という共通の窓口で扱われます。read() は「ファイルから読む関数」というより、ファイル記述子から読む関数 です。

この見方を持つと、

  • ファイル I/O
  • パイプ通信
  • ソケット通信

が、OS から見るとかなり似た形で扱える理由が見えてきます。

6.3.2 mmap はなぜ大事か

mmap はファイルやデバイスをメモリ空間へ写像する仕組みです。これにより、アプリケーションは「読む API を何度も呼ぶ」代わりに、「メモリを読むように」ファイル内容へアクセスできます。

直感としては、

  • read = データをコピーして受け取る
  • mmap = その内容がある領域を自分のアドレス空間へつなぐ

という違いです。

【図14】mmap の概念:

flowchart LR A["ファイル"] --> B["mmap"] B --> C["仮想メモリ空間に写像"] C --> D["通常のメモリアクセスのように読む"]

6.4 スケジューリング

OS は「いまどの実行主体に CPU を使わせるか」を決めます。

考えるべき観点:

  • 公平性
  • 応答性
  • 優先度
  • リアルタイム性

6.4.1 スケジューリングを日常の比喩で見る

スケジューリングは、1 台のコピー機を複数人で使う状況に似ています。

  • 1 人が長く占有しすぎると不公平
  • 短い作業は早く終わらせたほうが体感がよい
  • 締切のある仕事は優先したい

このバランスを取るのが OS です。

サーバ OS、デスクトップ OS、リアルタイム OS で重点が違うのも自然です。サーバでは throughput、デスクトップでは応答性、リアルタイムでは期限遵守がより重要になります。

6.5 コンテキストスイッチ

CPU がある実行主体から別の実行主体へ切り替わるとき、状態保存と復元が必要です。これがオーバーヘッドになります。

【図15】コンテキストスイッチの流れ:

flowchart LR A["実行中のスレッドA"] --> B["状態保存"] B --> C["次のスレッド選択"] C --> D["状態復元"] D --> E["スレッドB実行"]

6.6 仮想メモリ

各プロセスに「連続して広いメモリ空間があるように見せる」仕組みです。実際にはページ単位で管理されます。

仮想メモリの利点:

  • プロセス隔離
  • 保護
  • 見通しのよいアドレス空間
  • ディスクとの連携による大きな見かけの空間

OS の観点では、仮想メモリは単なる「ごまかし」ではありません。物理メモリの複雑さを隠しつつ、必要なページだけを主記憶に置く demand paging と、プロセス間の保護や共有を両立するための中心的な仕組みです。

【図15-2】仮想アドレスから物理メモリまで:

flowchart LR A["プロセスの仮想アドレス"] --> B["ページテーブル参照"] B --> C["物理メモリ上のページ"] B --> D["未配置ならページフォルト"] D --> C

6.7 ページとページフォルト

メモリはページという小さな単位で管理されます。必要なページがまだ物理メモリへ載っていないと、ページフォルトが起きて OS が対応します。

【図16】ページフォルトの処理フロー:

flowchart LR A["仮想アドレスへアクセス"] --> B["ページテーブル確認"] B --> C["物理ページあり"] B --> D["物理ページなし"] D --> E["ページフォルト"] E --> F["OS がページを用意"]

ページフォルトという名前は少し怖く見えますが、実際には「必要になったので今読み込む」という正常系の動作も多いです。異常になるのは、アクセス権がない場所を読もうとした、存在しない領域を触った、などのケースです。

6.8 ファイルシステム

ファイルシステムは、ストレージ上のデータを

  • ファイル
  • ディレクトリ
  • パス
  • 権限

として扱えるようにします。

6.8.1 永続化とジャーナリング

ファイルシステムで難しいのは、「途中で電源が落ちても壊れにくくすること」です。

そこで使われる考え方の1つが ジャーナリング です。これは、いきなり本体を書き換える前に、

  1. これから何を変えるかを書き残す
  2. 本体を更新する
  3. 完了したら記録を確定する

という順で進める方法です。

これにより、クラッシュ後にも「どこまで終わったか」を追いやすくなります。データベースのログやトランザクションとも発想が似ています。

6.8.2 同期 I/O と非同期 I/O

I/O の扱い方には、大きく

  • 同期 I/O: 終わるまで呼び出し側が待つ
  • 非同期 I/O: 依頼だけ出して、完了はあとで受け取る

という違いがあります。

これはレストランで、

  • 同期 = 自分で厨房の前に立って待つ
  • 非同期 = 呼び出しベルを受け取って、終わるまで別のことをする

ような違いです。

高負荷サーバや GUI アプリで非同期 I/O が重要なのは、CPU を遊ばせにくくできるからです。ただし、コードの流れは少し複雑になります。

6.9 なぜ OS が大事か

高級言語で書いたコードも、最終的には

  • メモリをどう取るか
  • ファイルをどう開くか
  • プロセスをどう起こすか
  • ネットワークをどう使うか

で OS に深く依存します。

6.10 ミニ比較表

概念 何をしているか 混同しやすいもの 違い
プロセス 独立した実行単位 スレッド 通常はメモリ空間を分ける
スレッド 共有しながら並行実行 プロセス 共有資源が多い
仮想メモリ 見かけのアドレス空間 物理メモリ 実在の RAM とは別
システムコール OS への入口 ライブラリ関数 ライブラリの裏で OS を呼ぶこともある

6.11 よくある誤解

よくある誤解
スレッドは「軽いプロセス」ですが、軽いから簡単というわけではありません。共有メモリゆえに競合やデッドロックの問題が増えます。

6.12 例題

【図17】OS に関する問題の切り分け:

flowchart LR A["問題を見る"] --> B["CPU / メモリ / ファイル / プロセスのどれか判定"] B --> C["OS の責務に対応づける"] C --> D["適切な概念で説明する"]

例題1: read() がライブラリ関数ではなく OS の機能にも関係するのはなぜか。

解説: 実際のファイルやデバイスアクセスは OS が管理しているからです。

例題2: プロセスとスレッドの最も大きな違いを一文で述べよ。

解説: 通常、プロセスは独立したメモリ空間を持ち、スレッドは同じプロセス内でそれを共有します。

例題3: ページフォルトは必ず異常終了を意味するか。

解説: 意味しません。必要なページを読み込む正常なページフォルトもあります。

6.13 練習問題

  1. OS の4つの主要責務を挙げよ。
  2. 仮想メモリの利点を1つ述べよ。
  3. forkexec はそれぞれ何をするか。
  4. コンテキストスイッチにコストがかかる理由を一文で述べよ。

6.14 練習問題の答え

  1. プロセス管理、メモリ管理、ファイル管理、デバイス管理
  2. 例: プロセス隔離、広い見かけの空間
  3. fork は複製、exec は新しいプログラムへ置換
  4. 状態保存と復元が必要だから

6.15 ユースケース

Web サーバ

  • プロセスやスレッドで同時接続をさばく
  • ファイルとソケットを扱う
  • メモリ管理とスケジューリングの影響を受ける

コンテナ

  • 名前空間や cgroups によって資源を分離
  • OS の仕組みの上に乗っている

まとめ

オペレーティングシステムは、資源管理、抽象化、分離を担う土台です。プロセス、メモリ、ファイル、I/O、仮想化までをまとめて見ると、アプリケーションの下で何が起きているかが立体的に見えてきます。