不同的进程是否具有共享静态变量或公共副本的单独副本?

时间:2014-02-11 10:53:19

标签: c linux shared-libraries shared-memory

我试图理解共享内存概念的基础。我试图创建一个具有一个函数和一个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。任何帮助都将受到高度赞赏。谢谢。

2 个答案:

答案 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 Programmingvirtual memoryaddress spaceprocessespagingthrashing,{{上阅读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上回答了几乎相同的事情。