2017-2018-1 20155333 《信息安全系统设计基础》第十四周学习总结
教材学习内容总结
链接
将各种代码和数据部分收集起来并组合成为一个单一文件的过程。(这个文件可被加载或拷贝到存储器并执行)
链接可以执行于编译,加载或运行时。
程序是怎样运行的
一个写好的C程序要先经过语言预处理器,编译器,汇编器和链接器生成最后的可执行文件,然后加载器将可执行文件加载到内存中才能运行。
- 以一个c程序main.c和GNU编译系统(静态链接)为例来说明生成可执行文件的过程:
- 首先经过c预处理器(cpp)将main.c翻译成一个 ASCII码的中间文件main.i;
- 接下来驱动程序运行C编译器(cc1)将main.i翻译成一个ASCII汇编语言文件main.s;
- 随后驱动程序运行汇编器,将main.s(as)翻译成一个可重定位目标文件main.o;
- 最后运行链接器ld将main.o和其他的一些的可重定位目标文件链接在一起创建一个可执行目标文件。
-
程序运行之前每个阶段的所做的具体工作:
1、 预处理阶段:预处理器cpp根据以字符#开头的命令,修改原始的C程序。比如常见的命令
#include<stdio.h>
就是告诉编译器读取系统头文件stdio.h的内容,这个头文件里包含了一些可能用到的函数的声明,预处理器将它直接插入到程序文本中,就得到了另一个c程序——main.i
2、 编译阶段:编译器(cc1)将文本文件main.i翻译成文本文件翻译成文本文件mian.s,它包含了一个汇编语言程序,汇编语言程序中的每条语句都描述了一句机器指令。汇编语言是非常有用的,因为它为不同的高级语言的不同编译器提供了通用的输出语言。
3、 汇编阶段:接下来汇编器(as)将main.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标文件的格式,即main.o。它是一个二进制文件。
4、 链接阶段:假设main.o调用了printf函数,而printf函数是标准C库中的一个函数,位于一个名为printf.o的单独预编译好了的目标文件中,问这个文件必须以某种方式合并到main.o中去,链接器(ld)就负责处理这种合并,结果得到main文件,它是一个可执行目标文件,可以被加载到内存中,由系统执行。
5、 加载:在命令行上键入/main
外壳程序会调用操作系统中一个叫做加载器的函数,它拷贝可执行文件中的代码和数据到存储器中,并将控制权转移到程序的开头。
静态链接
- 两个主要任务:
-
符号解析:将目标文件中的每个全局符号都绑定到一个唯一的定义
-
重定位:确定每个符号的最终存储器地址,并修改对那些目标的引用
符号表:
typedef struct{ int name; //字符串表中的字节偏移,指向符号的以NULL结尾的名字
int value; //符号的地址,对于可重定位的模块是距定义目标的节起始位置的偏移。
int size; //目标大小(单位:字节)
char type:4, //数据或函数
binding:4; //本地LOCAL/全局GLOBAL
char reserved;
char section; //到节头部表的索引
}Elf_Symbol;
每个符号都和目标的某个节相关联,由section字段表示。
section字段三个特殊的伪节
- ABS:不该被重定位的符号。
- UNDEF:未定义的符号,在本目标模块中引用,但在其他地方定义。
- COMMON:未被分配位置的未初始化数据目标。
Ndx=1表示.test节,Ndx=3表示.data节。
目标文件三种形式:
-
可重定位目标文件
-
可执行目标文件
-
共享目标文件
共享目标文件(共享库)是在运行时由动态链接器链接和加载,或者隐含地在调用程序被加载和开始执行时,或者根据需要在程序调用dlopen库的函数。
加载器将可执行文件的内容映射到存储器,然后调用动态链接器,通过加载共享库和重定位程序中的引用来完成链接任务。
Fpic
被编译为位置无关代码的共享库可以加载到任何地方,也可以在运行时被多个进程共享
编译库代码,使得不需要链接器修改库代码就可以在任何地址加载和执行这些代码。
用户对GCC使用-fPIC选项指示GNU生成PIC代码
处理目标文件的工具
-
AR:创建静态库,插入、删除、列出和提取成员。
-
STRINGS:列出一个目标文件中所有可打印的字符串。
-
STRIP:从目标文件中删除符号的信息。
-
NM:列出一个目标文件的符号表中定义的符号。
-
SIZE:目标文件中节的名字和大小。
-
READELF:显示一个目标文件的完整结构,包括ELF头中的编码的所有信息。包含SIZE和NM的功能。
-
OBJDUMP:所有二进制工具之母,能够显示一个目标文件中所有的信息。它最大的作用是反汇编.text节中的二进制指令。
-
LDD:列出一个可执行文件在运行时所需要的共享库。
什么是可重定位文件
典型的ELF可重定位目标文件格式
ELF头以一个16字节的序列开始,其中包含了生成该文件的系统的字大小和字节顺序,ELF头剩下部分包括ELF头大小、目标文件类型、机器类型、节头部表偏移(section header table)。
ELF文件中其他节的位置信息都在节头部表中可以找到
ELF头和节头部表之间的都是各种各样的节
- .text: 已编译程序的机器代码
- .rodata: 只读数据
- .data: 已初始化的全局变量(ELF文件中不含局部变量,他们保存在栈中)
- .bss:(Block Storage Start) 未初始化的全局变量,区分已初始化和未初始化全局变量的目的是为了节省磁盘空间,目标文件中这个节不占用空间,只是一个占位符
- .symtab: 符号表,存放程序中定义和引用的函数和全局变量的信息(没有局部变量的条目)
- .rel.text: 一个.text节中位置的列表。当链接器将此文件与其他目标文件链接时需要修改这些位置,一般任何调用外部函数或引用全局变量的指令都要修改
- .rel.data: 引用或定义的任何全局变量的重定位信息,任何已初始化的全局变量,如果它的初值是一个全局变量地址或外部函数地址,就需要修改
- .debug: 调试符号表,包含了程序中定义的局部变量和类型定义,定义或引用的全局变量,以及源文件。编译时使用-g选项才能生成这个section
- .line: 源文件中的行号和.text节中机器指令间的映射,编译时使用-g生成这个表
- .strtab: 字符串表,包含.symtab和.debug节中的符号表,以及节头部中的节名字
教材学习中的问题和解决过程
- 问题1:理解链接的好处?
- 问题1解决方案:
- 有助于构造大型程序
- 有助于避免一些危险编程错误
- 有助于理解其他重要的系统概念
- 能够利用共享库
-
问题2:静态库和共享库
-
问题2解决方案:静态库有一些明显的缺点:
-
- 静态库在更新时,使用该库的程序需要与更新的库进行重新链接。
-
- 由于使用静态库的程序在链接时都会拷贝静态库里被应用程序引用的目标模块,像printf和scanf这样的函数的代码在运行时都会被复制到每个运行进程的文本段中,这造成了冗余,浪费了稀缺的存储器资源。
为了解决静态库的这些缺陷,共享库(share library)出现了。
- 问题3:编译时:"-Og",学习解析多重定义的全局符号时:"-Wall"什么作用
- 问题3解决方案:表示使用全局优化;会打开一些很有用的警告选项,建议编译时加此选项。
- ...
代码调试中的问题和解决过程
- 问题1:XXXXXX
- 问题1解决方案:XXXXXX
- 问题2:XXXXXX
- 问题2解决方案:XXXXXX
- ...
代码托管
上周考试错题总结
-
Y86-64中()指令没有访存操作.
-
A .rrmovl
-
B .irmovq
-
C .rmmovq
-
D .pushq
-
E .jXX
-
F .ret
-
正确答案: A B E
-
4.3节
-
有关磁盘操作,说法正确的是()
-
A .对磁盘扇区的访问时间包括三个部分中,传送时间最小。
-
B .磁盘以字节为单位读写数据
-
C .磁盘以扇区为单位读写数据
-
D .读写头总处于同一柱面
-
正确答案: A C D
-
教材p409
-
有关RAM的说法,正确的是()
-
A .SRAM和DRAM掉电后均无法保存里面的内容。
-
B .DRAM将一个bit存在一个双稳态的存储单元中
-
C .一般来说,SRAM比DRAM快
-
D .SRAM常用来作高速缓存
-
E .DRAM将每一个bit存储为对一个电容充电
-
F .SRAM需要不断刷新
-
G .DRAM被组织为二维数组而不是线性数组
-
正确答案: A C D E G
-
教材p400
-
有关exec系列函数,下面说法正确的是()
-
A .可以用char[][] 来传递argv
-
B .进程调用了exec系列函数后,pid会变
-
C .进程调用了exec系列函数后,代码会改变。
-
D .system()和exec系列等价。
-
E .exec系列函数中带e的要传入环境变量参数
-
F .exec系列函数中带v的要传入环境变量参数
-
正确答案: C E
-
不能用char[][] 来传递argv,结尾的0(null)无法处理;system=fork+exec+wait;
结对及互评
点评模板:
- 博客中值得学习的或问题:
- xxx
- xxx
- ...
- 代码中值得学习的或问题:
- xxx
- xxx
- ...
- 其他
本周结对学习情况
- [2015532](http://www.cnblogs.com/zjy1997/)
- 结对照片
- 结对学习内容
- 教材第三章
- 实验五通讯协议设计
- ...
其他(感悟、思考等,可选)
xxx
xxx
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 10/10 | 1/1 | 10/10 | |
第二周 | 80/90 | 1/2 | 15/25 | |
第三周 | 100/190 | 1/3 | 15/40 | |
第四周 | 150/340 | 1/4 | 18/58 | |
第五周 | 2/6 | 20/78 | ||
第六周 | 2/8 | 20/98 | ||
第七周 | 2124/ | 2/10 | 20/118 | |
第八周 | 2/12 | 30/148 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:25小时
-
实际学习时间:20小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)