so库的static 变量深入了解

来源:互联网 发布:淘宝商城怎么注册 编辑:程序博客网 时间:2024/06/08 13:52

理解 so 的机制

    进程内存空间分成代码段(code),数据段(data),堆(heap),  栈(stack), 考虑加载 .so,进程空间应该不只一份 code 和 data segment)

    static 变量保存可执行文件或 so 的数据段(data segement) 中,并且有初始值

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

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.

     当用 gcc 编译时,  可以看见可执行文件中有此 static 变量的 symbol ( 详见本文最后),  当运行load 动态库时 resolve 此 symbol

初始化

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


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

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


两个so都初始化static变量会如何?

构造下面几个文件

--- 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 只认第一次初始化


另: 可以用下面命令查看, static 是全局的 symbol

$readelf -s a.out

...

51: 0000000000601028     4 OBJECT  GLOBAL DEFAULT   26 _ZN1A1mE

...

注: name mangling 的解释

_Z( 开始标志  )  N ( nested) 1( A长度) A (class A) 1 ( m 的长度) m (static int m) E ( 结束标志)

原创粉丝点击