内置命令何时加载到内存


11

假设我输入cd了我的shell。cd那时候是从内存加载的吗?我的直觉是,这些内置命令在内核加载后会预先加载到系统内存中,但是有人坚持说只有在我实际调用命令时(在外壳上按Enter键)才加载它们。您能否告诉我是否有参​​考文献对此进行解释?


1
我认为这个答案可以帮助您理解,尽管不是完全重复。
cjm 2013年

@cjm:谢谢,这确实是一个很好的解释。
Forethinker 2013年

Answers:


9

假设我在外壳中输入cd。那时从内存中装入了cd吗?我的直觉是,这些内置命令在内核加载后预加载到系统内存中,但是有人坚持只有在我实际调用该命令时才加载它们。

从广义上讲,其他答案是正确的-内置程序随外壳一起加载,独立程序在调用时被加载。但是,一个非常狡猾的狡猾的“某人”可能会坚持认为这不是那么简单。

讨论的内容是关于操作系统的工作方式以及不同操作系统的工作方式不同,但我认为一般而言,以下内容可能适用于所有现代* 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是虚拟地址空间,映射到RAM中。但是RES是该进程实际消耗的RAM数量-只有3.7 kB。其中,有些是上述共享区域的一部分-1.8 kB SHR。但是我/bin/bash的磁盘容量为930 kB,它链接到(共享库)的基本libc大小又增加了一倍。

该shell现在什么也没做。假设我调用了一个内置命令,我们之前说过该命令已经与外壳的其余部分一起“装入了内存”。内核从映射中的某个点开始执行涉及的所有代码,当内核到达尚未真正加载的代码的引用时,即使从磁盘上的可执行映像加载,它也会从磁盘上的可执行映像加载它。从某种意义上说,该可执行文件(无论是外壳程序,独立工具还是共享库)已经“加载到内存中”。

这称为需求分页


9

在等待其中一位重量级人物来临并提供完整的历史观点时,我将为您提供更为有限的理解。

内置的命令,比如aliascdecho等都是你的shell的一部分(bashzshksh或其他)。它们在外壳同时加载,并且仅仅是外壳的内部功能。


4

我做了以下实验,以表明内置命令实际上是作为exectuable的一部分加载的bash。因此,为什么将它们称为内置函数,但演示始终是证明某些东西的最佳方法。

  1. 启动一个新的bashshell,并记下其进程ID(PID):

    $ bash
    $ echo $$
    6402
    
  2. 在第二个终端中,运行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列中显示。

  3. 开始在外壳程序中运行命令(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窗口中监视内存使用情况,则会注意到它没有改变。在运行类似的程序时,不应注意到额外的内存使用情况。

  4. 痕迹

    这又表明我们正在处理内置函数bash而不是实际的可执行文件。尝试运行时,strace cd ..您会收到以下消息:

    $ strace cd ..
    strace: cd: command not found
    

3

“内置命令”是指内置在外壳程序中的命令,而不是作为单独的程序。ls,例如,实际上它不是内置命令,而是单独的程序。调用它时,它将被加载到RAM中,除非它已经在磁盘缓存中。

内置命令的示例为printfcd。它们是外壳的一部分,并与外壳的其余部分一起加载。

尽管已创建系统来默认执行此命令,但默认情况下不会预加载任何命令。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.