Linux とは — アーキテクチャ・コマンド・主要ディストリビューション のサムネイル

Linux とは — アーキテクチャ・コマンド・主要ディストリビューション

⏱ 約 19 分 view 73 like 0 LOG_DATE:2026-05-10
目次 / TOC

Linux #

Linux は、世界の サーバ・クラウド・スマートフォン (Android)・組み込み機器・スーパーコンピュータ の大半を動かしているオープンソースの OS — と言いたくなるが、厳密には Linux は「カーネル」だけを指す名前で、ユーザが日常的に触る「Linux」は GNU ユーザランド + ディストリビューション固有のグルー が積み上がった全体である。Richard Stallman が「GNU/Linux」と呼ぶことに固執するのも、この層構造の事実を反映している。

それでも「Linux」は実用的には 「Linux カーネルが動いている UNIX 系 OS のエコシステム全体」を指す呼称として広く通じる。本稿は最初にこの 3 層構造を整理し、次にカーネルとユーザランドがシステムコールで切れているという UNIX/Linux の根本設計、「すべてはファイル」という統一抽象、プロセス / 権限 / シェルという日常の使用感を作っている層、そして namespaces + cgroups から自然に出てきたコンテナ革命 までを、「Linux を 1 枚絵で理解する」 粒度で扱う。

1. Linux とは何 — 「カーネルだけ」と「OS 全体」の二重の意味 #

「Linux」という単語の多層性を最初に分解する。

内容
カーネル プロセス管理 / メモリ管理 / ファイルシステム / ネットワーク / デバイスドライバ。唯一「Linus Torvalds とコミュニティが管理する Linux」 linux-6.x (kernel.org)
ユーザランド (GNU + 周辺) ライブラリ (glibc / musl)、シェル (bash / zsh)、coreutils (ls cp cat)、GNU ツールチェーン (gcc / binutils) GNU project + util-linux + systemd
ディストリビューション カーネル + ユーザランド + パッケージマネージャ + 独自の設定 / 起動スクリプト / リリースポリシー Debian, Ubuntu, RHEL, Fedora, Arch, Alpine, Android

つまり「Ubuntu を入れた」 = 「Linux カーネル + GNU ツールチェーン + Debian パッケージング + Canonical 独自の Snap / Netplan / 設定」を 1 つにまとめたディストリを入れた、ということ。Android も Linux カーネルを使っているが、GNU ユーザランドではなく Bionic libc + Java/ART を載せているため「Linux」と呼ぶかどうかは微妙な扱いになる (kernel.org 的には Linux)。

自由ソフトウェア (Free Software)」 vs 「オープンソース (Open Source)」の哲学的議論はこの背景にあるが、実用上はどちらも GPL/MIT/Apache 等のライセンスでソースが公開されている点が本質。Linux カーネル自体は GPLv2 で、これが Android メーカーがカーネル変更を公開する義務の根拠になっている。

2. アーキテクチャ — カーネルとユーザランドはシステムコールで切れている #

Linux (UNIX 系全般) の設計の核は、カーネル空間とユーザ空間が CPU の特権レベルで物理的に分離されていること。ユーザプロセスはハードウェアに直接触れない、必ず システムコール という決められた入り口を通してカーネルに依頼する。

