在同一进程中多次加载的共享库的地址空间

Pen*_*lec 4 c linux gcc shared-libraries address-space

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

下面是这样的情况:我正在编写一个共享库(让我们称之为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   |
| >            |
|______________|
Run Code Online (Sandbox Code Playgroud)

现在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|
|  >           |
| >            |
|______________|
Run Code Online (Sandbox Code Playgroud)

......还是这样?

 ______________
| 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       |
| >            |
|______________|
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,保持单个过程的一致状态是微不足道的; 在第一种情况下,它将需要更多的努力(例如一些共享内存段,使用进程id作为第二个参数ftok()).

当然,由于我对链接和加载的工作方式知之甚少,上面的图表可能完全错误.据我所知,共享库可能位于内存中的固定空间,每个进程都访问相同的数据和代码.行为还可能取决于A和/或P和/或Q的编译方式.而且这种行为可能与平台无关.

cro*_*ser 5

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

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

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

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