首先,我已经找到了了 一些可以回答我的问题的参考资料。虽然我计划很快阅读它们(即下班后),但我仍然在这里询问以防答案是微不足道的并且不需要太多的补充知识。
情况如下:我正在编写一个共享库(我们称之为 libA.so),它需要在同一进程中保持一致的内部(如在 .c 文件中声明的静态变量)状态。这个库将被程序 P 使用(即 P 被编译为-lA
)。如果我到目前为止了解所有内容,那么 P 的地址空间将如下所示:
______________
| Program P |
| < |
| variables, |
| functions |
| from P |
| > |
| |
| < |
| libA: |
| variables, |
| functions |
| loaded (ie |
| *copied*) |
| from shared |
| object |
| > |
| < |
| stuff from |
| other |
| libraries |
| > |
|______________|
现在 P 有时会调用dlopen("libQ.so", ...)
。libQ.so 也使用 libA.so(即用 编译-lA
)。由于所有事情都发生在同一个进程中,因此无论调用来自 P 还是 Q,我都需要 libA 以某种方式保持相同的状态。
我不知道这将如何在记忆中翻译。会不会是这样:
______________
| Program P |
| < |
| P stuff |
| > |
| |
| < |
| libA stuff, |
| loaded by P |
| > | => A's code and variables are duplicated
| |
| < |
| libQ stuff |
| < |
| libA stuff,|
| loaded by Q|
| > |
| > |
|______________|
……还是这样?
______________
| Program P |
| < |
| P stuff |
| *libA |
| *libQ |
| > |
| |
| < |
| libA stuff, |
| loaded by P |
| > | => A's code is loaded once, Q holds some sort of pointer to it
| |
| < |
| libQ stuff |
| *libA |
| > |
|______________|
在第二种情况下,为单个进程保持一致状态是微不足道的;在第一种情况下,它需要更多的努力(例如,一些共享内存段,使用进程 ID 作为第二个参数ftok()
)。
当然,由于我对链接和加载的工作原理了解有限,所以上面的图表可能完全错误。据我所知,共享库可能位于内存中的固定空间,并且每个进程都访问相同的数据和代码。该行为还可能取决于 A 和/或 P 和/或 Q 的编译方式。而且这种行为可能与平台无关。