假设我有一个 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
和的地址这两个
是一样的吗?换句话说,内存中有两个.exe
文件的add()A.o
还是只有一个?
最佳答案
您的内存中没有任何重定位的目标文件。
我猜你有一个 Linux 系统。如果在 Windows 上,原理保持不变,但细节有所不同。
链接器(调用以构建 1.exe
和 2.exe
)构建一个可执行文件 ELF文件(由多个段组成,特别是所谓的 "text" segment 用于机器代码和只读常量数据,以及 "data" segment 用于可变数据)。 execve(2)启动该程序的系统调用是内存映射 ELF 文件的几个段(几乎与某些 mmap(2)
系统调用一样)。
请注意,为 Linux 可执行文件使用 .exe
文件后缀是令人困惑且不常见的。按照惯例,Linux 可执行文件根本没有后缀,并且以小写字母开头。
链接器已将两个 A.o
文件复制并重新定位到不同的地方(因为 relocation )。所以经常会出现1.exe
和2.exe
中a
或者add
的地址不一样的情况,处理它们的机器指令也是如此。
每个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
期间)。
关于c - .o 文件中的内存共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16052022/