Linux アーキテクチャ — Hardware からアプリまでの層構造 「カーネル空間 / ユーザ空間」は CPU 特権レベルで物理分離 / システムコールが唯一の入口 Application — ユーザが書く / 入れたソフト nginx / PostgreSQL / Firefox / Python スクリプト / vim / Docker クライアント など User Land — シェル + GNU coreutils + ライブラリ + デーモン (= 「OS の見た目」を作る部分) bash/zsh / ls,cp,cat,grep / glibc/musl / systemd / sshd / cron / Wayland/Xorg ───── system call interface (read / write / open / fork / exec / mmap / socket / ...) ───── Kernel — Linus Torvalds が管理している唯一の「Linux」 Process / Sched CFS / EEVDF PID, タスク状態 シグナル, futex cgroups namespaces Memory 仮想記憶 (MMU) ページキャッシュ slab allocator OOM killer swap VFS / FS ext4 / XFS / Btrfs tmpfs / procfs FUSE / NFS / overlayfs page cache io_uring Network TCP/IP スタック netfilter / nftables XDP / eBPF routing / qdisc socket layer + Device Drivers — NIC, GPU, NVMe, USB, ACPI, audio … (kernel modules で動的ロード可) Hardware — CPU / メモリ / ストレージ / NIC / GPU / 周辺機器 Linux 自体はこの層には触らない / ハード固有の差異はドライバが吸収する syscall は ~400 個 / 例: read=0, write=1, open=2, fork=57, execve=59, mmap=9, socket=41, futex=202 (x86_64)

押さえどころ:

  • カーネルは決して「アプリの一部」ではない。アプリは read() write() open() fork() socket() といった 400 ほどのシステムコールを通してしかカーネルにアクセスできない。「strace で実行を追える」のはこの境界が明確だから
  • GNU ユーザランドは「Linux カーネルとは別プロジェクト」lscatGNU coreutils が提供しており、Linux カーネルとは独立に開発されている。Alpine Linux のようにユーザランドを musl + BusyBox で軽量化 すると、同じカーネルでも全く別の OS の使用感になる。
  • systemd は「カーネルとユーザランドの間の現代的な接着剤」。プロセス管理 / cgroups / ロギング / ネットワーク設定 / DNS / 起動順序 — 従来は別個に存在していた仕組みを統合した。サービスを systemctl start nginx で起動するときに動いているのはユーザ空間の PID 1 デーモン
  • ドライバの動的ロードlsmod で見える kernel module が、必要に応じて modprobe で読み込まれている。Linux カーネルの実行中に新しいデバイスが繋がっても再起動なしで動くのはこの仕組み。
# システムコールを実況中継 (アプリが何をカーネルに頼んでいるか)
strace -f -e trace=openat,read,write ls /tmp

# カーネルバージョンとビルド設定
uname -a
cat /proc/version

# ロード済みカーネルモジュール
lsmod

# システム全体のシステムコール統計 (要 perf)
sudo perf stat -e 'syscalls:sys_enter_*' -a sleep 5

3. すべてはファイル — UNIX が世界に貢献した最大の抽象 #

すべてはファイル」(Everything is a file) は UNIX 哲学の中で最も影響力が大きい設計判断通常ファイル、ディレクトリ、デバイス、パイプ、ソケット、シンボリックリンク全て同じ read()/write()/open()/close() の API で扱えることで、プログラムが「相手が何か」を意識せずに合成可能になった。grep foo /var/log/sysloggrep foo < /dev/ttyS0 (シリアルポート) も cat hello | grep foo同じ read() の呼び出し — これが UNIX のシンプルさと強さの本体。

「すべてはファイル」 — Linux の 7 種のファイルタイプと特殊 FS どれも read() / write() / open() / close() で扱える / `ls -l` 先頭 1 文字で見分ける - (regular) 通常ファイル テキスト/バイナリ /etc/hosts /bin/ls d (directory) ディレクトリ 名前→inode 一覧 /home /etc /tmp l (symlink) シンボリックリンク 他パスへの参照 /lib → /usr/lib c (char dev) キャラクタデバイス バイト単位 I/O /dev/tty /dev/null b (block dev) ブロックデバイス ブロック単位 I/O /dev/sda /dev/nvme0n1 p (FIFO) 名前付きパイプ mkfifo s (sock) UNIX socket ▼ /dev — 物理 / 仮想デバイスへの入口 (デバイスファイル) /dev/null (書き込み破棄, 読み取り EOF) /dev/zero (読み取りで永遠に 0) /dev/random /dev/urandom (カーネル乱数) /dev/sda /dev/nvme0n1 (ストレージ) /dev/tty1〜 (仮想コンソール) /dev/ttyS0 (シリアル) /dev/loop0 (ループバック) ▼ /proc — カーネルとプロセスの内部状態を「ファイルとして」公開する仮想 FS /proc/cpuinfo /proc/meminfo /proc/loadavg /proc/uptime /proc/version /proc/PID/status /proc/PID/cmdline /proc/PID/maps /proc/PID/fd/ (プロセスごと) /proc/sys/net/ipv4/ip_forward (sysctl) — 書くとカーネル設定が変わる ▼ /sys — sysfs: デバイスとドライバの階層を「ディレクトリツリー」として公開 /sys/class/net/eth0/ (NIC の statistics, MTU, address …) /sys/block/sda/queue/ (ブロックデバイスの I/O スケジューラ等) /sys/class/thermal/ (温度センサ) /sys/class/leds/ (LED 制御) /proc, /sys, /dev は再起動するたびにカーネルが作り直す → ディスクには存在しない

