为什么c的数据段被分成两个部分?

时间:2017-09-23 06:18:03

标签: c

所有全局初始化值都存储在.data段中.i.e。初始化的数据段和未初始化的值存储在bss中,编译器在bss中自动将那些未启动的值初始化为零。然后为什么数据段被分隔为.data和bss。

是否有优势?或任何好处

1 个答案:

答案 0 :(得分:5)

C编程语言(这是一个用英语编写的规范)不了解 #video-background { position: fixed; right: 0; bottom: 0; min-width: 100%; min-height: 75%; width: auto; height: auto; z-index: -100; } .bssdata segment。请阅读n1570C11的最新草稿)。

在某些情况下(例如嵌入式计算),您没有任何数据段。例如,当cross-compileArduino时,生成的代码会上传到该微控制器的闪存中(并且数据位于RAM中,您的程序可能明确地清除)。

(我下面的大部分答案都集中在Linux上,但您可以将其改编为其他操作系统)

关于像Linux这样的类Unix系统上的data segment,请阅读更多ELF的规范。 方便是为了避免在executable文件中花费文件空间来存放全部为零的内容(.bss)。 kernelexecve(2)代码可以设置初始virtual address space,其中包含一些已清除的数据( mapped to some file段)。另见mmap(2)& elf(5)& ld-linux(8)。尝试使用.data命令来了解shell的虚拟地址空间。请参阅proc(5)

因此,可执行文件包含segments(其中一些全部为零且不占用任何磁盘空间),并由linker构建,它也处理relocations - 来自来自object files文件的compiler提供了多个source code。在Linux上,使用objdump(1)readelf(1)(和nm(1) ...)来探索和检查ELF可执行文件和ELF目标文件。

顺便说一句,virtual memory子系统不需要从磁盘中提取已清除的数据段,这可能会使稍微更快。当内核为page时,内核只会在RAM中清除paged

因此存在cat /proc/$$/maps以避免浪费可执行文件中的磁盘空间(以及加速初始化归零数据)。显然,一些可变数据被显式初始化为非零内容(并且需要位于.bss并占用可执行文件中的一些磁盘空间)。常量不可变只读数据进入.data(进入text segment,通常由运行相同程序的多个processes共享)

您可以配置链接器(例如,使用某个链接器script)将所有数据(甚至是已清除的数据)放入某些显式data segment中(但这样做只是浪费磁盘空间)。 ....历史上,Unix have been developed machines只有很少但成本高昂的磁盘空间(因此浪费它在当时是不可想象的,因此需要.rodata;今天你不在乎!)< / p>

阅读Levine的书Linkers and Loaders了解更多信息,Advanced Linux ProgrammingOperating Systems : Three Easy Pieces