so库的static 变量深入理解

so库的static 变量深入了解

理解 so 的机制

    进程内存空间分成代码段(code),数据段(data),堆(heap),  栈(stack)

    static 是在保存数据段(data segement) 中,并且有初始值

     编译程序在在 link 的时候,为 static 分配地址到数据段(此地址是进程的内存空间,并非物理内存),当so被 load 的时候,应该是直接把so 用物理内存映射的放到load进程地址空间,用户可以直接读取 static 变量;但当用户改写此 static 变量的时候,操作系统会重新分配物理内存并映射,原来 static 变量使用的进程地址并不改变。看下面的摘要:


Shared libraries are loaded into a process by memory-mapping the file into some portion of the process's address-space. When multiple processes load the same library, the OS simply lets them share the same physical RAM.

Portions of the library that can be modified, such as static globals, are generally loaded in copy-on-write mode, so that when a write is attempted, a page fault occurs, the kernel responds by copying the affected page to another physical page of RAM (for that process only), the mapping redirected to the new page, and then finally the write operation completes.

To answer your specific points:

  1. All processes have their own address space. The sharing of physical memory between processes is invisible to each process (unless they do so deliberately via a shared memory API).
  2. All data and code live in physical RAM, which is a kind of address-space. Most of the addresses you are likely see, however, are virtual memory addresses belonging to the address-space of one process or another, even if that "process" is the kernel.



初始化

如果定义一个结构,就必须有初始化代码


class A {
  public:
   static int m;
   int m2;

};

初始化代码写在 .cpp 中

int A:m=1;


否则就会报错

3.cpp:(.text+0x6): undefined reference to `A::m'
collect2: ld returned 1 exit status

看这个错的意思是如果不初始化,编译器连地址空间都不分配了


有两个地方初始化会如何?


构造下面几个文件

--- def.h ----- 
class A {
  public:
   static int m;
   int m2;

};

--- 1.cpp ----- 
#include 
int A::m =1


--- 2.cpp ----- 
#include 
int A::m =2


--- 3.cpp ----- 
#include 
#include 
int main()
printf("%d\n";,A::m);
}

用下面的命令,把 1.cpp 2.cpp 编译为动态库

g++ --shared -fPIC 1.cpp -o lib1.so

g++ --shared -fPIC 2.cpp -o lib2.so


当首先 link lib1.so 时,使用 lib1.so 对变量的初始化
$g++ 3.cpp -L . -l1 -l2
$ ./a.out 
输出 1


当首先 link lib2.so 时,使用 lib2.so 对变量的初始化

$ g++ 3.cpp -L . -l2 -l1
$ ./a.out 
输出  2

可见 static 只认第一次初始化