链接详解
来源:互联网 发布:周杰伦secret知乎 编辑:程序博客网 时间:2024/06/10 00:13
(以下icc命令编译基于intel c编译器)
1.多目标文件的链接
icc -c 1.c -o 1
icc -c 2.c -o 2
icc 1 2 -o test
一般情况下,.bss段,.text段,.dada段合并,可用readelf -a main命令查看,链接脚本会插入一些符号到最终生成的文件中
2.定义和声明
extern和static关键字
使用extern关键字标识这个标识符具有external linkage,如果把两个.c文件链接在一起,例如1.c,2.c,foo()是其中的一个函数,如果foo()在1.c和2.c中都有声明
,那么这些声明指的是同一个函数,链接之后是同一个GLOBAL符号,指向同一个地址,只在定义声明它的.c文件中,分配一次存储空间,不写extern的函数声明也标识这个函数具有external linkage(previous linkage,这次声明的标识符具有什么样的linkage取决于前一次的声明,第一次声明使用external)
使用static修饰一个函数声明,则标识该标识符具有internal linkage,链接时找不到它的定义,无法确定地址也就无法做符号解析。
3.storage class关键字对变量声明的作用
storage class
file scope declaration
block scope declaration
none
external linkage
static duration
static initializer
tentative definition
no linkage
automatic duration
dynamic initializer
definition
extern
previous linkage
static duration
no initializer
not a definition
previous linkage
static deration
no initializer
not a definition
static
internal linkage
static duration
static initializer
tentative definition
no linkage
static duration
static initializer
definition
四行分别描述变量的链接属性,生存期,以及这种变量如何初始化,是否算变量定义。链接属性有external linkage,internal linkage,no linkage和previous linkage,生存期有static duration 和antomatic duration,初始化有static initializer和dynamic initializer两种情况,前者标识initializer中只能使用敞亮表达式,,表达式的值必须在编译时候就确定,后者标识initia中可以使用任意的右值表达式,表达式的值可以再运行时候计算,tentative definition 这种情况下变量以0初始化。
4.静态库
比如把四个.c文件编译成一个目标文件再打包成一个静态库,库文件名都是以lib开头,以.a做后缀,标识archive,ar类似于tar,但是把目标文件打包成静态库只能用ar命令而不能用tar命令,选项r标识将后面的文件列表添加到文件包,如果文件包不存在就创建,如果文件包中已有同名文件就替换成新的。s是专用于生成静态库的,标识为静态库创建索引,这个索引被连接器使用
icc -c 1.c 2.c 3.c 4.c
ar rs lib1.a 1.o 2.o 3.o 4.o
5.共享库
组成共享库的目标文件编译时候要加-fPIC选项,PIC表示生成位置无关代码(position independent code)
icc -c -fPIC 1.c 2.c 3.c 4.c
可使用objdump -dS 1.o查看并与静态库中的反汇编查看,标出指令中有几处需要在重定位时修改,可做反汇编分析
icc -g main.c 1.o 2.o 3.o 4.o -Ilib1 -o test
objdump -dS test
编译成共享库再做反汇编分析
icc -shared -o lib2.so 1.o 2.o 3.o 4.o
objdump -dS lib2.so
6.虚拟内存管理
体系结构提供VA到PA的转换机制实现虚拟内存管理。
例如用ps查看当前终端下的进程,得知bash进程的id是23345,然后用cat /proc/23345/maps查看它的虚拟地址空间。/proc目录中的文件并不是真正的磁盘文件,二是由内核虚拟出来的系统,当前系统中运行的每个进程在/proc下都有一个子目录,目录名就是进程的id,查看文件可以得到该进程的相关信息。
简述虚拟内存管理的作用:
(1)虚拟内存管理可以控制物理内存的访问权限。物理内存本身是 不限制访问的,任何地址都可以读写,而OS要求不同的页面具有不同的访问权限,这时利用CPU模式和MMU的内存管理机制实现的。
(2)让每个进程有独立的地址空间。独立的地址空间是指,不同进程中的同一个VA被MMU映射到不同的PA,并且某一个进程中访问任何地址都不可能访问到另外一个进程的数据,这样使得任何一个进程由于执行错误指令或恶意代码导致的非法内存访问都不会意外改写其他进程的数据,不会影响其他进程的运行,从而保证整个系统的稳定。
另外,每个进程都认为自己独占整个虚拟地址空间,这样连接器和加载器的实现会比较容易,不必考虑各进程的地址范围是否冲突。
(3)VA到PA的映射会给分配和释放内存带来方便,物理地址不连续的几块内存可以映射成虚拟地址连续的一块内存。
- 链接详解
- 链接详解
- 链接详解
- 软链接&硬链接详解
- 数据库链接详解
- 编译链接详解
- 编译器链接详解zz
- 共享库链接详解
- 共享库链接详解
- iptables命令详解(链接)
- Linux链接脚本详解
- Linux 链接脚本详解
- c的链接详解
- c++ 详解链接过程
- Linux 链接脚本详解
- 动态链接库详解
- springmvc 详解链接
- Linux 链接脚本详解
- 如何不重新编译替换默认壁纸
- sh_page_fault函数的处理http://bbs.chinaunix.net/thread-2079251-1-1.html
- linux 下文件重命名/移动/复制命令 linux新建目录命令
- hadoop的datanode无法启动
- iphone之http post数据
- 链接详解
- bsearch函数
- 夜子:我在澳大利亚做Andriod, 阳光沙滩美女
- 说ibm aix jfs2
- 分析总结Spring管理Hibernate中Dao层访问数据库常用方式(附SSH的jar包)
- Java集合与数组
- C语言常用函数
- linux2.6.29 CFS调度详细分析
- android联系人过滤