Chapter 01

Linux 简史与哲学

从一封邮件到统治世界——理解 Linux 的诞生故事、设计哲学与"一切皆文件"的核心思想

Linux 的诞生

1991 年的那封邮件

1991 年 8 月 25 日,芬兰赫尔辛基大学一名 21 岁的学生 Linus Benedict Torvalds 在 Usenet 新闻组 comp.os.minix 发布了一条消息,措辞极其谦虚:

大家好——我正在为 386(486) AT 克隆机做一个(免费的)操作系统
(只是一个爱好,不会是 GNU 那样的大东西也不专业)。
自四月份以来一直在酝酿,开始有了成果……

这个"爱好项目"就是 Linux 内核。Linus 的动机很简单:他想在自己新买的 386 PC 上运行类 UNIX 系统,但 UNIX 太贵,Minix 又有太多限制(不允许商业使用)。于是他决定自己写一个。三十年后,这个"爱好"成为了世界上使用最广泛的操作系统内核。

关键时间线

1969 年
AT&T 贝尔实验室的 Ken Thompson 和 Dennis Ritchie 开发了 UNIX,这是 Linux 所有精神祖先的源头。UNIX 首次提出了"一切皆文件"和小型工具组合的设计哲学。
1983 年
Richard Stallman 发起 GNU 项目,目标是创建一个完全自由的 UNIX 兼容操作系统。GNU 提供了大量工具(gcc、bash、glibc 等),但缺少内核(Hurd 内核一直未完成)。
1991 年
Linus Torvalds 发布 Linux 内核 0.01(约 10,000 行代码)。Linux 内核 + GNU 工具 = 完整的操作系统(GNU/Linux)。互联网使全球开发者得以协作贡献代码。
1992 年
Linux 采用 GPL v2(GNU 通用公共许可证),任何人都可以免费使用、修改和分发,但修改后的版本必须以相同条款开放源码,开源精神得到法律保障。
1993—2000 年
Slackware(1993)、Debian(1993)、Red Hat(1994)相继发布。Linux 服务器市场份额快速增长,开始进入企业数据中心。
2004 年
Ubuntu 1.0 发布,由 Mark Shuttleworth 和 Canonical 公司打造,专注桌面用户体验,提供 6 个月发布周期和 LTS(长期支持)版本,极大推动了 Linux 普及。
2008 年
Android 首个正式版发布。Android 基于 Linux 内核,此后数十亿智能手机都运行着 Linux。
2024 年
Linux 运行在 97%+ 的云服务器(AWS、Azure、GCP 的绝大多数实例)、100% 的 TOP500 超算、以及数十亿 Android 和 IoT 设备上。Linux 内核代码量超过 3000 万行。

GNU/Linux 的关系

内核 vs 操作系统

严格来说,"Linux"只是操作系统内核——负责硬件抽象、进程调度、内存管理、驱动程序等底层工作。我们日常使用的文件命令(ls、cp)、Shell(bash)、编译器(gcc)、C 标准库(glibc)大多来自 GNU 项目。所以正确的叫法是 GNU/Linux,但习惯上简称为 Linux。

Linux 操作系统层次结构 ───────────────────────────────────────────────── 用户程序 │ vim, Firefox, Python, Docker, nginx ───────────────────────────────────────────────── GNU 工具 │ bash, ls, cp, gcc, glibc, coreutils ───────────────────────────────────────────────── Linux 内核 │ 进程调度/内存管理/文件系统/驱动/网络 ───────────────────────────────────────────────── 硬件 │ CPU, RAM, Disk, Network, GPU

Linux 内核的主要职责

