程序由不同的段构成(代码段、数据段),程序的静态特征就是指令和数据,动态特征就是执行指令处理数据。
源程序代码到可执行程序的对应关系:
.bss段(Block Started by Symbol segment)
存储未初始化的全局数据,不占用可执行文件的大小。
.data段:存储具有非0初始值的变量
.rodata段:存储const修饰的和其他只读数据
问题:.bss和.data段同样存储的是全局数据,为什么初始化的和不初始化的保存在不同的段中?
.bss段中的变量不用在再程序文件中保存初始值,从而减小可执程序的大小,提高程序加载的效率。(对于.bss段中的变量,在可执行文件中只需要保存其变量名和变量类型,在加载时统一将其初始化为0;而对于存储于.data段中的数据,需要保存其变量名,类型、和值,在加载其需要将变量值拷贝得到变量对应的空间)
编程实验:可以编写简单测试程序,通过objdump -h命令查看各个段的信息,使用nm命令查看可执行文件中的符号和地址,使用objdump -s -j .data ./a.ou查看某个段中的具体信息,并将上述信息对应起来。
栈时在程序被加载到内存之后才生成的,其本质时片连续的存储空间
SP寄存器作为栈顶“指针”实现入栈操作和出栈操作
栈通常作为以下用途
中断发生时,栈用于保存寄存器的值(现场保护)
函数调用时,栈用于保存函数的活动记录(栈帧信息)
并发编程时,每个线程拥有自己独立的栈
堆和栈一样,时程序被加载到内存后才生成的。是一片“空闲的空间”,用于提供动态内存分配。
需要函数的支持(malloc、free)
内存映射段(memory mapping segment)
内核将硬盘中的文件内容直接映射到内存映射段(mmap)
动态链接库在可执行程序加载时映射到内存映射段
程序执行时能够创建匿名映射区存放程序数据
内存映射文件的原理:
将硬盘上的文件数据逻辑映射到内存中(零耗时),通过缺页中断进行文件数据的实际载入(一次数据拷贝),映射后对内存的读写就是对文件的读写(极大的提高了文件的读写效率)。
使用传统的方式通过read函数来读取文件,首先内核程序接到应用程的请求,然后内核程序去读取硬盘中的文件内核空间,然后再讲内核空间中的数据拷贝到应用空间(使用了两次数据拷贝)。
最终各个段在内存中的布局:
这里我们看到栈、堆的起始地址都是随机的,这样做的目的是为了安全,当其实地址随机后,恶意代码修改程序的暗度变大(难以直接通过固定地址获取到程度的返回地址)。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。