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

摘要:
linux下的内存管理通过虚拟内存进行管理。内存分配不会在物理内存中打开空间,但仅在使用时才打开。它是按段落和页面管理的。在Linux中,内存分配基于页面。BSS是英语中BlockStartedbySymbol的缩写。可以通过nm命令查看节目中的符号信息,例如:0000000000660d_DYNAMIC 00000000006007f8d_ GLOBAL_ OFFSET_ TABLE_ 000000000040578R_ IO_ stdin_ used w_ Jv_ RegisterClasses0000000000640d_ CTOR_ END__ 0000000000638d_ CTOR_ LIST__ 0000000000650D_ DTOR_ END__ 000000000040648d_ DTOR_LIST__ 00000000004006630r_ FRAME_ END__ 00000000658d_ JCR_ END__0000000000658d__ JCR_ LIST__ 0000000060081cA__ bss_开始0000000000600818D_数据_开始0000000000400530t_ do_ global_ ctors_aux000000004003e0t_ do_global_ dtors_aux0000000400580R_ dso_handlew__gmon_开始0000000000600634d_ init_ array_结束0000000000634d__ init_ array开始0000000000400490T_ libc_csu_finish00000000004004a0T_ libc_csu_initU_ libc_start_ main@@GLIBC_2.2.5000000000060081cA_edata0000000000a00840A_end0000000000400568T_fini0000000000400358T_init0000000000400390T_start00000000004003bctcall_ gmon_ start0000000000600820b已完成634700000000000600818Wdata_ start000000000060828bdtor_ idx.6349000000000400450tframe_ Dummy000000000000400474Tmin000000000000600840Bspace最后一行中的B表示BSS段#defineDEBUG“调试”intspace[1024][1024];intdata=1;intno_data=0;Intmain(){char*a=DEBUG;return1;}在用nm观察后,0000000000 600660d_ DYNAMIC 00000000006007f8d_ GLOBAL_ OFFSET_ TABLE_ 0000000000 400578R_ IO_ stdin_ used w_ Jv_ RegisterClasses 0000000000640d__ CTOR_ END__ 0000000000 600638d_ CTOR_ LIST__ 0000000000 00650D_ _ DTOR_ END__ 0000000000600648d_ _ DTOR _ LIST__ 0000000000400630r_ _ FRAME_ END__ 00000000 600658d_ _ JCR_ END__0000000000 600658D_ _ JCR_ LIST__ 00000000 600820A__ bss_开始0000000000600818D_数据_开始0000000000400530t_ do_ global_ ctors_aux000000004003e0t_ do_global_ dtors_aux0000000400580R_ dso_handlew__gmon_开始0000000000600634d_ init_ array_结束0000000000634d__ init_ array开始0000000000400490T_ libc_csu_finish00000000004004a0T_ lib_csu_ initU_ libc_start_ main@@GLIBC_2.2.50000000000600820A_ edata0000000000a00840A_end0000000000400568T_fini0000000000400358T_init0000000000400390T_start00000000004003bctcall_ gmon_ start0000000000600820b已完成将数据分配给BSS段。

         近期在解决一个编译问题时,一直在考虑一个问题,那就是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是常量。可是它没有被放入常量区,而是在指令中直接通过马上数赋值

Linux段管理,BSS段,data段,.rodata段,text段第1张

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段管理,BSS段,data段,.rodata段,text段第2张

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


免责声明:文章转载自《Linux段管理,BSS段,data段,.rodata段,text段》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇python3 安装pyhanlp方法vs 外部依赖项、附加依赖项以及如何添加依赖项目下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python爬虫(2)——urllib、get和post请求、异常处理、浏览器伪装

urllib基础 urlretrieve() urlretrieve(网址,本地文件存储地址) 直接下载网页到本地 import urllib.request #urlretrieve(网址,本地文件存储地址) 直接下载网页到本地 urllib.request.urlretrieve("http://www.baidu.com","dld.html") u...

Ubuntu 16.04LTS修改开机启动项

装上Ubuntu16.04后,每次开机都得手选开机项,挺麻烦 sudo vi /etc/default/grub GRUB_DEFAULT=0GRUB_HIDDEN_TIMEOUT=0GRUB_HIDDEN_TIMEOUT_QUIET=trueGRUB_TIMEOUT=10GRUB_DISTRIBUTOR=`lsb_release -i -s 2>...

VMware虚拟机中如何安装VMWareTools详解

VMware虚拟机中如何安装VMWare-Tools详解 好处:可以支持图形界面,可以支持共享文件功能等VMware虚拟机中如何配置显卡 VMware作为一款虚拟机利器,很多人都利用它来实现Linux与Windows的和平共处。相对于普通的多重引导,有了VMware,Linux对磁盘空间变得不再挑剔,不需要像多重系统那样要求独霸某个分区,随便在哪个Wind...

Linux下防御ddos攻击

导读 Linux服务器在运营过程中可能会受到黑客攻击,常见的攻击方式有SYN,DDOS等。通过更换IP,查找被攻击的站点可能避开攻击,但是中断服务的时间比较长。比较彻底的解决方法是添置硬件防火墙。不过,硬件防火墙价格比较昂贵。可以考虑利用Linux 系统本身提供的防火墙功能来防御。 SYN攻击是利用TCP/IP协议3次握手的原理,发送大量的建立...

Linux 服务器网卡 IP 配置

  网卡是 Linux 服务器最重要的设备。据统计,Linux 网络故障有 35% 在物理层、25% 在数据链路层、10% 在网络层、10% 在传输层、10% 在对话层、7% 在表示层、3% 在应用层。由此可以看出,网络故障通常发生在网络七层模型的下三层,即物理层、链路层和网络层。对应于实际网络也就是使用的网卡、网络线缆、交换机等设备故障。     在 L...

CentOS PostgreSQL 12 主从复制(主从切换)

主从复制1.基于文件的日志传送 创建一个高可用性(HA)集群配置可采用连续归档,集群中主服务器工作在连续归档模式下,备服务器工作在连续恢复模式下(1台或多台可随时接管主服务器),备持续从主服务器读取WAL文件。 连续归档不需要对数据库表做任何改动,可有效降低管理开销,对主服务器的性能影响也相对较低。 直接从一个数据库服务器移动WAL记录到另一台服务器被称为...