4

首先,我已经找到了 一些可以回答我的问题的参考资料。虽然我计划很快阅读它们(即下班后),但我仍然在这里询问以防答案是微不足道的并且不需要太多的补充知识。

情况如下:我正在编写一个共享库(我们称之为 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 的编译方式。而且这种行为可能与平台无关。

4

1 回答 1

7

共享库的代码段以每个系统的单个实例存在于内存中。然而,它可以为不同的进程映射到不同的虚拟地址,因此不同的进程在不同的地址看到相同的函数(这就是为什么进入共享库的代码必须编译为 PIC)。

共享库的数据段为每个进程创建一个副本,并由库中指定的任何初始值进行初始化。

这意味着库的调用者不需要知道它是否是共享的:一个进程中的所有调用者都会看到函数的相同副本和库中定义的外部变量的相同副本。

不同的进程执行相同的代码,但有各自的数据副本,每个进程一份。

于 2014-04-04T12:41:04.133 回答