在良好的UNIX传统中,Linux拥有默认的全局资源视图。这就引出了一个问题:什么是全局视图(相对于什么?),什么是所谓的资源?
为什么我们首先要讨论资源可见性呢?主要原因是提高你对这个主题的认识,并使你对现代Linux环境中的一个重要主题—容器—有正确的认识。如果你现在没有了解所有的细节,那么也不要担心,我们将在本书中详细讨论这个主题,特别是在第6章,我们将更详细地讨论容器及其构建块。
你可能听说过这样一种说法:在UNIX(扩展为Linux)中,所有东西都是一个文件。在本书中,我们认为资源是任何可以用来帮助软件执行的东西,包括硬件及其抽象(如CPU和RAM、文件)、文件系统、硬盘驱动器、固态硬盘(SSD)、进程、与网络相关的东西(如设备或路由表)以及代表用户的凭证。
Linux中并非所有资源都是文件或通过文件接口表示。然而,也有一些系统,比如Plan 9( https://oreil.ly/5DkY8 ),在这方面做得更进一步。
让我们看一下一些Linux资源的具体示例。首先,我们想要查询一个全局属性(Linux版本),然后查询关于正在使用的CPU的特定硬件信息(输出已被编辑以适应本书版面):
❶输出Linux版本。
❷输出CPU相关信息,过滤模型。
通过前面的命令,我们了解到这个系统有四个Intel i7核可供使用。当使用不同的用户登录时,你希望看到相同数量的CPU吗?
让我们考虑一种不同类型的资源:文件。例如,如果用户troy在/tmp/myfile下创建了一个有权限的文件(见4.3节),那么另一个用户worf会看到这个文件,甚至能够对它进行写操作吗?
或者,以进程为例,也就是说,内存中的程序具有运行所需的所有资源,如CPU和内存。Linux使用进程ID(简称PID,见2.3.1节)来标识进程:
❶输出进程状态(即当前进程的详细信息)并限制输出,只显示前六行。
你可能已经注意到$$,并想知道这是什么意思。这是一个特殊的变量,指的是当前进程(详见3.1.2节)。注意,在shell上下文中,$$是你在其中键入命令的shell(例如bash)的进程ID。
Linux中可以有多个具有相同PID的进程吗?这个听起来很傻很没用的问题其实是容器的基础(参见6.6节)。答案是肯定的,可以有多个具有相同PID的进程,在不同的上下文中称为命名空间(参见6.6.1节)。这可能发生在容器化的设置中,比如当你在Docker或Kubernetes中运行应用程序时。
每个单独的进程都可能认为它是特殊的,具有PID 1,在更传统的设置中,PID 1是为用户空间进程树的根保留的(更多细节请参阅6.2节)。
从这些观测中我们可以了解到,给定资源上可以有一个全局视图(两个用户在完全相同的位置看到一个文件),也可以有一个本地或虚拟化视图,例如进程示例。这就提出了一个问题:Linux中的所有东西都是默认全局的吗?剧透一下:不是的。让我们仔细看看。
让多个用户或进程并行运行的部分错觉是对资源的(受限的)可见性。在Linux中提供本地视图(某些受支持的)的方法是通过命名空间(参见6.6.1节)。
第二个独立的方面是隔离。当我在这里使用术语“隔离”时,我并不一定要限定它——也就是说,我没有假设事物隔离得有多好。例如,考虑进程隔离的一种方法是限制内存消耗,以便一个进程不能占用其他进程的内存。例如,我给你的应用程序使用1GB的RAM,如果它使用了更多,它就会因内存不足( https://oreil.ly/kvk1u )而停止响应。这提供了一定程度的保护。在Linux中,我们使用一个叫作cgroups的内核特性来提供这种隔离,在6.6.2节中,你将了解到更多关于它的知识。
另外,完全隔离的环境会让应用程序看起来完全独立。例如,虚拟机(VM,请参见9.2节)可以用来为你提供完全隔离。