那里的连接器专家的问题。我一直在Matlab中处理mex文件,并且遇到了很多无法解释的崩溃,所以我想更深入一点。
您能否向我解释在加载(卸载)动态模块时如何在进程的虚拟内存空间中分配(取消分配)静态数据?
我假设这发生在_init()
和_fini()
函数中。但是,是否在堆空间中为BSS段分配了一块内存以及其他动态内存分配?
那么动态模块中的全局数据呢?符号名称是否与主要可执行文件冲突?
感谢您就这些问题发表看法。如果我必须选择一个平台,那么我想听听ELF专家的意见,因为我在Linux上进行了大部分开发工作。
最佳答案
这部分很简单:每个ELF
文件都有PT_LOAD
段,您可以在readelf -Wl foo.so
的输出中看到这些段。加载共享库时,这些段中的每一个都被mmap
编码到地址空间中,并且充当该共享库中任何静态数据的“分配”。
卸载foo.so
时,将通过munmap
系统调用处理数据(和代码)。
这种假设是不正确的。 _init
和_fini
是关于动态初始化的(例如,带有非平凡的构造函数/析构函数的C++
中的类类型的全局变量)。到_init
被调用时,所有全局变量的内存已经通过mmap
“保留”了。
.bss
节包含在与其他初始化(可写)数据相同的PT_LOAD
段中。这就是为什么p_filesz
中有单独的p_memsz
和ElfXX_Phdr
的原因:p_filesz
“覆盖”初始化的数据,(更大)的p_memsz
导致mmap
为初始化和.bss
数据“分配”空间。
那呢我在上面介绍了初始化数据。
当然。您可以在int foo = 42;
中定义a.out
,在int foo = 24;
中定义foo.so
。通常的规则是,如果foo
在a.out
的动态符号表中可见,那么无论从何处引用该foo
,都将使用该a.out
。
当foo
不导出-rdymamic
(如果它未与foo.so
链接且未针对foo.so
链接)时,或者当-Bsymbolic
与ojit_code链接时,会出现复杂问题。