1

可以说我有一个A.c文件并将其编译为一个 A.o文件。该A.c文件如下:

int a;
void add(void)
{
}

A.o文件与一个B.o表格一起成为一个1.exe文件。该A.o文件与一个C.o表格一起成为一个2.exe文件。

我的问题是,如果我同时运行1.exe,这两个文件2.exe的地址a和地址是否相同?换句话说,内存中有两个还是只有一个?add().exeA.o

4

3 回答 3

1

a和的地址add不会相同。您有两个进程,因此在此实例中内存中有两个副本。

于 2013-04-17T05:18:44.800 回答
1

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

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

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

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

链接器已将两个文件复制并重定位A.o到不同的东西(因为relocation)。所以通常会发生aor的地址在和 inadd中不同的情况,处理它们的机器指令也是如此。1.exe2.exe

每个进程都有自己的地址空间(可以通过例如mmap(2)系统调用进行更改)。键入cat /proc/1234/maps以了解 pid 1234 的进程的地址空间。还尝试cat /proc/self/maps获取运行该cat.

如果A.o你有一个共享对象(或动态库)而不是对象,则libA.so它的一些(mmap-ed)段将被共享(而另一些将使用写入时复制技术),并且一些重定位发生在动态链接时(例如,dlopen如果它是一个插件)。

另请阅读Levine 关于链接器和加载器的书。

于 2013-04-17T05:16:49.640 回答
0

它取决于链接...。默认情况下,链接始终是动态的,因此当您将两个 exe 文件加载到内存中时,文件 Ao 将表现为可重入函数,并且它的唯一一个实例将在内存中,由这两个 exe 文件共享。 .

它就像 printf 函数......有这么多 printf 任何差异差异文件,但一次只有一个实例在内存中运行......

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

于 2013-04-17T05:20:55.993 回答