假设我cd
在 shell 中输入。是cd
在那一刻从内存中加载的吗?我的直觉是,这些内置命令在内核加载后会预先加载到系统内存中,但有人坚持认为它们仅在我实际调用命令时才加载(在 shell 上按 Enter 键)。您能告诉我是否有参考资料可以解释这一点吗?
答案1
假设我在 shell 中输入 cd 。此时 cd 是否从内存中加载?我的直觉是,这些内置命令是在内核加载后预先加载到系统内存中的,但有人坚持认为它们仅在我实际调用命令时才加载......
从广义上讲,其他答案是正确的 - 内置程序随 shell 一起加载,独立程序在调用时加载。然而,一个非常顽固的黄鼠狼“某人”可能会坚持认为事情没那么简单。
这个讨论在某种程度上是关于操作系统如何工作的,不同的操作系统以不同的方式工作,但我认为一般来说以下内容可能适用于所有当代的 *nixes。
首先,“加载到内存中”是一个含糊不清的短语;我们真正指的是将其虚拟地址空间映射到内存中。这很重要,因为“虚拟地址空间”指的是可能需要放入内存中的内容,但实际上最初并不是这样:大多数实际加载到内存中的是地图本身- 和地图不是领土。 “区域”将是磁盘上(或磁盘缓存中)的可执行文件,事实上,其中大部分可能是不是当您调用可执行文件时加载到内存中。
此外,大部分“区域”是对其他区域(共享库)的引用,同样,仅仅因为它们被引用并不意味着它们确实被加载。它们在实际使用之前不会被加载,然后只有实际需要加载的部分才能成功“使用”。
例如,下面是top
Linux 上引用bash
实例的输出片段:
VIRT RES SHR S %CPU %MEM TIME+ COMMAND
113m 3672 1796 S 0.0 0.1 0:00.07 bash
113 MB VIRT 是虚拟地址空间,即映射的在内存中。但 RES 是进程消耗的实际 RAM 量——只有 3.7 kB。其中,有些是上面提到的共享区域的一部分——1.8 kB SHR。但我的/bin/bash
磁盘大小为 930 kB,并且它链接到的基本 libc(共享库)又是原来的两倍。
该 shell 现在没有执行任何操作。假设我调用了一个内置命令,我们之前说过该命令已经与 shell 的其余部分一起“加载到内存中”。内核从映射中的某个点开始执行所涉及的任何代码,当它到达对尚未真正加载的代码的引用时,它会加载它——从磁盘上的可执行映像——即使在更随意的意义上,该可执行文件(无论是 shell、独立工具还是共享库)已经“加载到内存中”。
这就是所谓的请求寻呼。
答案2
在等待一位重量级人物来提供完整的历史视角的同时,我将向您提供我更有限的理解。
alias
、cd
等内置命令echo
是 shell 的一部分(bash
、zsh
或ksh
其他命令)。它们与 shell 同时加载,并且只是该 shell 的内部函数。
答案3
我做了以下实验来表明内置命令实际上是作为可执行文件的一部分加载的bash
。因此,它们被称为内置程序,但演示始终是证明某些事情的最佳方法。
例子
启动一个新
bash
shell,并记下其进程 ID (PID):$ bash $ echo $$ 6402
在第二个终端中运行
ps
命令,以便我们可以观察并查看是否bash
开始占用任何额外的内存:$ watch "ps -Fp 6402"
输出如下所示:
Every 2.0s: ps -Fp 6402 Sat Sep 14 14:40:49 2013 UID PID PPID C SZ RSS PSR STIME TTY TIME CMD saml 6402 6349 0 28747 6380 1 14:33 pts/38 00:00:00 bash
笔记:此处的 SZ 和 RSS 列显示内存使用情况。
开始在 shell 中运行命令(pid 6402):
当您
cd
周围时,您会注意到内存实际上会增加,但这并不是因为可执行文件cd
被加载到内存中,而是因为磁盘上的目录结构被加载到内存中。如果您继续cd
进入其他目录,您会看到它逐渐上升。Every 2.0s: ps -Fp 30208 Sat Sep 14 15:11:22 2013 UID PID PPID C SZ RSS PSR STIME TTY TIME CMD saml 30208 6349 0 28780 6492 0 15:09 pts/38 00:00:00 bash
您可以进行更详细的测试,如下所示:
$ for i in `seq 1000`; do cd ..; cd 90609;done
此命令将 cd 上一级,然后返回到目录 90609 1000 次。运行此程序时,如果您监视窗口中的内存使用情况,
ps
您会发现它没有变化。运行类似的程序时,不应注意到额外的内存使用情况。斯特雷斯
这是另一个告诉我们我们正在处理一个内置函数而
bash
不是一个实际的可执行文件。当您尝试运行时,strace cd ..
您将收到以下消息:$ strace cd .. strace: cd: command not found
答案4
“内置命令”是指内置于 shell 中的命令,而不是作为单独的程序。ls
例如,实际上不是一个内置命令,而是一个单独的程序。当它被调用时,它将被加载到 RAM 中,除非它已经在磁盘缓存中。
内置命令的一个示例是printf
or cd
。它们是 shell 的一部分,并与 shell 的其余部分一起加载。
默认情况下不会预先加载任何命令,尽管已经创建了系统来执行此操作。