Linux内核data段和bss段的区别

嵌入式技术

1335人已加入

描述

从进程的角度,Linux内核是采用虚拟地址空间的,如下两张图所示,分别为32位、64位系统下进程地址空间的大概布局。

Linux

本文主要分析的是进程的用户空间地址中的数据分配,也就是上图中低地址中用户空间部分,下图为用户空间中内存通用分布图如下:

Linux

对于每个区域的作用可以从上图中看出来,就不一一列举,但是有几个常见疑问值得好好分析一下:

bss段、data段分别存放什么样的数据?两者分开的好处是什么?

先整体看:bss段与data段首先说明:data段和bss段都属于数据段,在编译时分配。

data段:存放赋了初值的【全局变量、静态变量】,属于静态内存分配。

bss段:存放未赋初值的【全局变量和静态变量】,属于静态内存分配

通过下面的测试程序,先直观感受data段和bss段的区别:

Linux

左侧定义了数组a,数组容量为4M,并没有进行初始化,右侧定义同样的数组,但是进行了初始化,结果分析:

1、通过size命令查看,可以看到左侧未初始化数组变量的程序bss段大约就是4M大小,右侧初始化数组变量的程序data段大约是4M大小,从此也可以看出来未初始的全局变量存放在bss段,初始化的全局变量存放在data段中。

2、通过ls命令查看,分别可以看到两者的可执行文件的大小差距很大(分别为8328字节、4202648字节),未初始化的全局数组变量并没有占据实际的磁盘空间,初始化的全局数组变量占据了数组对应的磁盘空间。

下面进一步分析:

先看bss段:bss段存放已经定义但没赋初值的【全局变量和静态变量】,bss的英文全称:Block Started Symbol,意为“以符号开始的块”,由此也可以看出来bss段的数据/变量只有名称和大小,只是简单维护地址空间中开始和结束的地址。下面进行详细测试:

测试1:定义一个全局未初始化int类型数组,查看可执行文件大小,各数据段的大小

Linux

测试1结果:由上测试结果可以看到,定义了一个未初始化的容量为4M的数组,可执行文件大小才为8328字节,很明显这4M大小的数组并没有在编译链接后的可执行文件中分配实际的磁盘空间。再通过size命令查看进程地址空间中各数据段的大小,可以看到bss段占据4194336字节,约4M大小空间,也说明全局未初始化变量分配在bss段,bss段不占用实际的磁盘空间,下面进行测试2.

测试2:与测试1定义相同的数组,只不过初始化了数组为0。

Linux

测试2结果:可以发现与测试1结果相同,也就是说全局未初始化、全局初始化为0的变量都分配在bss段上。

测试3:定义一个静态未初始化数组,数组容量大小4M,查看可执行文件大小,各数据段的大小

Linux

测试3结果:与测试1对比发现,静态未初始化变量也分配在bss段上,同理测试2,如果静态变量初始化为0,也分配在bss段上,其不占据相应的磁盘容量。由测试1~测试3验证了:未初始化的全局变量、未初始化的静态变量、初始化为0的全局变量、初始化为0的静态变量存放在bss段,且不占用相应的磁盘空间大小。

所以在Linux环境的C下,初始值为零和没有赋初始值的变量放在BSS段,因为这些值都是零,所以就不需要放到文件里面,只在段表中记录大小,在符号表中记录符号,等程序加载的时候再赋值0就好了,从而节约了磁盘空间。

再来看data段测试4:定义一个全局初始化的数组a,容量为4M,查看可执行文件大小,各数据段的大小

Linux

测试4结果:与测试1、测试2对比,可以看到全局初始化非0的变量分配在data段,占据对应的磁盘空间。测试5:定义一个静态初始化非0的数组a,容量大小为4M,查看可执行文件大小,各数据段的大小

Linux

测试5结果:与测试4对比,与测试4结果相同,可以看到静态初始化非0的变量存放在data段,占据对应的磁盘空间。

由测试4~测试5验证了:全局初始化且初始化非0、静态初始化且初始化非0的变量存放在data段,占据对应的磁盘空间。

总结:

1、bss段(Block Started Symbol,意为“以符号开始的块”),只是简单维护地址空间中开始和结束的地址,在实际运行对内存区域有效地清零即可。bss段存放全局未初始化/初始化为0、静态未初始化/初始化为0的变量,在磁盘上并不占用相应的磁盘空间。

2、data段,存放的是全局初始化(初始化非0)、静态初始化(初始化非0)的变量,在磁盘中占用相应的磁盘空间,这些变量在程序开始之前具有具体值,是可执行文件的一部分,当程序执行运行时,将可执行文件加载到内存中,读取相应的变量值。

3、bss段维护的是0值的数据变量,不需要占据相应的磁盘空间,data段存放的是具体有效非0值,需要占据相应的磁盘空间,以供程序运行时加载读取相应的值。两者分开维护管理,有效地降低可执行文件占据磁盘的容量,否则初始化化数据项越多,可执行文件越大,运行时加载到内存所需要的时间消耗越大。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分