特に重要な概念:

  • /devハードウェアと仮想デバイスへの入口echo "hello" > /dev/tty1 で 1 番目の仮想コンソールに出力する、dd if=/dev/zero of=test.bin bs=1M count=100 で 100 MB のゼロ詰めファイルを作る — どちらも普通のファイルへの書き込みと同じ syscallで動く。
  • /procカーネルがその場で生成する仮想 FS/proc/PID/mapsプロセスのメモリマッピング/proc/PID/fd/そのプロセスが開いているファイルディスクリプタが見える。ディスク上には何もないcat した瞬間にカーネルがテキストを生成している。
  • /sysカーネル内部のオブジェクト階層 (デバイス・バス・クラス) をディレクトリツリーとして公開するもの。NIC の MAC アドレスを変更する echo 02:11:22:33:44:55 > /sys/class/net/eth0/address のような操作が可能。
  • シンボリックリンク (l で始まる) は他のパスへの参照で、Windows のショートカットに似ているがカーネルが透過的に解決する点が違う。/lib → /usr/lib のような統合や、Deployer の current/ → releases/56 のような切替に多用される。
# ファイルタイプ確認
ls -l /dev/null /etc/hosts /lib /tmp/.X11-unix/X0
stat -c '%F %n' /dev/sda /proc/meminfo /sys/class/net/eth0

# プロセス情報を /proc から拾う
ls /proc/$$/fd                       # 自分のシェルが開いている FD
cat /proc/$$/maps                    # メモリマッピング
cat /proc/$$/status                  # 状態 (VmRSS 等)

# sysfs / sysctl で動的に設定変更
sudo sysctl -w net.ipv4.ip_forward=1
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward    # 同じこと

4. プロセスとシグナル — fork/exec と PID 1 #

Linux のプロセスモデルは fork() でコピー → exec() で別プログラムに置換」 という UNIX 由来の独特な設計。bash から ls を起動するとき、シェルは:

  1. fork() で自分のコピーを作る (子プロセス, 親と同じメモリ・FD を持つ)
  2. 子プロセスが execve("/bin/ls", ...)自分自身を ls プログラムに置換 (PID は変わらず)
  3. 親シェルは waitpid() で子の終了を待つ

これが 「全プロセスは PID 1 から派生する 1 本の系図 (プロセスツリー) を成す」 の根拠。pstree で見ると、systemd (PID 1) → sshdbashvim のように、自分の祖先を遡れる親プロセスが先に死ぬと、子は孤児になり PID 1 (systemd) が引き取るルール (init による reaping) が現代でも健在。

シグナルプロセス間の非同期通知。Ctrl+C で送られる SIGINTkill PID (デフォルト SIGTERM)、kill -9 PID (SIGKILL — プロセスから捕捉不能, 強制終了)、メモリエラー SIGSEGV など 31 種類が定義されている。SIGKILLSIGSTOP だけはプロセスがハンドラを設定できない (ユーザがどうしても止められる手段を残すため)。

# プロセスツリーを見る
pstree -p $$                         # 自分のシェルから祖先まで

