近期在解决一个编译问题时,一直在考虑一个问题,那就是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_usedw _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_handlew __gmon_start__
0000000000600634 d __init_array_end
0000000000600634 d __init_array_start
0000000000400490 T __libc_csu_fini
00000000004004a0 T __libc_csu_initU __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_usedw _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_handlew __gmon_start__
0000000000600634 d __init_array_end
0000000000600634 d __init_array_start
0000000000400490 T __libc_csu_fini
00000000004004a0 T __libc_csu_initU __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_startprocpushq   %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq    %rsp, %rbp.cfi_def_cfa_register 6movq    $.LC1, -8(%rbp)movl    $1819043176, -32(%rbp)movl    $1919907695, -28(%rbp)movw    $25708, -24(%rbp)movl    $1, %eaxleave.cfi_def_cfa 7, 8ret.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的内存管理做具体的介绍

Linux段管理,BSS段,data段,.rodata段,text段相关推荐

  1. bss、data、rodata和text

    在ELF格式的可执行文件中,全局内存包括三种:bss.data和rodata.其它可执行文件格式与之类似.了解了这三种数据的特点,我们才能充分发挥它们的长处,达到速度与空间的最优化. 1.bss(Bl ...

  2. bss、data和rodata区别与联系

    有人可能会说,全局内存就是全局变量嘛,有必要专门一章来介绍吗?这么简单的东西,还能玩出花来?我从来没有深究它,不一样写程序吗?关于全局内存这个主题虽然玩不出花来,但确实有些重要,了解这些知识,对于优化 ...

  3. 快速理解 .bss、.data和.rodata

    全局变量是放在全局内存中的,用static修饰的局部变量也是会放在放全局内存的,它的作用域是局部的,但生命期是全局的. 全局强调的是它的生命期,而不是它的作用域,所以有时可能把两者的概念互换.一般来说 ...

  4. 全局内存BSS,DATA,RODATA的区别以及其他内存区间相关

    刚接触c语言的时候,了解了全局变量这个概念,只知道所谓全局变量的意思就是代码文件里面所有的函数都可以随时调用修改的变量,而其实这种理解是十分不准确的,但随着后期学习的深入,接触了计算机组成原理和汇编的 ...

  5. 关于text段、data段和bss段

    根据APUE,程序分为下面的段:.text, data (initialized), bss, stack, heap. data/bss/text: text段在内存中被映射为只读,但.data和. ...

  6. C/C++程序内存布局(data段,bss段,text段)以及static关键字详解

    目录 1.内存布局 1.1 data段(可读可写) 1.2 text段(只读) 1.3 bss段(可读可写) 1.4 堆区 1.5 栈区 1.6全局区/静态区 1.7 字符串常量区 1.8 代码区 1 ...

  7. text段、data段和bss段知识介绍

    一.总体概述 1.bss(可读可写)      bss是英文Block Started by Symbol的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0.BSS ...

  8. linux代码段映射,bss,data,text,rodata,堆,栈,常量段与其各段在物理存储中关系

    本文想从linux出发[目前还想可不可以从51单片机出发],解答程序代码和各种数据结构是如何存储(映射)到存储区的. 目前未完成整理,还是初稿的想法.bss段: BSS段(bsssegment)通常是 ...

  9. (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)(C/C++存储类型总结)(内存管理)

    文章目录 bss段 data段 text段 堆(heap) 栈(stack) 一个程序本质上都是由 bss段.data段.text段三个组成的. 存储类型总结 bss段 bss段(bss segmen ...

  10. 汇编中bss,data,text,rodata,heap,stack段的作用

    原文:https://blog.csdn.net/bxd1314/article/details/38433837 Table of Contents bss段: data段: text段: roda ...

最新文章

  1. 饥荒海难机器人怎么用_饥荒:海难是一款野外生存游戏
  2. HTML元素title里面如何换行
  3. 硬件:笔记本电脑7大分类总结,看完你就明白了!
  4. LeetCode 130. 被围绕的区域(图的BFS/DFS)
  5. Git常见指令的本质
  6. python对八大常见排序算法的总结和实现以及时间消耗分析
  7. Linux中vi的退出命令
  8. 在线生成android ios icon,一键生成Android/Android-HD/IOS 多尺寸ICON
  9. 一种防止拍摄屏幕的新技术
  10. 兼容各操作系统平台的Anki选择题库模板
  11. Excel怎么一次性删除数据末尾的空格
  12. C# Excel导出超出65536行报错
  13. 在线HTML转XML工具
  14. python中的 split()函数
  15. tf第十二讲:TextCNN做文本分类的实战代码
  16. 算法(六):图解贪婪算法
  17. 数据库系统实践 IV 查询插入修改删除操作
  18. 视频或音频数据存储的2种格式packed和planar
  19. python下批量下载专利-欧洲专利局
  20. 马化腾2018中国“互联网+”数字经济峰会演讲《互联网+助力数字中国建设》全文...

热门文章

  1. Redis搭建及介绍
  2. Postman局部变量设置
  3. js如何监听元素事件是否被移除_javascript:什么是js事件?(上)
  4. 一年多开源没进展,我也放弃了
  5. LINUX下载maven/mvn
  6. 文字处理技术:有哪些难点?
  7. LINUX下载编译libyuv
  8. 论耐力,哺乳动物中人类可能是第一
  9. Python安装cv2库出错及解决:Could not find a version that satisfies the requirement cv2
  10. MySQL用C访问的示例代码