C .o文件中的内存共享
假设我有一个C .o文件中的内存共享,c,memory,compiler-construction,linker,C,Memory,Compiler Construction,Linker,假设我有一个a.c文件,并将其编译成a.o文件。 A.c文件如下: int a; void add(void) { } A.o文件与B.o一起构成A1.exe文件。 A.o文件与C.o一起构成2.exe文件 我的问题是,如果我同时运行1.exe和2.exe,这两个.exe文件的a和add()地址是否相同?换句话说,内存中有两个A.o,还是只有一个?内存中没有任何重新定位的对象文件 我猜你有一个Linux系统。如果安装在Windows上,则原理保持不变,但细节不同 链接器(被调用来构建1.exe
a.c
文件,并将其编译成a.o
文件。
A.c
文件如下:
int a;
void add(void)
{
}
A.o
文件与B.o
一起构成A1.exe
文件。
A.o
文件与C.o
一起构成2.exe
文件
我的问题是,如果我同时运行
1.exe
和2.exe
,这两个.exe
文件的a
和add()
地址是否相同?换句话说,内存中有两个A.o
,还是只有一个?内存中没有任何重新定位的对象文件
我猜你有一个Linux系统。如果安装在Windows上,则原理保持不变,但细节不同
链接器(被调用来构建1.exe
和2.exe
)构建一个可执行文件(由几个段组成,特别是所谓的机器代码和只读常量数据段,以及可变数据段)。启动该程序的系统调用是ELF文件的几个段的内存映射(类似于一些mmap(2)
syscall)
请注意,对Linux可执行文件使用.exe
文件后缀既令人困惑又不常见。按照惯例,Linux可执行文件根本没有后缀,而是以小写字母开头
链接器已将两个A.o
文件复制并重新定位到不同的位置(因为存在错误)。因此通常情况下,a
或add
的地址在1.exe
和2.exe
中不同,处理它们的机器指令也不同
每个都有自己的(可以随系统调用而更改)。键入cat/proc/1234/maps
以了解pid 1234进程的地址空间。还可以尝试cat/proc/self/maps
获取运行该cat
的进程的地址空间
如果您有一个共享对象(或动态库)libA,而不是A.o
object,那么
它的一些(mmap
-ed)段将被共享(其他部分将使用技术),并且一些重定位在动态链接时发生(例如,在dlopen
期间,如果它是一个插件)
另请阅读。a和
add
的地址将不相同。您有两个进程,因此在此实例中内存中有两个副本。这取决于链接。默认情况下,链接始终是动态的,因此当您将两个exe文件加载到内存中时,文件A.o将表现为可重入函数,它的唯一一个实例将位于由这两个exe文件共享的内存中
它类似于printf函数…有太多printf任何diff-diff文件,但一次只有一个实例在内存中运行
可重入函数不应产生任何必须注意的数据损坏为什么要使用.exe后缀?因为原始海报使用了
.exe
后缀,那么OP可能在Windows上使用了GCC,而您关于mmap
和ELF的所有内容都与此无关。