菜鸟笔记
提升您的技术认知

bss段(未初始化数据)是否占用空间的问题

关于bss段,请教个问题,它是不是并不占用可执行程序的硬盘空间?
hello.c文件内容如下

#include <stdio.h>
int main()
{
        return 0;
}

编译后
[root@localhost ctest]# ll hello

-rwxr-xr-x 1 root root [b][color=Red]4613[/color][/b] 06-10 16:06 hello
[root@localhost ctest]# size hello
text data bss dec hex filename
803 248 [color=Red] 8 [/color] 1059 423 hello

可见这时hello的大小为 4613字节,用size去看hello,其bss段为8字节

然后修改代码,填上一行 int bss[1000]; (该数组在运行时应占4000字节 )

#include <stdio.h>

int bss[1000];//这行是增加的,它应位于bss段

int main()
{
        return 0;
}

[root@localhost ctest]# ll hello
-rwxr-xr-x 1 root root 4633 06-10 16:07 hello
[root@localhost ctest]# size hello
text data bss dec hex filename
803 248 4032 5083 13db hello

发现hello的大小变为4633,比4613增加了20字节,而不是增加了4000字节,这应该就说明了bss段的数据并不占用可执行文件的空间吧?
但奇怪的是 第二次对hello执行size命令时, 其bss段大小变为4032,而第一次时是8

第一次
[root@localhost ctest]# size hello
text data bss dec hex filename
803 248 [color=Red] 8 [/color] 1059 423 hello

第二次

[root@localhost ctest]# size hello
text data bss dec hex filename
803 248 [color=Red]4032 [/color] 5083 13db hello

实际上hello仅增加了20字节 ,是不是size命令得到的bss段的大小是指程序运行后,映射到虚拟内存空间后,bss段实际所占空间的大小?而不是说在硬盘上的大小? 这样理解对么?

readelf -t 看.bss section大小变化。

另外如果对bss[]赋值初始化数据
int bss[1000]={1,2,3,4,5};
这个变量会被放在.data section里面。

不是不映射,是先映射再挖空.bss,看.so加载比看elf执行文件加载代码紧凑些。
文件: /usr/src/linux/fs/binfmt_elf.c (kernel v2.6.33)

static int load_elf_library(struct file *file)
{
......
         /* Now use mmap to map the library into memory. */
         down_write(¤t->mm->mmap_sem);
         error = do_mmap(file,
                         ELF_PAGESTART(eppnt->p_vaddr),
                         (eppnt->p_filesz +
                          ELF_PAGEOFFSET(eppnt->p_vaddr)),
                         PROT_READ | PROT_WRITE | PROT_EXEC,
                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
                         (eppnt->p_offset -
                          ELF_PAGEOFFSET(eppnt->p_vaddr)));
         up_write(¤t->mm->mmap_sem);
         if (error != ELF_PAGESTART(eppnt->p_vaddr))
                 goto out_free_ph;

         elf_bss = eppnt->p_vaddr + eppnt->p_filesz;
         if (padzero(elf_bss)) {
                 error = -EFAULT;
                 goto out_free_ph;
         }

         len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
                             ELF_MIN_ALIGN - 1);
         bss = eppnt->p_memsz + eppnt->p_vaddr;
         if (bss > len) {
                 down_write(¤t->mm->mmap_sem);
                 do_brk(len, bss - len);
                 up_write(¤t->mm->mmap_sem);
         }
         error = 0;
...
}