进程管理
创建、调度和终止进程。Linux 使用 CFS(完全公平调度器)保证进程公平使用 CPU。实时进程可设置更高优先级(SCHED_FIFO)。
内存管理
虚拟内存、物理内存分配、分页、交换空间(swap)管理。每个进程有独立的虚拟地址空间,内核负责地址映射和保护。
文件系统
通过 VFS(虚拟文件系统)抽象层统一不同文件系统(ext4、XFS、Btrfs、ZFS、FAT32 等)的访问接口,上层程序无需关心底层文件系统类型。
设备驱动
将硬件设备抽象为文件(/dev/sda、/dev/input/mice 等),程序通过统一的文件 API 操作硬件,无需了解硬件细节。
网络协议栈
实现 TCP/IP、UDP、IPv4/IPv6 等网络协议。通过 socket 接口暴露给用户程序,同时提供 iptables/nftables 防火墙和 tc 流量控制。

主流发行版图谱

三大家族

家族 代表发行版 包管理器 配置风格 适用场景
Debian 系 Debian, Ubuntu, Mint, Kali, Pop!_OS apt / dpkg /etc 配置文件,systemd 服务器、桌面、开发
Red Hat 系 RHEL, CentOS Stream, Fedora, Rocky, AlmaLinux dnf / yum / rpm SELinux 默认启用 企业服务器、生产环境
Arch 系 Arch Linux, Manjaro, EndeavourOS pacman / yay 滚动更新,最新软件 高级用户、桌面
其他 openSUSE, Alpine(容器), NixOS, Gentoo zypper / apk / nix / emerge 各有特色 特殊需求/容器/嵌入式
学习选哪个发行版?

推荐从 Ubuntu LTS(如 24.04 LTS)开始学习。它有最大的社区、最丰富的教程资源,且与生产环境(大多数云服务器使用 Ubuntu 或 Debian)一致。掌握 Ubuntu 后,其他发行版迁移成本很低——核心命令和概念完全相同,只有包管理器不同。

"一切皆文件"哲学

Unix/Linux 的核心设计原则

在 Linux 中,几乎所有资源都被抽象为文件:普通文件是文件,目录是文件,硬件设备(磁盘、键盘、打印机)是文件,网络连接(socket)是文件,进程信息(/proc)是文件,内核参数(/sys)是文件……

这种设计的好处是:统一的接口。读取硬盘数据、读取键盘输入、读取网络数据,都可以用相同的 open()read()write()close() 系统调用。这大幅简化了程序设计,也使得管道(pipe)等强大特性成为可能。

# 访问设备(一切皆文件的体现)
cat /dev/random | head -c 16 | xxd    # 读取随机数据(/dev/random 是字符设备)
echo "Hello" > /dev/pts/1              # 向另一个终端写文字(pts = 伪终端)
dd if=/dev/sda of=backup.img          # 读取整块磁盘(逐字节读取)
dd if=/dev/zero of=file.img bs=1M count=100  # 创建 100MB 空文件

# 进程信息作为文件(/proc 虚拟文件系统)
# /proc 中的文件不存在于磁盘,由内核在访问时动态生成
cat /proc/1/cmdline                    # PID=1 进程(systemd)的命令行参数
cat /proc/$$/status                    # 当前 shell 进程的状态($$=当前PID)
cat /proc/meminfo                      # 内存信息(MemTotal、MemFree、Cached 等)
cat /proc/cpuinfo                      # CPU 信息(型号、核心数、频率等)
cat /proc/loadavg                      # 系统负载(1分钟/5分钟/15分钟平均)
cat /proc/net/tcp                      # 当前所有 TCP 连接(十六进制格式)

# 内核参数作为文件(/sys 虚拟文件系统)
# /sys 暴露内核对象的属性,可读写(写入修改内核行为)
cat /sys/class/net/eth0/address        # 网卡 MAC 地址
cat /sys/block/sda/size                # 磁盘大小(以 512B 扇区为单位)
echo 1 > /sys/class/leds/led0/brightness  # 控制 LED 亮度(需 root)

# 内核运行时参数调整(/proc/sys 是 sysctl 的接口)
sysctl vm.swappiness                   # 查看 swap 使用倾向(默认 60)
sysctl -w vm.swappiness=10            # 运行时修改(不持久)
echo 'vm.swappiness=10' >> /etc/sysctl.conf  # 持久化配置
Unix 设计哲学(Doug McIlroy 总结)