# 状態とリソース
ps -ef                               # 全プロセス (UNIX 形式)
ps auxf                              # ツリー表示 (BSD 形式)
top  /  htop                         # リアルタイム
ss -tnp  /  lsof -p PID              # PID が開いている接続/ファイル

# シグナル送信
kill -SIGTERM PID                    # 礼儀正しく頼む (アプリは cleanup できる)
kill -9 PID                          # 強制終了 (リソースリークの危険)
kill -SIGUSR1 PID                    # アプリ独自の通知 (nginx のログローテーション等)

ゾンビ (Z 状態) = 子が exit したが親が wait() を呼んでいないプロセス。リソースは解放済みで PID とプロセステーブルエントリだけ残っている状態。ゾンビが大量発生する場合は親プロセスのバグ (子の終了を待っていない) で、PID 空間を食い潰すと新規プロセスが起動できなくなる。

5. 権限モデル — UID/GID/rwx → setuid → capabilities → namespaces #

UNIX の権限モデルは UID (ユーザ ID) + GID (グループ ID) + 各ファイルの rwx 9 bit という単純な仕組みから出発した。ls -l-rwxr-xr-x の 9 文字は 「所有者 rwx / グループ rwx / その他 rwx」 の並び。

UID 0 = rootすべての権限を持つ特権ユーザで、普段の作業はできるだけ非 root で行う + 必要な瞬間だけ sudo が現代のセキュリティ運用の基本。

しかし**「rwx だけでは粒度が足りない」**シーンが何度もあり、段階的に拡張されてきた:

機能 何を解決したか
setuid / setgid bit passwd コマンドが /etc/shadow を更新するために、一般ユーザの実行でも root 権限で動く必要があった → 実行ファイルに setuid bit を立てると実行時だけ所有者の権限になる乱用するとローカル特権昇格の温床になるため、検出 (find / -perm -4000) が侵入後解析の定番
POSIX ACL rwx の「所有者・グループ・その他」3 段階では 複数ユーザに別々の権限が与えられない → setfaclファイル単位に細かく
Capabilities 「root の権限を全部寄越せ」ではなく 40 個ほどの能力に分割 (CAP_NET_BIND_SERVICE = 1024 番未満ポートを開ける, CAP_NET_ADMIN = ネットワーク設定, CAP_SYS_ADMIN = なんでも) → デーモンに必要最小限だけ与える ことが可能に
MAC (Mandatory Access Control) rwx は DAC (Discretionary) で「ファイルの所有者が自由に決める」 → SELinux / AppArmorシステム全体のポリシーで「この binary はこの操作だけ」を強制
Namespaces + cgroups プロセスごとに別の世界 (PID 空間 / FS / ネットワーク / UID マッピング) を見せる」「CPU / メモリ / I/O を制限する」 → これがコンテナの正体 (§7)
# 基本の権限
ls -l /etc/shadow                    # `-rw-r-----` root:shadow → 一般ユーザは見えない
chmod 600 ~/.ssh/id_ed25519          # SSH 秘密鍵は 600 (= rw------- 所有者のみ)

# setuid を探す (システムに何があるか把握する基本)
find / -perm -4000 -type f 2>/dev/null

# capabilities (root を分割する)
sudo setcap cap_net_bind_service=+ep /usr/bin/python3.11
# → python が root でなくても 80/443 を bind 可能

# SELinux (RHEL 系) のステータス確認
sestatus
ls -lZ /var/www/html

# sudo の設定 (NOPASSWD は限定的に)
sudo visudo                          # /etc/sudoers の安全な編集

6. シェルがすべてを繋ぐ — pipe と標準入出力 #

Linux/UNIX の生産性の本質は、小さな単機能プログラムを | で繋ぎ合わせて何でも作れること。これを実現しているのが 「すべてはファイル」 + 標準入出力 (stdin / stdout / stderr) + パイプ (|)

┌──────┐  stdout    stdin  ┌──────┐  stdout   stdin  ┌──────┐
│ ls   │ ─────────────────→│ grep │ ────────────────→│ wc   │
└──────┘                   └──────┘                  └──────┘

