C++笔记_01深入编译链接和运行
用任何语言写代码,无非产生两种东西,,,指令+数据
CPU的位数,指的是:一次性,能加以运算的最长的正数的宽度。
ALU 算数逻辑单元的宽度
虚拟内存的大小与CPU的位数有关系 SIZE== 2^32 == 4G
0x0000 0000 ------ 0x FFFF FFFF
0x00000000 -> 0x C000 0000 用户空间(低3G)
0x C0000 0000 -> 0x FFFF FFFF 内核空间(高1G)
0x0000 0000 -> 0x 0804 8000 128M的禁止访问区域
.text 代码段 存放指令
.data 数据段 存放数据 (已经初始化的数据)
.bss 数据段 存放数据 (未初始化或初始化为0的变量)占用虚拟地址空间
heap 堆
共享库 如果当前程序用到库中的函数
.stack 栈
命令行参数
环境变量
(以上是用户空间)
-----------(分界线)
(以下是内核空间)
ZONE_DMA 低16M 直接内存访问(加速内存和磁盘之间访问数据用的)
ZONE_NORMAL 中间892M 内核常用
ZONE_HIGHMEN 高128M 高端内存(主要在内核映射高于1G的物理内存)
内存布局以及相互之间的关系
.data?? 数据段,存放程序中已经初始化的变量
.bss?? 占用的是虚拟地址空间 层程序中未初始化偶初始化为0的变量
heap 存放进程中运行中被动态分配的内存段
stack 存放程序临时创建的局部变量
内核共享,,,用户空间独立
编译的过程
预编译 : 去掉注释以及#开头的预处理文件
编译: 代码的优化,汇总所有的符号
汇编: 根据特定平台转化成该平台特定的机器码,CPU使用汇编指令将代码生成二进制可重定位目标文件
生成二进制可重定位目标文件: .obj .o 内部存在符号表
数据产生符号,函数只产生函数名符号
重定位? 二进制目标语言重定位之后才可运行1
指把 程序的逻辑地址空间变换成内存中的实际物理地址空间的过程,也就是再装载时对目标城中指令和数据的修改过程。分为两种 动态、静态重定位。
虚拟内存:: 是计算机系统内存管理的一种技术。它使应用程序认为它拥有连续的可用内存(一个连续完整的地址空间),实际上它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。如, windows的虚拟内存,linux的交换空间等
http://baike.baidu.com/link?url=1dFbPEuytWnfia9BC78ysbOXUEshpbV_zehkQ4FTu4j1ssM2uQLHgcLKORhCSPbsgUh-LkJPAcuoWtjuAvo188nMRFltLrdosigp93hfSh-zZMETAfqiZRMUNhI7Zzjw
链接
1.合并所有.obj文件的段,并调整段的段偏移和段长度,合并符号表进行符号解析 [仅分配内存地址]
2.链接的核心。。 符号重定位
链接时 对所有.obj文件的glocal(全局)符号进行处理,local(局部)的符号不做任何处理
符号解析?? :: 所有obj符号表中对符号引用的地方都要找到该符号定义的地方
所有相同属性的段进行合并组织在一个界面上
可执行文件
???
C语言中强符合和若符号
初始化了的是强符号,包括初始化为0
没初始化的是若符号
若同时出现了强符号和若符号,则选择强符号
多个若符号,则选择内存占用量最多的,但是随着编译器的不同它也不同
main.o结构
程序运行的过程
1.创建虚拟地址空间到物理内存的映射(创建内核地址映射结构体),创建目录和页表
2.加载代码段和数据段
3.把可执行文件的入口地址写到CPU的PC寄存器里面
mmap 函数 用来映射磁盘《深入理解计算机第九章》
可执行文件结构:
比.obj(可重定位二进制目标文件)多一个在ELF Header 下面多一个programheaders(程序启动入口)
???为什么每个程序入口地址都是0x80482e0
符号地址都一样?
0x80482e0地址是.text的地址(代码段的开始)也是_start()的地址。在_start()中又会调用_libc_start_main(),=》程序初始化
*UDN* ???对符号的引用
.test 是对符号的定义,在链接的第一阶段,所有的.obj文件的段都会进行合并调整段的大小以及起始地址的偏移量,然后合并符号表进行符号解析,让所有符号引用的地方都要定位到符号的定义处,具有唯一性,定位好之后分配内存的虚拟地址;第二步进行符号的重定位,