① 每个程序只做一件事,且做好它;② 程序的输出成为另一个程序的输入(管道/流);③ 编写处理文本流的程序,因为文本是通用接口。这三条原则解释了为什么 Linux 有成百上千个小命令,以及为什么管道(|)如此强大。

FHS 文件系统层次标准

Linux 目录结构速查

/ (根目录)
整个文件系统的起点,所有其他目录和文件都挂载在这里。根分区必须包含启动系统所需的最基本文件。
/bin, /sbin → /usr/bin, /usr/sbin
基础命令(ls、cp、bash 等)和系统管理命令(fdisk、iptables)。现代系统(Ubuntu 22.04+)将 /bin 和 /sbin 合并到 /usr/bin 和 /usr/sbin,/bin 只是符号链接。
/etc
系统配置文件,全部是纯文本,可用编辑器直接修改。重要子目录:/etc/network(网络配置)、/etc/passwd(用户账户)、/etc/shadow(密码哈希)、/etc/fstab(自动挂载)、/etc/systemd(服务配置)。
/home
普通用户的主目录(/home/alice、/home/bob)。用户的个人配置文件(以 . 开头的隐藏文件,如 .bashrc、.ssh/)都存放在这里。每个用户只能访问自己的目录(除非 root)。
/root
root 超级管理员的主目录,单独存放(不在 /home 下),确保系统故障时管理员仍可登录。
/var
可变数据(variable),内容随时间变化:/var/log(系统日志)、/var/cache(程序缓存)、/var/lib(数据库文件、包管理器状态)、/var/spool(打印/邮件队列)。
/tmp 和 /run
/tmp 存放临时文件,系统重启后清空(通常挂载为 tmpfs 内存文件系统)。/run 存放运行时数据(PID 文件、锁文件、socket),重启后清空。
/usr
用户级程序和数据(Unix System Resources):/usr/bin(用户程序)、/usr/lib(共享库)、/usr/include(头文件)、/usr/share(文档、图标、字体)。
/dev
设备文件:/dev/sda(第一块 SATA/NVMe 磁盘)、/dev/sda1(第一个分区)、/dev/null(黑洞,写入丢弃、读取返回空)、/dev/zero(无限零字节)、/dev/random(真随机数)、/dev/urandom(伪随机数,快)。
/proc 和 /sys
虚拟文件系统,不占用磁盘空间,由内核在访问时动态生成。/proc 暴露进程和系统信息;/sys 暴露内核对象(设备、驱动、模块)的属性,可读可写。
/boot
启动所需文件:Linux 内核镜像(vmlinuz-*)、内存初始化文件系统(initrd/initramfs)、GRUB 引导程序配置。通常是独立分区,不加密。
/opt 和 /usr/local
/opt 用于安装第三方软件的自包含包(如 Google Chrome、JetBrains IDE);/usr/local 用于系统管理员手动编译安装的软件,优先级高于 /usr 中的发行版包。

终端与 Shell 的区别

TTY / 终端(Terminal)
历史上指电传打字机(Teletypewriter,TTY),现代指终端模拟器(Terminal Emulator)。负责处理键盘输入和文字显示,但不解释命令。常见:GNOME Terminal、iTerm2(macOS)、Alacritty、kitty。
Shell(命令解释器)
运行在终端内部的程序,读取用户输入并解释执行命令。Linux 默认 Shell 是 bash(Bourne Again Shell,1989年),其他常见:zsh(功能更强,macOS 默认)、fish(用户友好,彩色提示)、dash(轻量,/bin/sh)。
伪终端(PTY)
软件模拟的终端,使 SSH 远程登录、tmux 多路复用器等可以工作。SSH 连接后,服务端会创建一个 PTY,你的命令实际上是通过网络发到这个 PTY 执行的。
登录 Shell vs 交互 Shell
登录 Shell 在用户登录时启动(读取 .bash_profile 或 .profile);交互 Shell 是普通终端会话(读取 .bashrc);非交互 Shell 是脚本执行时的环境(不读取配置文件)。这影响环境变量的加载来源。
# 查看当前 Shell 信息
echo $SHELL           # 当前用户默认 Shell(/bin/bash 或 /usr/bin/zsh)
echo $0               # 当前进程名(-bash 前缀的减号表示登录 Shell)
echo $$               # 当前 Shell 的 PID

