• Linux段管理,BSS段,data段,.rodata段,text段


             近期在解决一个编译问题时,一直在考虑一个问题,那就是Linux下可执行程序执行时内存是什么状态,是依照什么方式分配内存并执行的。查看了一下资料。就此总结一下,众所周知。linux下内存管理是通过虚存管理的,在分配内存是并不是在物理内存开辟了一段空间,而是在使用时才分配的。并且是通过段页式管理。

    以上比較废话,開始看看程序执行时内存会是什么状态。

            在linux下内存分配是以页为单位的。而页是通过段管理。各个段之间是独立的,方便管理。linux程序执行时。能够分为下面几个内存段:

    一、BSS段 bss segment)一般是指用来存放程序中未初始化的全局变量的一块内存区域。

    BSS是英文Block Started by Symbol的简称。

    BSS段属于静态内存分配。

        该段用于存储未初始化的全局变量或者是默认初始化为0的全局变量,它不占用程序文件的大小,可是占用程序执行时的内存空间。

    #define DEBUG "debug"
    
    int space[1024][1024];
    
    int main()
    {
      char *a = DEBUG;
      return 1;
    }

    上面声明了一个space的二维数组,是一个全局变量,没有被初始化。通过nm命令能够查看程序中的符号信息例如以下:

    0000000000600660 d _DYNAMIC
    00000000006007f8 d _GLOBAL_OFFSET_TABLE_
    0000000000400578 R _IO_stdin_used
                     w _Jv_RegisterClasses
    0000000000600640 d __CTOR_END__
    0000000000600638 d __CTOR_LIST__
    0000000000600650 D __DTOR_END__
    0000000000600648 d __DTOR_LIST__
    0000000000400630 r __FRAME_END__
    0000000000600658 d __JCR_END__
    0000000000600658 d __JCR_LIST__
    000000000060081c A __bss_start
    0000000000600818 D __data_start
    0000000000400530 t __do_global_ctors_aux
    00000000004003e0 t __do_global_dtors_aux
    0000000000400580 R __dso_handle
                     w __gmon_start__
    0000000000600634 d __init_array_end
    0000000000600634 d __init_array_start
    0000000000400490 T __libc_csu_fini
    00000000004004a0 T __libc_csu_init
                     U __libc_start_main@@GLIBC_2.2.5
    000000000060081c A _edata
    0000000000a00840 A _end
    0000000000400568 T _fini
    0000000000400358 T _init
    0000000000400390 T _start
    00000000004003bc t call_gmon_start
    0000000000600820 b completed.6347
    0000000000600818 W data_start
    0000000000600828 b dtor_idx.6349
    0000000000400450 t frame_dummy
    0000000000400474 T main
    0000000000600840 B space

    最后一行的B表示是BSS段。也就表示space是存在于BSS段中的。

    二、data段 该段用于存储初始化的全局变量,初始化为0的全局变量出于编译优化的策略还是被保存在BSS段,对上面的程序做一下更改就能够看到是怎样分配的了。

    #define DEBUG "debug"
    
    int space[1024][1024];
    int data = 1;
    int no_data = 0;
    
    int main()
    {
      char *a = DEBUG;
      return 1;
    }

    使用nm查看后

    0000000000600660 d _DYNAMIC
    00000000006007f8 d _GLOBAL_OFFSET_TABLE_
    0000000000400578 R _IO_stdin_used
                     w _Jv_RegisterClasses
    0000000000600640 d __CTOR_END__
    0000000000600638 d __CTOR_LIST__
    0000000000600650 D __DTOR_END__
    0000000000600648 d __DTOR_LIST__
    0000000000400630 r __FRAME_END__
    0000000000600658 d __JCR_END__
    0000000000600658 d __JCR_LIST__
    0000000000600820 A __bss_start
    0000000000600818 D __data_start
    0000000000400530 t __do_global_ctors_aux
    00000000004003e0 t __do_global_dtors_aux
    0000000000400580 R __dso_handle
                     w __gmon_start__
    0000000000600634 d __init_array_end
    0000000000600634 d __init_array_start
    0000000000400490 T __libc_csu_fini
    00000000004004a0 T __libc_csu_init
                     U __libc_start_main@@GLIBC_2.2.5
    0000000000600820 A _edata
    0000000000a00840 A _end
    0000000000400568 T _fini
    0000000000400358 T _init
    0000000000400390 T _start
    00000000004003bc t call_gmon_start
    0000000000600820 b completed.6347
    000000000060081c D data
    0000000000600818 W data_start
    0000000000600828 b dtor_idx.6349
    0000000000400450 t frame_dummy
    0000000000400474 T main
    0000000000600830 B no_data
    0000000000600840 B space

    能够看到变量data被分配在data段,而被初始化为0的no_data被分配在了BSS段。

    三、.rodata段

    该段也叫常量区,用于存放常量数据,ro就是Read Only之意。

    可是注意并非全部的常量都是放在常量数据段的。其特殊情况例如以下:
    1)有些马上数与指令编译在一起直接放在代码段。

    int main()
    {
      int a = 10;
      return 1;
    }
    a是常量。可是它没有被放入常量区,而是在指令中直接通过马上数赋值



    2)对于字符串常量,编译器会去掉反复的常量,让程序的每一个字符串常量仅仅有一份。

    char *str = "123456789";
    char *str1 = "helloworld";
    
    int main()
    {
      char* a = "helloworld";
      char b[10] = "helloworld";
      return 1;
    }
    汇编代码例如以下:

                    .file   "hello.c"
    .globl str
            .section        .rodata
    .LC0:
            .string "123456789"
            .data
            .align 8
            .type   str, @object
            .size   str, 8
    str:
            .quad   .LC0
    .globl str1
            .section        .rodata
    .LC1:
            .string "helloworld"
            .data
            .align 8
            .type   str1, @object
            .size   str1, 8
    str1:
            .quad   .LC1
            .text
    .globl main
            .type   main, @function
    main:
    .LFB0:
            .cfi_startproc
            pushq   %rbp
            .cfi_def_cfa_offset 16
            .cfi_offset 6, -16
            movq    %rsp, %rbp
            .cfi_def_cfa_register 6
            movq    $.LC1, -8(%rbp)
            movl    $1819043176, -32(%rbp)
            movl    $1919907695, -28(%rbp)
            movw    $25708, -24(%rbp)
            movl    $1, %eax
            leave
            .cfi_def_cfa 7, 8
            ret
            .cfi_endproc
    .LFE0:
            .size   main, .-main
            .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)"
            .section        .note.GNU-stack,"",@progbits
    能够看到str1和a同一时候指向.rodata段中同一个LC1,而是用数组初始化的字符串常量是没有放入常量区的,另外用const修饰的全局变量是放入常量区的,可是使用cons修饰的局部变量仅仅是设置为仅仅读起到防止改动的效果,没有放入常量区。

    3)有些系统中rodata段是多个进程共享的,目的是为了提高空间的利用率。

    四、text段

    text段是用于存放程序代码的,编译时确定,仅仅读。更进一步讲是存放处理器的机器指令,当各个源文件单独编译之后生成目标文件。经连接器链接各个目标文件并解决各个源文件之间函数的引用,与此同一时候,还得将全部目标文件里的.text段合在一起,但不是简单的将它们“堆”在一起就完事,还须要处理各个段之间的函数引用问题。

    五、stack段

    也就是栈段,常说的堆栈段之中的一个,是由系统负责申请释放,其操作方式类似stack,用于存储參数变量及局部变量,事实上函数的运行也是stack的方式,所以才有了递归

    六、heap段

    也就是俗称的堆。它由用户申请和释放。申请时至少分配虚存,当真正存储数据时才分配对应的实存,释放时也并不是马上释放实存。而是可能被反复利用。待兴许会再细致介绍相关的知识。


    能够看到堆和栈的内存增长方向是相反的。兴许会对linux的内存管理做具体的介绍


  • 相关阅读:
    Natas29 Writeup(Perl命令注入、00截断、绕过过滤)
    Natas27 Writeup(mysql溢出截断漏洞)
    Natas26 Writeup(PHP反序列化漏洞)
    Natas25 Writeup(目录遍历、头部注入)
    Natas24 Writeup(strcmp绕过漏洞)
    yum提示Another app is currently holding the yum lock; waiting for it to exit
    linux网站
    fastdfs_5.05下载
    sqlog连接虚拟机mysql服务
    java知识博客网站(一些配置和学习的记录)
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5105316.html
Copyright © 2020-2023  润新知