假设我有一个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()
的地址对于这两个.exe
是否相同文件?换句话说,内存中有两个A.o
还是只有一个?
答案 0 :(得分:1)
内存中没有任何重定位目标文件。
我猜你有一个Linux系统。如果在Windows上,原则保持不变,但细节不同。
链接器(被称为构建1.exe
和2.exe
)构建一个可执行的ELF文件(由多个段组成,特别是所谓的"text" segment用于机器代码和只读常量数据,以及可变数据的"data" segment。启动该程序的execve(2)系统调用是内存映射ELF文件的几个段(几乎与某些mmap(2)
系统调用一样)。
请注意,对Linux可执行文件使用.exe
文件后缀是令人困惑和不常见的。通常,Linux可执行文件根本没有后缀,并以小写字母开头。
链接器已将两个A.o
文件复制并重定位到不同的内容中(因为relocation)。因此,a
或add
的地址通常会在1.exe
和2.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
期间)。
答案 1 :(得分:1)
a
和add
的地址不一样。您有两个进程,因此在此实例中内存中有两个副本。
答案 2 :(得分:0)
它取决于链接....默认情况下,链接总是动态的,所以当你将两个exe文件加载到内存中时,文件Ao将表现为可重入函数,它的唯一一个实例将在内存中,这两个exe共享文件...
它就像printf函数...有很多printf任何diff diff文件,但是一次只有一个实例在内存中运行...
可重入函数不应传递您必须处理的任何数据损坏