# 查看系统安装的所有 Shell
cat /etc/shells
# 输出示例:
# /bin/sh
# /bin/bash
# /usr/bin/bash
# /usr/bin/zsh
# /usr/bin/fish

# 切换默认 Shell(重新登录后生效)
chsh -s /usr/bin/zsh  # 修改当前用户的默认 Shell
sudo chsh -s /bin/bash alice  # 修改指定用户的默认 Shell

# 查看 Linux 版本信息
uname -r              # 内核版本(如 6.8.0-41-generic)
uname -a              # 完整系统信息
cat /etc/os-release   # 发行版信息(标准化格式)
lsb_release -a        # 详细发行版信息(Debian/Ubuntu)
hostnamectl           # 主机名、操作系统、内核版本

# 查看硬件信息
lscpu                 # CPU 详细信息(核心数、频率、架构)
lsmem                 # 内存信息
lsblk                 # 块设备(磁盘/分区)信息
lspci                 # PCI 设备(显卡、网卡等)
lsusb                 # USB 设备

用户与权限的基础概念

Linux 是多用户操作系统,权限模型是安全的基石。理解这些概念为后续章节打好基础。

root 用户
超级管理员,UID=0,拥有系统的完全控制权。可以读写任何文件、杀死任何进程、修改系统配置。日常操作不应以 root 身份运行(误操作代价极大)。使用 sudo 临时获取 root 权限更安全。
普通用户
UID 从 1000 开始(系统用户 1-999),只能访问自己的文件和公共资源。通过组(Group)可以实现多用户共享文件。/etc/passwd 记录所有用户,/etc/shadow 记录密码哈希(只有 root 可读)。
sudo
以另一用户(通常是 root)身份执行单个命令。相比直接切换到 root,sudo 的优势:记录日志(/var/log/auth.log)、需要输入自己的密码验证、每次提权都是显式声明,安全性更高。
rwx 权限位
每个文件有 3 组权限(所有者/组/其他人),每组 3 位:r(读,4)、w(写,2)、x(执行,1)。数字表示法:755 = 所有者rwx + 组r-x + 其他人r-x,644 = 所有者rw- + 组r-- + 其他人r--。
# 用户管理基础命令
whoami                # 当前用户名
id                    # 用户 UID、GID 和所属组
id alice              # 查看指定用户信息
groups                # 当前用户所属的组

# 使用 sudo 执行特权命令
sudo apt update       # 以 root 权限执行 apt update
sudo -i               # 切换到 root shell(需谨慎!)
sudo -u alice ls /home/alice  # 以 alice 身份执行命令

# 临时切换用户
su alice              # 切换到 alice(需要 alice 的密码)
su - alice            # 切换到 alice 并加载其完整环境
exit                  # 退出,返回之前的用户

# 查看文件权限
ls -la /etc/passwd    # 查看 /etc/passwd 的权限
stat /etc/shadow      # 详细权限和时间戳信息
避免 rm -rf / 类灾难操作

Linux 没有回收站(默认情况下),rm -rf / 会删除整个系统且无法恢复!在输入任何 rm 命令前先确认路径。在脚本中,优先使用变量保护:rm -rf "${DIR}/"(即使 DIR 为空,有斜杠的路径更安全)。生产环境建议安装 trash-cli,将文件移入回收站而非直接删除。

本章小结

Linux 的核心要点:① Linux 是内核,GNU/Linux 才是完整操作系统;② "一切皆文件"让程序和硬件通过统一接口交互;③ FHS 规范了目录结构,/etc 是配置,/var 是可变数据,/proc 和 /sys 是内核接口;④ Shell 是命令解释器,终端是 I/O 界面;⑤ 多用户权限模型是安全基础,日常操作避免使用 root。掌握这些概念,是后续学习所有 Linux 操作技能的基础。