如何在Linux中共享库(.so)的全局变量,使得使用该共享库的同一进程实例之间可以共享这些变量?

8
我有一个共享库(.so),在执行应用程序之前,我会预加载它,并且在共享库中有一些全局数据结构,应用程序使用这些结构。应用程序可以创建其他进程,例如使用fork(),并且这些进程可以更新共享库中的全局数据结构。我希望在所有进程中保持这些全局数据结构的一致视图。在Linux中有没有任何方法可以实现这一点?
我已经尝试使用shm_*调用和mmap()将共享库的全局数据映射到共享段,但不起作用。
3个回答

9
要表达得更清楚一些:您无法完全实现您所要求的功能。Linux不支持共享由链接器布局的全局变量。该内存将位于不可共享的映射到交换空间中。
我可以提供的普遍方法是:
1.定义一个结构,布局您的数据。没有指针!只有偏移量。 2. 第一个进程在 /tmp 中创建一个文件,根据需要设置访问权限为 rw。打开,使用 MAP_SHARED 进行映射。 3. 后续进程也会打开,并使用 MAP_SHARED 进行映射。 4. 每个人都使用结构来找到他们引用、读取或写入的部分。 5. 注意并发问题!
如果您真的只关心父进程和其派生的子进程,那么您可以使用匿名映射,不必担心文件,并且可以在全局中存储映射的位置(可以在子进程中读取)。

4
如果您只想与后代进程共享数据(而不是与任意启动的分离进程共享数据,这些进程刚好链接到相同的共享库),那么最简单的方法是在构造函数中使用mmap()创建映射(当共享库最初在父进程中加载时调用)。
MAP_ANONYMOUSMAP_SHARED标志传递给mmap - 这意味着继承映射的子进程将具有与父进程(和其他子进程)共享的映射。然后,共享库应该将要共享的数据结构存储在该mmaped内存段中(就像从malloc返回的内存一样)。显然,您可能需要某种形式的锁定。
可以使用gcc __constructor__函数属性指示库的构造函数。
您无需担心清除此类共享内存 - 当具有匿名映射的最后一个进程退出时,内存将被清除。

这并不是OP所要求的:双向共享全局变量。 - bmargulies
当然可以,如果这些全局变量存储在共享映射中(这可能意味着全局变量实际上需要是指针,但这只是一种实现细节)。 - caf
它可以在fork()中工作,但不能在exec()中工作(例如新进程使用相同的库),因此在一般情况下无法工作。 - MarkR

0
如何在已知的目录位置创建一个简单的管道,然后让其他进程通过fread/fwrite打开管道进行读/写,以共享数据...棘手的部分是确保数据以不会导致损坏的方式通过管道传递。你提到了使用共享内存shm_和mmap,但这与进程绑定,当你fork代码时,这不是问题,因为fork的代码是原始进程的一部分!希望这能帮到你。

最好的问候, 汤姆。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接