链接详解

来源:互联网 发布:周杰伦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.定义和声明

externstatic关键字

    

    使用extern关键字标识这个标识符具有external linkage,如果把两个.c文件链接在一起,例如1.c2.cfoo()是其中的一个函数,如果foo()在1.c2.c中都有声明

,那么这些声明指的是同一个函数,链接之后是同一个GLOBAL符号,指向同一个地址,只在定义声明它的.c文件中,分配一次存储空间,不写extern的函数声明也标识这个函数具有external linkageprevious 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 linkageinternal linkageno linkageprevious linkage,生存期有static duration antomatic duration,初始化有static initializerdynamic initializer两种情况,前者标识initializer中只能使用敞亮表达式,,表达式的值必须在编译时候就确定,后者标识initia中可以使用任意的右值表达式,表达式的值可以再运行时候计算,tentative definition 这种情况下变量以0初始化。

 

4.静态库

比如把四个.c文件编译成一个目标文件再打包成一个静态库,库文件名都是以lib开头,以.a做后缀,标识archivear类似于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.虚拟内存管理

体系结构提供VAPA的转换机制实现虚拟内存管理。

例如用ps查看当前终端下的进程,得知bash进程的id23345,然后用cat /proc/23345/maps查看它的虚拟地址空间。/proc目录中的文件并不是真正的磁盘文件,二是由内核虚拟出来的系统,当前系统中运行的每个进程在/proc下都有一个子目录,目录名就是进程的id,查看文件可以得到该进程的相关信息。

简述虚拟内存管理的作用:

(1)虚拟内存管理可以控制物理内存的访问权限。物理内存本身是 不限制访问的,任何地址都可以读写,而OS要求不同的页面具有不同的访问权限,这时利用CPU模式和MMU的内存管理机制实现的。

(2)让每个进程有独立的地址空间。独立的地址空间是指,不同进程中的同一个VAMMU映射到不同的PA,并且某一个进程中访问任何地址都不可能访问到另外一个进程的数据,这样使得任何一个进程由于执行错误指令或恶意代码导致的非法内存访问都不会意外改写其他进程的数据,不会影响其他进程的运行,从而保证整个系统的稳定。

另外,每个进程都认为自己独占整个虚拟地址空间,这样连接器和加载器的实现会比较容易,不必考虑各进程的地址范围是否冲突。

(3)VAPA的映射会给分配和释放内存带来方便,物理地址不连续的几块内存可以映射成虚拟地址连续的一块内存。

 

原创粉丝点击