.o文件中的内存共享

时间:2013-04-17 05:13:25

标签: c memory compiler-construction linker

假设我有一个A.c文件并将其编译为A.o文件。 A.c文件如下:

int a;
void add(void)
{
}

A.o文件和B.o形成1.exe文件。 A.o文件和C.o形成2.exe文件。

我的问题是,如果我同时运行1.exe2.exeaadd()的地址对于这两个.exe是否相同文件?换句话说,内存中有两个A.o还是只有一个?

3 个答案:

答案 0 :(得分:1)

内存中没有任何重定位目标文件。

我猜你有一个Linux系统。如果在Windows上,原则保持不变,但细节不同。

链接器(被称为构建1.exe2.exe)构建一个可执行的ELF文件(由多个段组成,特别是所谓的"text" segment用于机器代码和只读常量数据,以及可变数据的"data" segment。启动该程序的execve(2)系统调用是内存映射ELF文件的几个段(几乎与某些mmap(2)系统调用一样)。

请注意,对Linux可执行文件使用.exe文件后缀是令人困惑和不常见的。通常,Linux可执行文件根本没有后缀,并以小写字母开头。

链接器已将两个A.o文件复制并重定位到不同的内容中(因为relocation)。因此,aadd的地址通常会在1.exe2.exe中有所不同,处理它们的机器指令也是如此。

每个process都有自己的address space(可以使用例如mmap(2)系统调用进行更改)。输入cat /proc/1234/maps以了解pid 1234进程的地址空间。另请尝试cat /proc/self/maps以获取运行cat的进程的地址空间。

如果您拥有共享对象(或动态库)A.o而不是libA.so对象,则会共享其中一些(mmap - ed)段(以及其他人将使用copy on write技术),并且一些重定位发生在动态链接时(例如,如果它是插件,则在dlopen期间)。

另请阅读Levine's book on Linkers and Loaders

答案 1 :(得分:1)

aadd的地址不一样。您有两个进程,因此在此实例中内存中有两个副本。

答案 2 :(得分:0)

它取决于链接....默认情况下,链接总是动态的,所以当你将两个exe文件加载到内存中时,文件Ao将表现为可重入函数,它的唯一一个实例将在内存中,这两个exe共享文件...

它就像printf函数...有很多printf任何diff diff文件,但是一次只有一个实例在内存中运行...

可重入函数不应传递您必须处理的任何数据损坏