内存中程序的加载和执行

内存中程序的加载和执行

在比较链接加载器和链接编辑器时,我发现了一点,在链接加载器的情况下,程序的每次执行都会发生链接和重定位(并且在加载时发生),而在链接编辑器的情况下,链接仅发生一次并且程序可以被多次加载和使用。这是否意味着只有当程序被赋予执行控制权时(或者操作系统已经决定它是下一个要执行的程序),程序才会被加载到主内存中?具体来说,将程序加载到主内存中是否可以保证立即执行槽?

答案1

这里需要澄清一些事情:

  1. 程序在硬盘上或在内存中实际上没有区别。如果内核没有找到已经映射到内存的文件, mmap从那时起,该文件将通过内存页访问,映射到程序的虚拟内存中。请注意,整个机制是透明的,而许多事情都在后台发生:文件可能已经从以前的使用中缓存起来,如果空间不足,实际内存可能已被交换到磁盘,等等......
  2. 即使许多可执行文件链接到动态链接库,动态链接库也会加载一次。同样,页面被映射到需要它们的进程的虚拟内存中。
  3. 将可执行文件的内容加载到内存中与正在运行的代码无关。每次创建新进程(通过 fork)时,它都会获得自己的虚拟内存布局,并且不关心页面存储在哪里以及还有谁在使用它们。当exec被调用时(execve通常),二进制文件(可能是elf格式)将被解析,不同的内容映射到不同的页面(程序代码,静态数据,堆栈被分配等),链接器查找代码中未解析的符号并将它们映射到动态可链接库中的地址,这些地址也在此阶段映射到虚拟地址空间。然后执行被传递到执行程序中代码的入口点。

请注意,特定程序的每次执行都是其自己的新进程,并且并不真正关心代码来自哪里。代码可能已经在 RAM 中——或者没有,内存管理是非常动态的。也可能是包含代码的同一物理内存页被映射到多个进程的地址空间,并且动态链接库肯定使用相同的共享页,但仅此而已。

可以在启动时预加载常用的库,因此进程执行得更快:但这意味着链接器已经找到加载到 RAM 中的页面,不需要从硬盘驱动器中读取它们。这又是一种缓存方式,只是内核以任何它想要的方式洗牌页面这一事实的副作用,你看到的只是虚拟地址空间。

如果您指的是调用某个命令重用现有进程的情况,那就完全不同了。您可能有一些通信协议来查找现有实例并告诉它要做什么。或者你可能有一个睡眠过程,当有更多事情要做时就会醒来。但在这些情况下,您实际上并没有运行新进程。

我不太确定你的问题是什么,但我希望这至少能部分回答你的问题。

答案2

你的问题很难理解,可能包含一些误解。

这是否意味着只有在给予程序执行控制权时(或者操作系统已决定它是下一个要执行的程序),才会将程序加载到主内存中

execve()在 UNIX 中,控制权通过系统调用(及其变体)移交给下一个程序。该系统调用将要执行的程序的文件名作为参数。所以它就像一个加载并执行程序的请求。该程序尚未预先加载。所以从这个意义上说,你的问题的答案是“是”。

我们将忽略这样一个事实:如果程序代码之前已被读取或执行过,则它可能仍然缓存在物理内存中。这就是一个优化。

内核所做的第一件事是加载有问题的文件。

如果它是动态链接的可执行文件,那么它还会加载动态链接器,这是一个将在程序上执行运行时链接的帮助程序。这个助手完成它的工作,通常涉及加载其他代码段(共享库)。

一旦完成动态链接(或者如果由于程序不是动态链接而没有完成动态链接),则控制权将被传递到适当的程序代码。

将程序加载到主内存中是否可以保证立即执行槽?

我不明白“立即执行槽”。

将文件(包含程序)加载到内存中可能有许多不同的原因:运行它、复制它、编辑它等等......

相关内容