不同的进程是否有单独的共享静态variables或普通副本的副本?

我想了解共享内存概念的基础。 我试图创build一个具有一个函数和一个STATIC数组variables的共享库。 我想通过该共享库的函数来访问静态数组variables。

这是我的共享库

//foo.c #include <stdio.h> static int DATA[1024]={1 ,2 ,3 ,...., 1024}; inline void foo(void) { int j, k=0; for(j=0;j<1024;j++) { k=DATA[j]; } k+=0; } 

我通过遵循共享库的指令创build了共享库对象(libfoo.so)

现在我的问题是

1>如果我从两个不同的程序(程序1和程序2)访问foo(),程序1和程序2是否会有单独的foo()函数副本?

2>会有程序1和程序2的静态DATA数组的单独副本?

3>他们将加载到相同的物理内存位置? 如果静态DATA数组分别加载,有什么办法强制/使它加载到相同的内存位置?

4>有什么办法可以find程序1和程序2的静态DATA数组的存储位置吗?

我在linux下使用gcc。 任何帮助将不胜感激。提前感谢。

只有一个定义好的方法可以在进程之间共享内存 : 共享内存 。 从不同的进程访问这个内存需要正确的同步对这个区域的访问(通过进程本身)。 没有同步访问,就会导致像UNIX / Linux / Windows这样的多任务操作系统的灾难。

详细解答:

如果我从两个不同的程序(程序1和程序2)访问foo(),程序1和程序2是否会有单独的foo()函数副本?

没有。当你的程序和一个共享库链接时,函数的代码将在与这个库链接的多个程序之间被共享。

会有程序1和程序2的静态DATA数组的单独副本?

是。 没有数据将被共享。

他们会加载到相同的物理内存位置? 如果静态DATA数组分别加载,有什么办法强制/使它加载到相同的内存位置?

否(但请阅读上面的共享内存)

有什么办法可以找到程序1和程序2的静态DATA数组的存储位置吗?

是的,你可以使用GDB找到它。 但是这些程序无法找到对方。

阅读有关虚拟内存 , 地址空间 , 进程 , 分页 , 抖动 , ELF , ASLR的 高级Linux编程和wikip

另请阅读Drepper的论文: 如何编写共享库

请注意,在某个进程中运行的应用程序代码并不关心物理内存 ,它只使用虚拟内存 。 Linux内核可以自由移动物理内存中的数据(例如换出或交换某些页面)。 你不应该关心你的数据在哪里(在物理内存中),并且可以随时改变,所以从应用程序代码的角度来看,这个问题没有任何意义)。

应使用-fPIC GCC标志将共享对象编译为与位置无关的代码 (否则将包含太多的重定位 )。 然后,一个函数的机器代码(比如你的foo )通常会坐在一个共享的只读文本段中,并且包含它的RAM(如果有的话)在多个进程之间共享。

尝试下面的命令

 cat /proc/self/maps 

它向您显示运行该cat命令的进程的虚拟地址空间。 一些内存段是共享的,其他的是私人副本…

还读取execve(2) – 启动程序并设置其地址空间 – fork(2) – 创建一个新的porocess – mmap(2) – 更改地址空间 – (由动态链接器ld-linux使用(8) ), dlopen(3) (动态加载插件)和proc(5) – 向内核查询各种事情。 注意,如果你有root权限,你可以使用mlock(2)将内存锁定到RAM中(避免交换它)。

每个进程都有自己的地址空间,特别是有自己的数据段(对于static或全局extern变量,例如在共享对象或程序可执行文件中)。 所以当然,如果一个进程改变了一些static数据,那么这个改变对于进程来说是本地的,并且对于运行相同可执行文件或者共享库的其他进程是不可见的。 要与其他进程共享数据,请使用带有MAP_SHARED (可能是PROT_WRITE )或Posix共享内存shm_overview(7)的 mmap(2 ) …

顺便说一句,这是一个非常普遍的问题。 我很确定我几次在StackOverflow上回答了几乎相同的问题。