进程内存镜像

进程的内存映像是指内核在内存中如何存放可执行程序文件。 在将程序转化为进程的过程中,操作系统将可执行程序由硬盘复制到内存。

内存镜像一般布局:

内存镜像

  • 正文段

    • 包括常量区和代码区,用于存放常量和CPU执行的机器指令部分。
    • 正文段是可共享的,所以即使频繁执行的程序在存储器中也只有一个副本
    • 正文段为只读,以防止程序由于意外修改其指令
  • 初始化数据段

    • 包含程序中需明确赋初值的变量。
    • 可读写
  • bss(block started by symbol)

    • 称为由符号开始的块
    • 存放未初始化的数据
    • 执行时动态分配
    • 存放自动变量以及每次函数调用时所需保存的信息

使用pmap 可以查看进程的内存镜像

[root@iz2zecj7a5r32f2axsctb9z test]\# pmap 723
723:   nginx: master process /usr/local/nginx/sbin/nginx -g daemon off;
0000000000400000    684K r-x-- nginx
00000000006aa000      4K r---- nginx
00000000006ab000     72K rw--- nginx
00000000006bd000    128K rw---   [ anon ]
0000000002146000   1084K rw---   [ anon ]
00007f85164fa000     48K r-x-- libnss_files-2.17.so
00007f8516506000   2044K ----- libnss_files-2.17.so
00007f8516705000      4K r---- libnss_files-2.17.so
00007f8516706000      4K rw--- libnss_files-2.17.so
00007f8516707000     24K rw---   [ anon ]
00007f851670d000    144K r-x-- libselinux.so.1
00007f8516731000   2044K ----- libselinux.so.1
00007f8516930000      4K r---- libselinux.so.1
00007f8516931000      4K rw--- libselinux.so.1
00007f8516932000      8K rw---   [ anon ]
00007f8516934000     88K r-x-- libresolv-2.17.so
00007f851694a000   2048K ----- libresolv-2.17.so
00007f8516b4a000      4K r---- libresolv-2.17.so
00007f8516b4b000      4K rw--- libresolv-2.17.so
00007f8516b4c000      8K rw---   [ anon ]
00007f8516b4e000     12K r-x-- libkeyutils.so.1.5
00007f8516b51000   2044K ----- libkeyutils.so.1.5
00007f8516d50000      4K r---- libkeyutils.so.1.5
00007f8516d51000      4K rw--- libkeyutils.so.1.5
00007f8516d52000     56K r-x-- libkrb5support.so.0.1
00007f8516d60000   2048K ----- libkrb5support.so.0.1
00007f8516f60000      4K r---- libkrb5support.so.0.1
00007f8516f61000      4K rw--- libkrb5support.so.0.1
00007f8516f62000    196K r-x-- libk5crypto.so.3.1
00007f8516f93000   2044K ----- libk5crypto.so.3.1
00007f8517192000      8K r---- libk5crypto.so.3.1
00007f8517194000      4K rw--- libk5crypto.so.3.1
00007f8517195000     12K r-x-- libcom_err.so.2.1
00007f8517198000   2044K ----- libcom_err.so.2.1
00007f8517397000      4K r---- libcom_err.so.2.1
00007f8517398000      4K rw--- libcom_err.so.2.1
00007f8517399000    868K r-x-- libkrb5.so.3.3
00007f8517472000   2044K ----- libkrb5.so.3.3
00007f8517671000     56K r---- libkrb5.so.3.3
00007f851767f000     12K rw--- libkrb5.so.3.3
00007f8517682000    296K r-x-- libgssapi_krb5.so.2.2
00007f85176cc000   2048K ----- libgssapi_krb5.so.2.2
00007f85178cc000      4K r---- libgssapi_krb5.so.2.2
00007f85178cd000      8K rw--- libgssapi_krb5.so.2.2
00007f85178cf000      8K r-x-- libfreebl3.so
00007f85178d1000   2044K ----- libfreebl3.so
00007f8517ad0000      4K r---- libfreebl3.so
00007f8517ad1000      4K rw--- libfreebl3.so
00007f8517ad2000   1808K r-x-- libc-2.17.so
00007f8517c96000   2044K ----- libc-2.17.so
00007f8517e95000     16K r---- libc-2.17.so
00007f8517e99000      8K rw--- libc-2.17.so
00007f8517e9b000     20K rw---   [ anon ]
00007f8517ea0000     84K r-x-- libz.so.1.2.7
00007f8517eb5000   2044K ----- libz.so.1.2.7
00007f85180b4000      4K r---- libz.so.1.2.7
00007f85180b5000      4K rw--- libz.so.1.2.7
00007f85180b6000   2264K r-x-- libcrypto.so.1.0.2k
00007f85182ec000   2048K ----- libcrypto.so.1.0.2k
00007f85184ec000    112K r---- libcrypto.so.1.0.2k
00007f8518508000     52K rw--- libcrypto.so.1.0.2k
00007f8518515000     16K rw---   [ anon ]
00007f8518519000    412K r-x-- libssl.so.1.0.2k
00007f8518580000   2048K ----- libssl.so.1.0.2k
00007f8518780000     16K r---- libssl.so.1.0.2k
00007f8518784000     28K rw--- libssl.so.1.0.2k
00007f851878b000    384K r-x-- libpcre.so.1.2.0
00007f85187eb000   2048K ----- libpcre.so.1.2.0
00007f85189eb000      4K r---- libpcre.so.1.2.0
00007f85189ec000      4K rw--- libpcre.so.1.2.0
00007f85189ed000     32K r-x-- libcrypt-2.17.so
00007f85189f5000   2044K ----- libcrypt-2.17.so
00007f8518bf4000      4K r---- libcrypt-2.17.so
00007f8518bf5000      4K rw--- libcrypt-2.17.so
00007f8518bf6000    184K rw---   [ anon ]
00007f8518c24000     92K r-x-- libpthread-2.17.so
00007f8518c3b000   2044K ----- libpthread-2.17.so
00007f8518e3a000      4K r---- libpthread-2.17.so
00007f8518e3b000      4K rw--- libpthread-2.17.so
00007f8518e3c000     16K rw---   [ anon ]
00007f8518e40000      8K r-x-- libdl-2.17.so
00007f8518e42000   2048K ----- libdl-2.17.so
00007f8519042000      4K r---- libdl-2.17.so
00007f8519043000      4K rw--- libdl-2.17.so
00007f8519044000    136K r-x-- ld-2.17.so
00007f8519250000     36K rw---   [ anon ]
00007f8519263000      4K rw-s- zero (deleted)
00007f8519264000      4K rw---   [ anon ]
00007f8519265000      4K r---- ld-2.17.so
00007f8519266000      4K rw--- ld-2.17.so
00007f8519267000      4K rw---   [ anon ]
00007ffee56fd000    132K rw---   [ stack ]
00007ffee5756000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total            46636K

