跳转到正文
Mind in Motion

GNU 是什么?从自由软件理念到 GNU/Linux

从 GNU 的历史、递归缩写和四项自由,理解 GNU 与 Linux 内核、GNU 工具链及日常开发环境的关系。

计算机基础,开发实践3分钟阅读

GNU 可以从三个层面理解:一个自由软件项目、一套 Unix-like 操作系统,以及一组广泛使用的开发工具。我们在 GNU/Linux 系统中使用的 Bash、GCC、GNU C Library、Coreutils 和 GNU Make,都属于这套软件生态的重要组成部分。

这篇文章从 GNU 的起源讲起,再把 GNU 与 Linux 内核、Linux 发行版、开源软件和日常开发工具放到同一张地图中。

GNU 项目由 Richard Stallman 在 1983 年发起,1984 年开始开发,目标是构建一套与 Unix 兼容的完整自由软件系统。GNU 是递归缩写,完整写法是 GNU’s Not Unix;这里的递归指缩写展开后仍然包含 GNU 自身。GNU 的英文发音接近“格努”,首字母的 g 会发音。

GNU 的重点落在“自由软件”(free software)中的自由。自由软件关注用户拥有运行、研究、分享和改进软件的权利,软件价格可以是零,也可以由发行者采用收费方式。

时间 事件
1983 年 Richard Stallman 宣布 GNU 项目,提出构建自由 Unix-like 系统的目标。
1984 年 GNU 系统进入持续开发阶段,开发者开始逐步补齐编译器、编辑器、Shell 和系统工具。
1985 年 《GNU 宣言》公开 GNU 项目的动机与自由软件理念。
1990 年 GNU Hurd 内核开始开发,GNU 项目拥有了自己的内核方向。
1991 年 Linux 内核发布,后来与 GNU 软件组合成广泛使用的 GNU/Linux 系统。

GNU 的实现路线采用“逐个替换系统组件”的方式:先开发能够自由使用和修改的工具,再逐步补齐完整操作系统所需的组件。GCC、Bash、GNU C Library、Coreutils、Binutils、GNU Make 和 GDB 都来自这条长期演进的路线。

GNU 对自由软件的定义通常用四项自由说明。数字从 0 开始,代表运行软件的自由属于第一项基础自由:

编号 自由 具体含义
0 运行 按自己的目的运行程序,不受使用场景限制。
1 研究与修改 研究程序的工作方式,并根据需要修改程序;这需要获得源代码。
2 分享副本 把软件的副本分享给其他人,帮助他人使用同一套程序。
3 分享改进版 发布自己修改后的版本,让整个社区从改进中受益。

这四项自由关注软件交付给用户后的权利范围。许可证负责把这些权利写成可以执行的授权条件,因此阅读项目使用的具体许可证仍然很重要。

理解 GNU/Linux 最简单的方法是把操作系统拆成层次:

应用程序:浏览器、编辑器、ROS 2、数据库服务
用户空间:Bash、glibc、Coreutils、GCC、Make、GDB
内核:Linux kernel
硬件:处理器、内存、磁盘、网卡、外设

Linux 负责内核工作:管理进程、内存、文件系统、网络和硬件驱动。GNU 提供了大量运行在内核之上的用户空间组件,包括 Shell、C 语言运行库、基础命令、编译器、链接器和调试器。Linux 内核与 GNU 软件组合后,形成常见的 GNU/Linux 系统。

日常交流中,“Linux”经常被用来指代完整的 Linux 发行版。技术讨论涉及系统分层、许可证或工具来源时,使用“Linux 内核”和“GNU/Linux 系统”能够表达得更准确。

组件 作用 常见命令或文件
Bash Shell,负责解释和执行命令 bash
Coreutils 提供文件、目录、文本和进程相关的基础命令 lscpmvcat
GCC GNU Compiler Collection,编译器集合 gccg++
glibc GNU C Library,为程序提供常用 C 运行库和系统调用接口 libc.so
Binutils 汇编、链接、目标文件检查等工具集合 asldobjdump
GNU Make 根据规则自动执行编译任务 make
GDB 调试器,用于断点、调用栈和变量检查 gdb
Emacs 可扩展的文本编辑器与开发环境 emacs
Stow 用符号链接管理独立软件包和配置文件 stow

一个发行版会按照自己的目标组合内核、GNU 软件包、桌面环境、安装器、包管理器和其他第三方软件。Ubuntu、Debian、Fedora 和 Arch Linux 都属于 GNU/Linux 发行版,各自的默认组件与管理方式存在差异。

以 GCC 编译 C 程序为例,一条看似简单的命令会串起多个 GNU 工具:

Terminal window
cat > hello.c <<'EOF'
#include <stdio.h>
int main(void) {
puts("Hello, GNU/Linux!");
return 0;
}
EOF
gcc hello.c -o hello
./hello

执行 gcc hello.c -o hello 时,工具链大致经过以下阶段:

  1. 预处理器展开头文件和宏。
  2. 编译器把 C 代码转换为目标平台的汇编或中间表示。
  3. 汇编器把汇编代码生成目标文件。
  4. 链接器把目标文件与运行库组合成可执行文件。

可以用版本命令观察当前环境中的工具来源和版本:

Terminal window
cat /etc/os-release
uname -sr
bash --version | head -n 1
gcc --version | head -n 1
make --version | head -n 1
ld --version | head -n 1
gdb --version | head -n 1

command -v bash gcc make ld gdb 可以查看 Shell 实际调用的可执行文件路径。排查编译问题时,同时记录工具版本、路径、目标架构和发行版信息,能够更快定位工具链差异。

GNU Stow 是一个符号链接管理器(symlink farm manager)。它把每组软件或配置文件放在独立的包目录中,再在目标目录创建指向这些文件的符号链接,让多个包可以共同呈现为一棵完整的目录树。