ls | grep '\.log$' | wc -l3 つの独立プロセスを同時に起動し、stdout を次のプロセスの stdin に直結することで「カレントディレクトリの .log 拡張子のファイル数」を 1 行で計算する。カーネルがパイプ (FIFO バッファ) を仲介しており、プロセス間メモリは共有しない

要素 意味
cmd > file stdout をファイルに 上書き
cmd >> file stdout を 追記
cmd 2> err.log stderr のみをファイルへ
cmd 2>&1 stderr を stdout にマージ
cmd < file stdin をファイルから
cmd1 | cmd2 cmd1 の stdout を cmd2 の stdin に
cmd1 ; cmd2 順次実行 (前者の終了コードを問わず)
cmd1 && cmd2 前者が 成功 (exit 0) したときだけ後者
cmd1 || cmd2 前者が 失敗 したときだけ後者

終了コード (exit code)プログラム間の最重要な戻り値0 = 成功それ以外 = 何らかの失敗。シェルスクリプトはこれで分岐し、CI/CD はこれで「ビルド成功か失敗か」を判定する。

環境変数 (PATH, HOME, LANG, LD_LIBRARY_PATH …) は親プロセスから子プロセスにコピーで伝わるexport FOO=bar でその後起動する子プロセスに渡る。bash の set -euo pipefail は「未定義変数で死ぬ / エラー終了で即停止 / パイプ途中の失敗も検出」というスクリプトの安全装備の定型。

7. ディストリビューション — どれを選ぶか #

「Linux を入れる」 = 「ディストリを選ぶ」。カーネルは同じでも、パッケージマネージャ・リリースサイクル・標準デーモン・コミュニティの色が違う。

ディストリ 系統 パッケージ 特徴 / 使われる場面
Debian 元祖 apt (.deb) 安定第一・コミュニティ駆動・サーバ用途で長期に強い
Ubuntu Debian 派生 apt デスクトップで最普及・LTS リリース・ビジネス向け Canonical サポート
RHEL (Red Hat Enterprise Linux) 商用 dnf (.rpm) エンタープライズ実本番標準・サブスクリプション・10 年サポート
Fedora RHEL 上流 dnf 最新機能の人柱・RHEL に降りていく前のテストベッド
CentOS Stream / Rocky / AlmaLinux RHEL 互換 dnf 旧 CentOS の後継 — Rocky / Alma がバイナリ互換
Arch Linux 独立系 pacman ローリングリリース・最新志向・自分で組む派・ArchWiki が世界一の Linux 文書
Alpine Linux 独立系 apk musl + BusyBox で極小 (~5 MB)Docker イメージのデフォルトベースとして爆発的普及
Android Google (独自) Linux カーネル + Bionic libc + Java/ART — 世界最普及の Linux
WSL2 (Windows 上) Microsoft 親ディストリに依る Windows 上で動く Linux カーネル (Hyper-V VM) — 開発環境として急速に普及

選び方の指針:

  • 本番サーバRHEL / Rocky / Ubuntu LTS (10 年サポート・エンタープライズ実績)
  • 開発機 / デスクトップUbuntu / Fedora / Arch (好み次第)
  • コンテナベースAlpine (小さい) または Debian slim / Ubuntu minimal (互換性重視)
  • 古いハードの再生軽量派生 (Lubuntu, MX Linux …)
  • 学習用Arch (pacstrap で 0 から組む経験) または Debian (デフォルトで最小限)

8. コンテナ革命 — namespaces + cgroups から自然に出てきた #

Docker / Kubernetes が席巻した 2010 年代後半は、Linux にとって何が起きたのか? 答えは 「Linux カーネルにもとから入っていた 2 つの機能を組合せて使い始めただけ」:

  • namespaces (PID / network / mount / UTS / IPC / user) — プロセスごとに別の世界を見せる
    • PID namespace: コンテナ内では ps で自分のプロセスしか見えない
    • network namespace: 独自の eth0 / ルーティングテーブルを持つ
    • mount namespace: 独自のファイルシステム/ として見る
    • user namespace: コンテナ内 root がホストから見ると非 root (rootless container)
  • cgroups (control groups) — CPU / メモリ / I/O / pid 数プロセス群単位で制限・計測

