全部博文(842)
分类: 系统运维
2012-05-14 16:58:18
历史上,一个C程序可以由以下部分组成:
1、代码段(text segment),CPU执行的机器指令。通过,代码段是可共享的,以便经常执行的程序只需在内存里单个拷贝,比如文本编辑器,C编译器,外壳,等等。还有代码段通常是只读的,为了阻止一个程序偶然修改了它的指令。
2、初始化的数据段(Initialized data segment),通常简称为数据段,包括在程序里特别初始化的变量。例如,C出现在任何函数外的声明int maxcount = 99;会导致这个变量以其初始值存储在初始数据段里。
3、未初始化的数据段(Uninitialized data segment),经常被称为“bss”段,在代表“block started by
symbol”的古老的汇编操作之后命令。在这个段的数据被内核在程序开始执行前初始化为数字0或null指针。出现在任何函数外的C声明long
sum[1000];导致这个变量被存储在未初始化的数据段里。
4、栈,存储自动变量和每次一个函数调用时保存信息的地方。每次一个函数被调用时,它要返回到的地址和关于调用者环境的特定信息,比如一些机器寄存器,被
保存在栈里。新调用的函数然后在栈上为自动和临时变量开辟空间。这是在C里的递归函数如何工作的。每次一个递归函数调用它自身时,一个新的栈框架被使用,
所以一堆变量不会和这个函数的其它实例的变量冲突。
5、堆,动态内存分配通常发生的地方。历史上,堆一直放在未初始化数据和栈之间。
这些段的典型布局是:最低地址是代码段,其上是初始化数据,再上是未初始化数据,最高地址是命令行参数和环境变量,其下是栈,在栈和bss段之间是堆。这 是一个程序看起来的逻辑图,没有要求说一个给定的实现必须以这种风格排列它的内存。尽管如此,这给了我们一个可以描述的典型的排列。在Intel x86处理器上的Linux上,代码段从地址0x8048000开始中,而栈的底部从0xC0000000开始。(在这个特定的架构上,栈从高位地址向地 位地址增长。)在堆的顶部和栈的顶部之间的空间是巨大的。
一些存在于一个a.out里的更多的段类型,包括符号表,调试信息,为动态共享库的链接表,等等。这些额外的段没有被载入作为被进程执行的程序映像的一部分。
注意未初始化数据段的内容没有存储在磁盘上的程序文件里。这是因为内核在程序开始运行时设置它为0。需要保存在程序文件部份只有代码段和初始化数据。
size命令报告代码、数据和bss段的(字节)尺寸。例如:
$ size /usr/bin/cc /bin/sh
text data bss dec hex filename
296400 2000 5736 304136 4a408 /usr/bin/cc
93358 900 10188 104446 197fe /bin/sh
第三和第四列是前三个尺寸的总数。分别以十进制和十六进制表示。