所在小组
第六组
组内昵称
蒋权
你的心得体会
一些重要的笔记和词汇
链接是将各种代码和数据片段收集并组合成为一个单一文件的过程。
静态链接:以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的、可以加载和运行的可执行目标文件作为输出。
一共有两个主要任务:
符号解析:目标文件定义和引用的符号,每个符号对应于一个函数、一个全局变量或一个静态变量(注意,没有局部变量)。符号解析的目的是将每个符号引用正好和一个符号定义关联起来。
重定位:在完成符号解析后,就可以重定位这些节,修改所有对这些符号的引用,使得他们指向这个内存位置。
有三种形式,
可重定位目标文件:包含二进制代码和数据,在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
可执行目标文件:包含二进制代码和数据,其形式可以被直接复制到内存并执行。
共享目标文件:特殊的可重定位目标文件,可被动态地加载进内存并链接。
we8105
2020 年11 月 1 日 13:03
42
所在小组
第二组
组内昵称
陶鑫
心得体会
1、 静态链接是由在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。为了构造可执行文件,链接器必须完成两个主要任务: 符号解析和重定位;
2、静态库, 程序在编译阶段,会将引用到的库中的左右内容复制到程序中,然后在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合 ,即很多目标文件经过压缩打包后形成的一个文件。
3、 重定位:两步组成:1) 重定位节和符号定义,链接器将所有想通类型的节合并为同一类型的新的聚合节、2) 重定位节中的符号引用,链接器修改代码节和数据节中对每个符号的引用,是的他们指向正确 的运行时地址。
4、链接器如何解析多重定义的全局符号,
规则1:不允许多个强符号;
规则2:如果有一个强符号和多个弱符号,那么选择强符号;
规则3:如果有多个弱符号,那么这些弱符号中任意选择一个。
5、动态链接, 他是使得不同的程序开发者和部门能够相对独立地开发和测试自己的程序模块,从某种意义上来讲大大促进了程序的开发效率,原先限制程序的规模也随之扩大。但是慢慢地静态链接的诸多缺点也逐步暴露出来,比如浪费内存和磁盘空间、模块更新困难等问题,使得人们不得不寻找一种更好的方式来组织程序的模块。
6、库打桩(library interpositioning),它允许你截获对共享库函数的调用,取而代之执行自己的代码。基本思想:给定一个需要打桩的目标函数,创建一个包装函数,它的原型与目标函数完全一样。使用某种特殊的打桩机制,你就可以欺骗系统调用包装函数而不是目标函数了。包装函数通常会执行它自己的逻辑,然后调用目标函数,再将日标函数的返回值传递给调用者。
所在小组
第六组
组内昵称
钟荣荣
你的心得体会
链接 :理解链接器的作用:理解链接器如何解析引用,什么是库,链接器如何解析引用库可以在面对链接器错误是不会迷惑;了解语言的作用域是如何实现的;帮助理解加载,运行程序,虚拟内存,分页,内存映射等概念;链接器的两个主要任务:符号解析(将目标文件的每个全局符号都绑定到一个唯一的定义);重定位(确定每个符号的最终内存地址,并修改对目标的引用)
异常控制流 :理解异常控制流的作用:帮助理解IO,进程,虚拟内存的实现机制;理解操作系统和应用程序如何交互;异常控制流是实现并发的基本机制,有助于理解并发;可以了解高级语言如何实现异常
名词解释
名词
解释
Linux LD
静态链接器(static linker)的一种. 以一组可重定位目标文件(relocatable object file/.o结尾)和命令行参数作为输入,生成一个完全链接的、可以加载和运行的可执行目标文件(executable object file)。
加载器(loader)
shell 调用操作系统中一个叫做加载器的函数,将可执行文件中的代码和数据复制到内存,然后将控制转移到这个程序的开头
符号链接(symbol resolution)
目标文件定义和引用符号。每个符号对应于一个函数、一个全局变量或一个静态变量。符号解析的目的是将每个符号引用 正好和一个符号定义 关联起来
重定位(relocation)
编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义与一个内存位置关联起来,从而重定位 这些节,然后修改所有对这些符号的引用,使得它们指向对应的内存位置(即为每个符号分配运行时地址).
目标文件
可重定位目标文件。 包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
可执行目标文件。包含二进制代码和数据,其形式可以被直接复制到内存并执行
共享目标文件。一个特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载进内存并链接
When in doubt, invoke the linker with a flag such as the gcc-fno-commonflag
, which triggers an error if it encounters multiply-defined global symbols. Or use the -Werror
option, which turns all warnings into errors.
当你怀疑有 变量的重复声明 时可以尝试开启
重定位
由两步组成
重定位节和符号定义
链接器将所有相同类型的节合并为同一类型的新的聚合节。例如: 来自所有输入模块的.data节被全部合并为一个节,这个节成为输出的可执行 目标文件的.data节。然后,链接器将运行时内存地址赋给新的聚合节,赋给输入模块定义的每个节,以及赋给输入模块定义的每个符号。
重定位节中的符号引用
链接器修改代码节和数据节中对每个符号的引用,使得它们指向正确的运行时地址。
静态库和动态库
为什么-lm或者引入的静态库要放到最后面?
关于库的一般准则时将它们放在命令行的结尾。如果各个库的成员时相互独立的(也就是说没有成员引用另一个成员定义的符号),那么这些库就可以以任何顺序放置在命令行的结尾处。如果库不是相互独立的,那么必须对它们排序,使得对于每个被存档文件的成员外部引用的符号s,在命令行中至少有一个s的定义是在对s的引用之后的。
异常控制流ECF
在任何情况下,当处理器检测到有时间发生时,他就会通过一张叫做一场表的跳转表,进行一个间接过程调用,到一个专门设计用来处理这类事件的操作系统子程序,当异常处理程序完成处理后,根据引起异常的事件的类型,会发生一下三种情况
处理程序将控制返回给当前指令
处理程序将控制返回给下一个指令
中断程序
异常类别
类别
原因
同步异步
返回行为
中断
来自I/o设备的信号
异步
总是返回下一条指令
陷阱
有意的异常
同步
总是返回下一条指令
故障
潜在可恢复的错误
同步
可能返回当前指令
终止
不可恢复的错误
同步
不会返回
异常控制流的概念很宽,从处理器内置的异常(比如除0、段错误)、操作系统的(软件中断)、高级语言提供的(try/catch语句块)
陷阱最重要的作用就是提供了一个像过程一样的接口:syscall n
黄小黄
2020 年11 月 1 日 13:22
45
所在小组: 静默组
组内昵称:黄小黄
心得体会:
– 可重定位目标文件:包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
可执行目标文件:包含二进制代码和数据,其形式可以直接拷贝到存储器并执行。
共享目标文件:一种特殊类型的可重定位目标文件,可以在加载或运行时被动态地加载到存储器并链接。
典型的ELF 可重定位目标文件包含以下几个节:
.text:已编译程序的机器代码
.rodata:制度数据,比如 printf 语句中的格式串和开关语句的跳转表
.data:已初始化的全局 C 变量。
.bss:未初始化的全局 C 变量。
.symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。
.rel.text:一个 .text 节中位置的列表,当链接器把这个目标文件和其它文件结合时,需要修改这些设置。
.rel.data:被模块引用或定义的任何全局变量的重定位信息。
.debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义。
.line:原始 C 源程序中的行号和 .text 节中机器指令之间的映射。
.strtab:一个字符串表,其内容包括 .symtab 和 .debug 节中的符号表,以及节头部中的节名字。
所在小组
第五组
组内昵称
chesongbin
心得体会
Subject: Linking 链接
Date: 2020-11-01
链接可以分为两个任务:
符号解析:将目标文件中的每个全局变量都绑定到一个唯一的定义
符号重定位:确定每个符号的最终内存地址,并修改目标文件中的地址
链接可以发生在:
编译时静态链接
加载时共享库动态链接
运行时共享库动态链接
静态链接
gcc -c addvec.c multvec.c
ar rcs libvector.a addvec.o multvec.o # 创建静态库
gcc -c main2.c
gcc -static -o p2 main2.o ./libvector.a # 创建完全链接的可执行目标文件,使用libc.a 静态库不需要在命令行中指定
加载时共享库动态链接
平时使用gcc时候,没有指定-static 参数,说明使用的是动态库,执行了动态链接
生成的二进制可执行文件是一个部分链接的可执行文件
基本过程:
创建可执行文件时,静态执行部分链接
在程序加载时候,调用动态链接器,完成链接
gcc -shared -fpic -o libvector.so addvec.c multvec.c
gcc -o p2 main2.c ./libvector.so # 使用libc.so 动态共享库不需要在命令行中指定
运行时共享库动态链接
Linux系统为动态链接器提供了一些接口
#include<dlfcn.h>
// 以调用我们自己构造的共享库libvector.so为例子
void * handler
void (* addvec)(int *, int *, int *, int)
// 打开共享库文件
handler = dlopen("./libvector.so", RTLD_LAZY)
// 符号解析,获得函数的地址
addvec = dlsym(handler, "addvec")
// 执行函数调用
addvec(x, y, z, 2)
Java本地接口(JNI):允许Java程序调用本地的C和C++函数,基本思想就是将相应的C、C++函数(eg:foo)编译到一个共享库(foo.so )。然后当Java程序在调用foo函数的时候,Java解释器就会利用到运行时共享库动态链接。
其他
这一章阅读比较吃力,有比较多的术语和概念,需要将其转化为自己的“存储模型”
符号:全局变量、全局函数、static变量、static函数,也就是在生成.o文件时候,无法确定具体内存位置的,需要一个符号来表示
链接:将多个.o文件合体,这里需要将.o文件中的符号,改为具体的内存地址
sadame
2020 年11 月 1 日 13:48
53
所在小组
第一组
组内昵称
SADAME
你的心得体会
预处理器 :将 C 语言代码(da.c)转化成 da.i
文件(gcc –E
),对应于预处理命令 cpp
编译器 :C 语言代码(da.c, wang.c)经过编译器的处理(gcc -0g -S
)成为汇编代码(da.s, wang.s)
汇编器 :汇编代码(da.s, wang.s)经过汇编器的处理(gcc
或 as
)成为对象程序(da.o, wang.o)
链接器 :对象程序(da.o, wang.o)以及所需静态库(lib.a)经过链接器的处理(gcc
或 ld
)最终成为计算机可执行的程序
加载器 :将可执行程序加载到内存并进行执行,loader
和 ld-linux.so
链接过程
链接器主要是将有关的目标文件彼此相连接生成可加载、可执行的目标文件。链接器的核心工作就是符号表解析和重定位。
RockLD
2020 年11 月 1 日 13:49
54
所在小组
第二组
组内昵称
文弱书生
心得体会
链接:
是将各种程序和库组合成一个目标文件的过程,目标文件可以被加载到内存并执行。
链接执行时机:
编译时,加载时或运行时。
链接器:
负责链接的程序叫做链接器
静态链接:
用一组可重定位的目标文件和命令行输入参数作为输入,生成一个完全链接、可加载和运行的可执行目标文件
优点:代码加载速度快,执行速度快,在程序执行的时候不需要考虑运行环境
缺点:占用内存和空间,更新程序的时候比较麻烦,需要定期的维护和更新
动态链接:
运行时再进行链接
优点:不会浪费内存和空间,使各个模块更加独立,降低耦合。
缺点:载入时如果发现dll文件不存在会报错,速度比静态链接慢,有版本依赖
所在小组
五组
组内昵称
张学广
心得体会
第六章 存储器层次结构
这一章介绍了计算机中的各种存储器,以及各自的优缺点和组合使用,之后介绍了如何编写缓存友好的代码,在这部分有很好的收货。
计算机中的存储是分层的,从最高速的cpu缓存,到 L1、L2、L3这些高速缓存,之后是主存以及最后的磁盘存储,规律是存储从小到大,速度从快到慢,造价从高到底,这样的组合利用了各种存储器的优劣势可以兼顾速度大小与造价。
之后是些高速缓存友好的代码,有以下几点
让常见的情况运行的更快
尽量增加缓存命中
到实际中需要注意的两点:
对局部变量反复利用
步长为1的引用模式
命中率主要看高速缓存的原理,一行一行的读取数据是要比一列一列读取快的多的。
其次也要注意程序的切换,切换程序会导致缓存的刷新,导致命中率降低