C 编程语言(它是用英语编写的规范)不知道.bss
or .data
or 数据段 https://en.wikipedia.org/wiki/Data_segments。通过阅读来检查n1570 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf(最新草案C11 https://en.wikipedia.org/wiki/C11_(C_standard_revision)).
在某些情况下(例如嵌入式计算),您没有任何数据段。例如当你交叉编译 https://en.wikipedia.org/wiki/Cross_compiler for an Arduino https://www.arduino.cc/,生成的代码被上传到该微控制器的闪存(数据位于 RAM 中,您的程序可能会明确地 clear).
(most of my answer below is focused on Linux, but you could adapt it to other OSes)
关于数据段 https://en.wikipedia.org/wiki/Data_segment在 Linux 等类 Unix 系统上,请阅读更多规范ELF https://en.wikipedia.org/wiki/Executable_and_Linkable_Format. It is 方便的以避免花费文件空间可执行文件 https://en.wikipedia.org/wiki/Executable为某事归档(.bss https://en.wikipedia.org/wiki/.bss)全为零。这kernel https://en.wikipedia.org/wiki/Kernel_(operating_system)代码为执行(2) http://man7.org/linux/man-pages/man2/execve.2.html能够设置一个初始虚拟地址空间 https://en.wikipedia.org/wiki/Virtual_address_space一些清除的数据(即not 映射到某个文件 https://en.wikipedia.org/wiki/Memory-mapped_file部分)。也可以看看mmap(2) http://man7.org/linux/man-pages/man2/mmap.2.html & elf(5) http://man7.org/linux/man-pages/man5/elf.5.html & ld-linux(8) http://man7.org/linux/man-pages/man8/ld-linux.8.html。试一些cat /proc/$$/maps
命令来了解 shell 的虚拟地址空间。看proc(5) http://man7.org/linux/man-pages/man5/proc.5.html.
所以可执行文件包含segments https://en.wikipedia.org/wiki/Memory_segmentation(其中一些全为零,不占用任何磁盘空间),并且由linker https://en.wikipedia.org/wiki/Linker_(computing)- 还可以处理搬迁 https://en.wikipedia.org/wiki/Relocation_(computing)- 来自几个目标文件 https://en.wikipedia.org/wiki/Object_file由提供compiler https://en.wikipedia.org/wiki/Compiler from 源代码 https://en.wikipedia.org/wiki/Source_code文件。在 Linux 上,使用对象转储(1) http://man7.org/linux/man-pages/man1/objdump.1.html and 雷德尔夫(1) http://man7.org/linux/man-pages/man1/readelf.1.html (and nm(1) http://man7.org/linux/man-pages/man1/nm.1.html...)来探索和检查 ELF 可执行文件和 ELF 目标文件。
顺便说一句,清除的数据段不需要由虚拟内存 https://en.wikipedia.org/wiki/Virtual_memory子系统,这可能会使事情slightly快点。内核只会清除一个page https://en.wikipedia.org/wiki/Page_(computer_memory)当它在 RAM 中时paged https://en.wikipedia.org/wiki/Paging in.
So the .bss
存在是为了避免浪费可执行文件中的磁盘空间(并加速归零数据的初始化)。显然,一些可变数据被显式初始化为非零内容(并且需要位于.data
并在可执行文件中占用一些磁盘空间)。恒定的不可变只读数据进入.rodata
(进入文本段 https://en.wikipedia.org/wiki/Code_segment#rodata,一般由几个人共享流程 https://en.wikipedia.org/wiki/Process_(computing)运行相同的程序)
您可以配置您的链接器(例如使用某些链接器script https://sourceware.org/binutils/docs/ld/Scripts.html)将所有数据(甚至是清除的数据)放入一些显式的数据段 https://en.wikipedia.org/wiki/Data_segment(但这样做只是浪费磁盘空间)……从历史上看,Unix已经开发出来了 https://en.wikipedia.org/wiki/History_of_Unix on machines https://en.wikipedia.org/wiki/PDP-11#Unibus_models磁盘空间很少但成本高昂(因此浪费它在当时是不可想象的,因此需要.bss
;今天你不在乎了!)
读莱文的书链接器和加载器 http://iecc.com/linkers/了解更多,以及高级Linux编程 http://advancedlinuxprogramming.com/ and 操作系统:三个简单的部分 http://pages.cs.wisc.edu/~remzi/OSTEP/.