Stow 很适合管理 dotfiles(以点号开头的配置文件)。把配置文件放进 Git 仓库后,可以在多台电脑之间同步 Shell、编辑器、Git 和终端配置;修改配置时,编辑的是仓库中的真实文件,目标位置通过符号链接使用同一份内容。

Ubuntu 或其他 Debian 系发行版可以使用系统包管理器:

Terminal window
sudo apt update
sudo apt install stow

macOS 可以使用 Homebrew:

Terminal window
brew install stow

安装后检查版本:

Terminal window
stow --version

下面的目录结构把 ~/dotfiles 作为 Stow directory,把 zshgittmux 作为三个 package,把用户主目录作为 target directory:

~/dotfiles/ Stow directory
├── zsh/ package
│ ├── .zshrc
│ └── .config/zsh/starship.toml
├── git/ package
│ └── .gitconfig
└── tmux/ package
└── .tmux.conf
~/ target directory
├── .zshrc -> dotfiles/zsh/.zshrc
├── .config/zsh/starship.toml -> dotfiles/zsh/.config/zsh/starship.toml
├── .gitconfig -> dotfiles/git/.gitconfig
└── .tmux.conf -> dotfiles/tmux/.tmux.conf

每个 package 内部都按照 target directory 的相对路径摆放文件。zsh/.zshrc 对应 ~/.zshrcgit/.gitconfig 对应 ~/.gitconfig。这套镜像目录结构是 Stow 能够自动建立链接的关键。

先进入 Stow directory,使用 --simulate--verbose 预览操作:

Terminal window
cd ~/dotfiles
stow --simulate --verbose --target="$HOME" zsh git tmux

确认输出中的文件路径和操作范围后,再执行实际链接:

Terminal window
stow --target="$HOME" zsh git tmux

检查链接指向:

Terminal window
ls -l "$HOME/.zshrc" "$HOME/.gitconfig" "$HOME/.tmux.conf"

--target="$HOME" 明确指定目标目录,命令可以从仓库外部运行。Stow 会管理它创建的链接,配置文件本体仍然保留在 ~/dotfiles 中。

修改 package 中的文件后,通常可以重新执行 stow;需要清理旧链接或调整目录结构时使用 --restow

Terminal window
cd ~/dotfiles
stow --restow --target="$HOME" zsh

暂时停用一个 package 时使用 --delete

Terminal window
stow --delete --target="$HOME" tmux

--delete 会移除 Stow 自己管理的目标链接,并保留 package 目录中的原始文件。重新启用时,再运行普通的 stow 命令即可。

目标位置已经存在普通文件时,Stow 会报告冲突并停止该次操作。处理已有配置可以遵循这条路径:

  1. 先备份目标文件,再使用 --simulate --verbose 查看冲突位置。
  2. 比较目标文件与 package 中的版本,确认需要保留的内容。
  3. 将最终版本放入正确的 package 路径,再执行 stow。

--adopt 可以把目标位置已有的普通文件移动到对应 package 中,并继续建立链接:

Terminal window
cd ~/dotfiles
stow --simulate --verbose --target="$HOME" zsh
stow --adopt --target="$HOME" zsh
git diff -- zsh

--adopt 会改变 Stow directory 的内容,使用前应确认备份和 Git 工作区状态。涉及 .zshrc、SSH、编辑器或代理配置时,先保留可恢复副本,再处理冲突。

Stow 的完整选项和冲突规则可以查阅 GNU Stow 官方手册

GNU 项目使用“自由软件”这个说法,强调用户对软件拥有的实际自由;“开源软件”通常强调源代码可获得、许可证允许修改与再发布,以及开放协作带来的开发优势。两种理念在大量软件项目中相互重叠,GNU 的许多软件包也符合开源软件的许可证标准。

GNU General Public License(GNU GPL)是 GNU 生态中具有代表性的 Copyleft 许可证。Copyleft 的核心方向是让软件及其改进版本继续保留用户自由。涉及项目分发、静态链接、动态链接或商业交付时,应结合具体 GPL 版本、依赖关系和发布方式进行合规审核。

GNU 既可以指 GNU Project,也可以指由 GNU 软件包组成的 Unix-like 系统,还可以指单个 GNU 软件包。看到“GNU 工具”时,通常是在说 Bash、GCC、Coreutils、Make 这类独立项目。

Linux kernel 是操作系统内核。Ubuntu、Debian、Fedora 等发行版在内核之上继续组合 GNU 工具、包管理器、服务、桌面环境和应用程序。理解层次后,gcc 安装问题、网络驱动问题和桌面软件问题可以分别沿工具链、内核或发行版配置方向排查。

发行版可以选择不同的 Shell、C 运行库、初始化系统和桌面环境。常见系统大量使用 GNU 软件,具体组件仍然应以本机安装包、可执行文件路径和版本输出为准。

  1. 先用 cat /etc/os-releaseuname -sr 识别发行版与内核。
  2. 再用 bash --versiongcc --versionmake --version 检查 GNU 工具链。
  3. 使用 man bashinfo coreutilsinfo gcc 阅读本机手册。
  4. 编写一个小型 C 程序,观察预处理、编译、汇编和链接的输出。
  5. 阅读 GNU 项目简介GNU/Linux 与 GNUGNU GPL,把技术层次与软件自由联系起来。

GNU 的价值同时存在于工程实践和软件文化中:它提供了每天运行的编译器、Shell、库与系统工具,也持续推动用户理解、修改、分享和改进软件。掌握 GNU 与 Linux 内核的分工后,阅读 Linux 文档、配置编译环境和排查系统问题都会拥有更清晰的入口。

© yznn007. 保留所有权利。