これに overlayfs (積層ファイルシステム) を組合せると、「ホスト OS の上に独立したミニ OS をプロセス単位で動かす」 = コンテナ になる。Docker は最初これらを lxc 経由で使い、後に runc を作って独自実装、現代は OCI runtime 標準 に至っている。

「コンテナは仮想マシンより軽い」のは、ハードウェア仮想化 (Hyper-V, KVM, VMware) を経由しないから — カーネルはホストと共有し、プロセス分離だけでハードウェアエミュレーションはしない。代償としてカーネル脆弱性が出るとコンテナの分離が崩れる (CVE-2022-0185, CVE-2024-1086 などが有名)。

# コンテナの中身を「ただの Linux プロセス」として見る
docker inspect --format '{{.State.Pid}}' my-container    # ホスト上の PID
ls /proc/<PID>/ns                                        # その PID の namespaces
nsenter -t <PID> -n -p ip addr                           # ネットワーク namespace に入って ip 確認
cat /sys/fs/cgroup/system.slice/docker-<ID>.scope/cpu.stat  # cgroups の CPU 統計

Kubernetes はこの上にもう 1 段「コンテナをクラスタで自動配置・自動修復・自動スケール」する制御平面を被せたもの。Linux カーネルがコンテナを動かし、Kubernetes がそれを管理する という 2 層構造。

9. 現代の Linux はどこで動いているか #

場所 シェア / 状況
クラウドサーバ 95% 以上。AWS EC2 / Azure VM / GCP CE のデフォルトイメージは Linux。マネージド DB・Kubernetes ワーカー・Lambda・Fargate もすべて Linux 上
スマートフォン (Android) 世界の 70%+ が Android = Linux カーネル。世界で最も普及した OS
組み込み機器 ルータ・テレビ・冷蔵庫・自動車・産業機器・スマートウォッチ・IoT — 無数に動いているが見えない
スーパーコンピュータ TOP500 の 100% が Linux (2017 以降)。HPC は事実上 Linux しかない
デスクトップ ~3-5%。Windows / macOS が圧倒的、ただし開発者・科学者・エンジニアコミュニティでは大きい
WSL2 (Windows 上) 急成長。Microsoft が公式に Linux カーネルを Windows に同梱 という時代

サーバとモバイルとあらゆる埋め込み機器を支えているが、デスクトップだけは少数派」というのが Linux の現代の立ち位置。Windows と macOS は OS 製品として競合するが、Linux はインフラとしての OS で別レイヤを占めている


Linux は 「Linus Torvalds が 1991 年に趣味で書いたカーネル」 から始まり、「世界の半分以上のコンピューティングを支える OS のエコシステム全体」を指す呼称になった。理解の鍵は 「カーネル = Linux 本体」「ユーザランド = GNU + ディストリ」「両者は syscall で物理分離されている」 という 3 層構造、そして 「すべてはファイル」「fork/exec」「pipe + 終了コード」「rwx → capabilities → namespaces」 という UNIX 由来の設計判断が現代までそのまま生き続けていることを押さえることにある。

クラウドもコンテナもスマートフォンも、「Linux の設計思想がそのまま現代インフラに通用している」事実の上に成立している。コンテナは「Linux の機能を新しい組み方で使い始めただけ」Kubernetes は「Linux 上のコンテナを管理するもう 1 段」、サーバレスは「Linux カーネル上の極小 VM (Firecracker 等) で関数を動かすもの」 — どこを掘っても Linux の syscall と namespaces と cgroups に行き着く。Linux を 1 度ちゃんと理解すると、現代インフラのほとんどに同じ語彙で対峙できるようになる。