可执行程序和内存映像的区别

  • 可执行程序位于磁盘中而内存映像位于内存中;

  • 可执行程序没有堆栈,因为程序被加载到内存中才会分配堆栈;

  • 可执行程序虽然也有未初始化数据段但它并不被储存在位于硬盘中的可执行文件中;

  • 可执行程序是静态的、不变的,而内存映像随着程序的执行是在动态变化的,数据段随着程序的执行要存储新的变量值,栈在函数调用时也是不断变化中。

c 查看各个地址

#include <stdio.h>

const int g_A = 10;    // 常量
int g_B  = 20;    // 数据段
static int g_C = 30;   // 数据段
static int g_D;   // bss
int g_E;   // bss 
char *p1;   // bss

int main(int argc, char *argv[]){
    int local_A;    // 栈
    static int local_C = 0;  // 数据段
    static int local_D;   // 数据段

    char *p3 = "123456";   // p3在栈上, 123456在常量区

    p1 = (char *) malloc(10);    // 堆

    strcpy(p1, "123456");

    printf("\n");
    printf("main address: %p\n", main);
    printf("g_A addrss, %p\n", &g_A);
    printf("g_B addrss, %p\n", &g_B);
    printf("g_C addrss, %p\n", &g_C);
    printf("g_D addrss, %p\n", &g_D);
    printf("g_E addrss, %p\n", &g_E);
    printf("p1 addrss, %p\n", &p1);

    printf("local_A addrss, %p\n", &local_A);
    printf("local_C addrss, %p\n", &local_C);
    printf("local_D addrss, %p\n", &local_D);

    printf("p3 addrss, %p\n", &p3);
    return 0;
}
文档更新时间: 2021-03-14 21:48   作者:周国强