我试图理解共享内存概念的基础。我试图创建一个具有一个函数和一个STATIC数组变量的共享库。我想通过该共享库的功能访问静态数组变量。
这是我的共享库
//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;
}
我已按照shared library
中的说明创建了共享库对象(libfoo.so)现在我的问题是
1&GT;如果我从两个不同的程序(program1和program2)访问foo(),那么program1和program2会有单独的foo()函数副本吗?
2 - ;是否会为program1和program2?
单独复制静态DATA数组3&GT;它们会加载到相同的物理内存位置吗?如果单独加载静态DATA数组,有没有办法强制/加载到相同的内存位置?
4&GT;有没有办法找到为program1和program2存储静态DATA数组的位置?
我在linux下使用gcc。任何帮助都将受到高度赞赏。谢谢。
答案 0 :(得分:5)
只有一种定义明确的方法可以在进程之间共享内存:Shared Memory。从不同进程访问此内存需要正确同步对该区域的访问(通过进程本身)。如果不同步访问,则会导致UNIX / Linux / Windows等多任务操作系统出现故障。
详细答案:
如果我从两个不同的程序(program1和program2)访问foo(),那么program1和program2会有单独的foo()函数副本吗?
没有。将程序与共享库链接时,函数代码将在链接到该库的多个程序之间共享。
是否会为program1和program2提供单独的静态DATA数组副本?
是。不会共享任何数据。
它们会加载到相同的物理内存位置吗?如果单独加载静态DATA数组,有没有办法强制/加载到相同的内存位置?
否(但请阅读上面的共享内存)
有没有办法找到为program1和program2存储静态DATA数组的位置?
是的,您可以使用GDB找到它。但这些节目无法相互了解。
答案 1 :(得分:4)
在Advanced Linux Programming,virtual memory,address space,processes,paging,thrashing,{{上阅读ELF和wikipages 3}}
另请阅读ASLR
请注意,在某些进程中运行的应用程序代码不关心物理内存,它只使用虚拟内存。 Drepper's paper: How to write shared libraries可以自由地在物理内存中移动数据(例如,在某些页面中换出或交换)。您不应该关心(在物理RAM中)您的数据位置(并且可以随时更改,因此从应用程序代码的角度来看,这个问题没有任何意义)。
共享对象应使用-fPIC
GCC标志编译为Linux kernel(否则,它将包含太多position independent code)。然后,函数的机器代码(如foo
)通常位于共享的只读文本段中 - 包含它的RAM(如果有的话)在多个进程之间共享。
尝试以下命令
cat /proc/self/maps
显示运行cat
命令的进程的虚拟地址空间。一些内存段是共享的,另一些是私有副本......
同时阅读relocation - 启动程序并设置其地址空间 - execve(2) - 创建新的porocess-,fork(2) - 更改地址空间 - (由动态链接器mmap(2)),ld-linux(8)(动态加载插件)和dlopen(3) - 查询内核有关各种事物的信息。请注意,如果您具有root权限,则可以使用proc(5)将内存锁定到RAM中(避免交换它)。
每个进程都有自己的地址空间,特别是有自己的数据段(用于static
或全局extern
变量,例如在共享对象或程序可执行文件中。因此,当然,如果进程更改了某些static
数据,则更改对于进程是本地的,并且对于运行相同可执行文件或相同共享库的其他进程是不可见的。要与其他某个流程共享数据,请使用mlock(2)与MAP_SHARED
(可能是PROT_WRITE
)或Posix共享内存mmap(2) ...
BTW,这是一个非常常见的问题。我很确定我已经多次在StackOverflow上回答了几乎相同的事情。