引言
当你在 Ubuntu 中打开终端,输入 ls 或 cp 这样的命令时,你使用的是 Linux 吗?
在日常交流中,答案是肯定的。但从技术角度来看,这个过程中其实有多个软件组件在共同工作:终端提供文字交互界面,Shell 解释你的命令,工具程序执行具体任务,而 Linux 内核负责管理底层资源。
其中,许多常见工具来自 GNU 项目。这也是为什么你有时会看到 GNU/Linux 这个名称,而不只是 Linux。
理解它们的关系,可以帮助你弄清楚:为什么 Linux 被称为内核,GNU 为什么重要,以及 Ubuntu、Debian 这样的发行版为什么包含来自许多不同项目的软件。
本文不需要编程基础。我们先从内核讲起,再介绍 GNU,最后通过一条简单命令,把这些组件之间的关系串起来。
第一章:Linux 是内核
从严格的技术定义来说,Linux 是一个操作系统内核。 内核是操作系统的核心组件,负责管理硬件资源,并向运行中的程序提供基本服务。
当多个应用程序都需要使用处理器时,内核负责调度它们的执行。当程序需要内存时,内核管理它的地址空间以及对物理内存的访问。当软件读取文件或者通过网络发送数据时,内核协调相关的文件系统、网络和设备操作。
应用程序通常通过系统调用请求这些服务。系统调用为程序提供了进入内核、申请操作系统服务的受控接口。
内核非常重要,但它并不包含人们使用计算机时需要的全部功能。只有内核,并不会自动出现熟悉的命令提示符、文件管理命令、软件安装工具或桌面环境。
这些功能需要其他软件提供。
因此,首先要理解一个区别:内核负责管理系统资源,而其他软件提供了用户和应用程序日常使用的大部分工作环境。
第二章:GNU 最初就是一个完整操作系统项目
理查德·斯托曼在 1983 年 9 月宣布 GNU 项目,并于 1984 年 1 月开始开发。项目的目标是建立一个完整的类 Unix 操作系统,让用户能够自由使用、研究、修改和分享软件。
GNU 是 GNU’s Not Unix 的缩写,意思是“GNU 不是 Unix”。 这是一个递归缩写,因为展开后的名称里又包含 GNU 自己。
这个名字体现了项目的方向:GNU 借鉴 Unix 中有价值的设计思想和熟悉的使用接口,同时开发一套独立的自由软件系统。
“类 Unix”描述的是系统的设计方式和行为特征,并不意味着 GNU 只是把某个商业 Unix 系统改了名字。
这里还需要理解自由软件中的“自由”。它强调用户拥有运行、研究、修改和分享软件的自由,并不要求软件必须免费。GNU 希望用户能够了解并改变控制自己计算机的软件,而不只是获得运行软件的许可。
因此,GNU 从一开始就不只是几个方便使用的命令。它开发的工具,是构建完整操作系统这一目标的一部分。
第三章:GNU 为 Linux 系统提供了什么?
在许多 GNU/Linux 发行版中,从命令行环境到软件开发工具,都能看到 GNU 软件。有些组件直接与用户交互,有些则在后台支持程序运行。
Bash:解释用户输入的命令
Bash 是 GNU 项目开发的一种命令行 Shell,也就是命令解释器。 它负责解释命令、启动程序,并支持变量、重定向、管道和脚本等功能。
终端窗口与 Shell 是两个不同的组件。终端负责文字输入与输出的交互,Shell 则负责解释通过终端输入的命令。
Bash 使用广泛,但它并不是唯一的 Shell。Linux 系统可以使用其他 Shell,而不必因此更换内核。
GNU Coreutils:完成日常操作
GNU Coreutils 是一组基础工具程序,提供许多用于处理文件、目录和文本的命令。例如,ls 用于列出目录内容,cp 用于复制文件,mv 用于移动或重命名文件,rm 用于删除文件。
这些工具运行在内核之上,并不是 Linux 内核内部自带的命令。
不过,看到相同的命令名称,并不能直接判断它一定来自 GNU。其他项目也可以提供这些命令的实现。例如,某些环境中的 ls 来自使用 Rust 开发的 uutils 项目。具体来源可以通过版本信息等方式确认。
另外,还要区分外部工具程序和 Shell 内置命令。例如,cd 通常由 Shell 自己执行,因为它需要改变 Shell 自身的工作目录。pwd 和 echo 等命令则可能同时存在 Shell 内置版本和独立程序版本。
glibc:支持应用程序运行
GNU C Library 通常简称为 glibc,即 GNU C 库。 它提供许多程序需要调用的函数,包括字符串处理、内存分配、输入输出以及访问操作系统服务等功能。
可以把程序库理解为一组可重复使用的代码。应用程序可以调用这些现成的功能,而不必自己重新实现所有基础操作。
有些库函数完全在应用程序的进程内部完成工作;另一些则通过系统调用向内核请求服务。因此,调用一个库函数,并不一定意味着程序进入了内核。
GCC:构建软件
GCC 是 GNU Compiler Collection,即 GNU 编译器集合。 它为 C、C++ 等语言提供编译器,帮助开发者将源代码转换为能够在目标机器上运行的代码。
编译器对于构建许多软件非常重要,但不是每台运行这些软件的计算机都必须安装编译器。服务器或桌面计算机可以直接运行在其他机器上编译好的程序。
GDB:分析程序行为
GDB 是 GNU 调试器。 开发者可以使用它暂停程序执行、检查变量和运行状态,并调查程序出错的原因。
这些例子展示了 GNU 贡献的广度:既有与用户交互的工具,也有基础命令、运行库,以及用于构建和调试软件的开发工具。
第四章:GNU 和 Linux 是怎样结合起来的?
到了 20 世纪 90 年代初,GNU 已经开发了许多重要的操作系统组件,但在其计划中的完整系统里,一个实用的内核仍然是重要的缺口。
GNU 并不是没有自己的内核项目。GNU Hurd 于 1990 年开始开发,采用了不同于 Linux 的设计,将操作系统服务安排在微内核之上的多个服务程序中。因此,说“GNU 从来没有开发内核”是不准确的。
1991 年,Linus Torvalds 开始开发 Linux 内核。1992 年,Linux 改用 GNU 通用公共许可证,也就是 GNU GPL,成为自由软件。这使它能够与 GNU 软件结合,作为自由操作系统的一部分进行分发。
两方面的工作形成了互补:Linux 提供内核,GNU 提供许多构成实用操作环境所需的工具和程序库。
但把它们组合起来,并不是简单地将文件放在一起。开发者还需要移植和适配软件、解决兼容性问题、制作安装工具,并维护能够相互配合的软件包。
Linux 也始终是一个独立项目。它与 GNU 软件共同使用,并不意味着 Linux 内核归 GNU 项目所有,也不意味着两个项目合并成了同一个组织。
还需要区分许可证版本:Linux 内核整体采用的是 GPL 第二版,而不是自动跟随 GPL 的最新版本,并包含明确的系统调用例外说明。
第五章:输入 ls 命令后,系统发生了什么?
通过一个具体例子,更容易理解这些组件怎样配合。
假设你正在 Ubuntu 或 Debian 的终端中使用 Bash,输入 ls,然后按下回车。这里假设没有别名或 Shell 函数改变这个命令的含义。
首先,终端将输入交给 Bash。 Bash 读取并解释命令,判断接下来需要执行什么操作。
接着,Bash 找到并启动 ls 程序。 在许多系统中,它来自 GNU Coreutils;在另一些系统中,它也可能来自 uutils 或其他实现。无论来自哪个项目,它都是一个独立于内核的工具程序。
启动程序需要内核参与。内核负责相应的进程创建、程序装载和执行等工作。
随后,ls 请求读取目录信息。 程序通过相关的库函数和系统调用,取得目录条目,并根据需要获取文件的属性信息。
Linux 内核处理底层的文件系统操作。 它检查访问权限,并通过文件系统机制取得需要的信息。部分信息可能已经缓存在内存中,因此,显示目录内容不一定每次都需要实际读取存储设备。
最后,ls 整理结果并输出,终端将文字显示出来。 命令执行结束后,Bash 再次显示提示符,等待下一条命令。
在这个过程中,各个组件承担不同的工作:
因此,日常把 ls 称为“Linux 命令”很方便,但从技术上说,ls 程序本身并不是 Linux 内核的一部分。
第六章:Ubuntu 和 Debian 又增加了什么?
大多数用户不会先下载一个内核,再逐个寻找程序库、工具和应用程序,把它们手工拼成操作系统。我们通常直接安装一个发行版。
发行版会选择、构建、整合、测试和分发软件,将这些组件组织成可以实际使用的系统。
Ubuntu 和 Debian 将 Linux 内核、GNU 组件以及许多其他项目的软件整合在一起。根据安装方式的不同,系统可能包含后台服务、网络工具、软件包管理器、安装程序、图形桌面和应用软件。
发行版还提供软件仓库和更新机制。用户可以安装相互兼容的软件包、获取修复,而不必自己重新编译整个系统。
发行版并不是给同一个内核换上一套不同的外观。 不同发行版可能采用不同的软件包格式、默认软件、配置方式、发布周期和维护策略。
即使是同一个发行版,桌面安装和最小化服务器安装包含的软件也可能相差很大。
因此,“GNU 加 Linux”可以帮助我们初步理解系统的构成,但一个完整的现代发行版,还包含更广泛的开发者社区所提供的软件。
第七章:为什么有人强调 GNU/Linux 这个名称?
GNU/Linux 这个名称强调了 GNU 软件与 Linux 内核的结合。 GNU 项目提倡使用这一名称,是为了让人们认识到 GNU 的贡献,以及其背后的自由软件目标。
在日常交流中,人们也广泛使用较短的名称 Linux,来指代完整操作系统、发行版,甚至整个相关的软件生态。具体含义需要结合上下文判断。
如果有人讨论 Linux 的内存管理或设备驱动,他通常是在说内核。如果有人说“我在笔记本上安装了 Linux”,他通常是在说自己安装了某个完整发行版。
对于初学者来说,理解下面三个层次最有帮助:
Linux 内核,指负责资源管理和基本系统服务的核心组件。
GNU/Linux,指将 Linux 内核与大量 GNU 系统软件结合起来的系统。
Ubuntu、Debian 等发行版名称,指经过具体整合、配置和维护的操作系统。
学习的重点是理解这些组件之间的关系,而不是把每一次日常使用“Linux”这个简称,都当成需要纠正的技术错误。
第八章:并不是所有基于 Linux 的系统都使用相同的 GNU 组件
观察一些采用不同软件组合的系统,可以进一步理解:内核与内核之上的环境,是可以分别选择和组织的。
Android:使用 Linux 内核,但软件环境不同
Android 使用基于 Linux 的内核,但它的标准应用环境与常见的 GNU/Linux 桌面系统存在很大区别。
例如,Android 使用的 C 库是 Bionic,而不是 glibc,同时还拥有自己的运行时、应用框架和系统服务。
这说明:使用 Linux 内核,并不意味着必须采用传统的 GNU 用户空间环境。
这里的“用户空间”,指的是内核之外运行应用程序和许多系统服务的环境。
Alpine Linux:使用不同的程序库和基础工具
Alpine Linux 的基础环境围绕 musl C 库和 BusyBox 构建,为 glibc 和许多 GNU 命令行工具提供了替代选择。需要时,也可以另外安装 GNU 软件包。
类似地,uutils 为许多常用基础命令提供了另一套实现。你输入的仍然可能是 ls,但实际执行的程序不一定来自 GNU。
这也解释了为什么同一个命令在不同环境中可能支持不同的参数:命令名称相同,不代表实现完全相同。
这些区别为什么有实际意义?
跟随教程操作时,仅仅知道“这是 Linux”有时还不够。你可能还需要了解教程采用的发行版、Shell、程序库环境,以及某个工具的具体实现。
内核只是影响软件兼容性的一部分。两个系统即使都使用 Linux 内核,也可能提供不同的工具和应用程序运行环境。
结论
GNU 和 Linux 关系密切,但它们代表不同的项目,也承担系统中的不同角色。
GNU 最初的目标是构建一个完整、自由的类 Unix 操作系统。它开发了 Bash、GNU Coreutils、GCC、glibc 和 GDB 等重要工具与程序库。Linux 则提供了一个能够管理硬件资源,并向程序提供基本服务的内核。
Ubuntu、Debian 等发行版将这些组件与其他项目的软件整合起来,再提供安装、软件包管理、配置和持续更新。
当你输入一条命令时,多个组件正在协作:Shell 解释请求,工具程序完成任务,程序库支持执行,内核管理进程并提供系统资源访问。
同时,这些组件并非永远固定不变。系统可以采用不同的 Shell、C 库和基础工具,而继续使用 Linux 内核。
