期中总结
第一章
1.信息就是“位+上下文”。
2.系统的硬件组成
- 总线:携带信息字节并负责在各个部件之间传递;定长的字节块,即字。字中的字节数(即字长)是一个基本的系统参数。
- I/O设备
- 主存,由一组DRAM组成
3.操作系统两个基本功能:防止硬件被失控的应用程序滥用;向应用程序提供简单一致的机制来控制复杂的低级硬件设备
4.操作系统三个基本抽象:文件<--I/O设备;虚拟存储器<--主存,磁盘I/O设备;进程<--处理器,主存,I/O设备
第二章
1.makefile使用
Makefile带来的好处就是——“自动化编译”,一但写好,只需要一个 make 命令,整个工程便可以完全编译,极大的提高了软件的开发效率
一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干个目录中。makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更复杂的功能操作
make工具最主要也是最基本的功能就是根据makefile文件中描述的源程序至今的相互关系来完成自动编译、维护多个源文件工程。而makefile文件需要按某种语法进行编写,文件中需要说明如何编译各个源文件并链接生成可执行文件,要求定义源文件之间的依赖关系。
2.编译链接器
指源代码转化成生成可执行代码的过程,最常用的编译器是gcc。
gcc的编译流程
·预处理阶段:头文件和宏定义,—E可以让gcc在预处理结束之后停止编译过程,因此可以看到预处理的过程
一般格式为:gcc [选项] 要编译的文件 [选项] 目标文件
gcc -E hello.c -o hello.i
·编译阶段:gcc将代码翻译成汇编语言,使用选项-S只进行编译而不进行汇编,结果生成汇编代码。
gcc -S hello.i -o hello.s
汇编阶段:将.s文件转成目标文件,使用选项-c可以看到汇编代码转换为二进制目标代码。
gcc -c hello.s -o hello.o
链接阶段:默认搜索链接到libc.so.6函数库当中,调用库文件中已经实现的函数。
gcc编译选项分析
第三章
1.gcc -S xxx.c 可以得到C语言编译器产生的汇编代码,但不会做其他工作;使用“-c”命令,GCC就会编译并汇编该代码,得到二进制文件XXX.o。
2.寻址方式的通用公式:有效地址可以表示为Imm+R[Eb]+R[Ei]*s。Imm为立即数偏移;Eb为基址寄存器;Ei为变址寄存器;s为比例因子。
3.IA32利用程序栈来支持过程调用(包括将数据和控制)。为单个过程分配的那部分栈做栈帧。最底端(地址最大)%ebp为帧指针;最顶端(地址最小)%esp为栈指针。当程序执行时,栈指针可以移动。
4.转移控制——
1)call指令:后接被调用过程的起始的指令地址。效果是将返回地址入栈,并跳转到被调用过程的起始处。
2)ret指令:从栈中弹出地址,并跳转到这个位置。
第四章
1.Y86
一个简单的、可以称之为IA32指令集的子集的指令集;只包括四字节整数操作,寻址方式比较少。指令编码长度从1——6字节不等。指令集的一个重要性只就是字节编码必须具有唯一的解释。
关于指令结构,每条指令的第一个字节表明指令的类型;这个字节分为两个部分,每部分四位:高四位是代码部分(0——0xB),第四位是功能部分。这里补充一些缩写:立即数(i),寄存器(r)、存储器(m)。指令附加的寄存器指示符字节依次是数据源(如果是立即数,把这一位设置成0xf)、目的寄存器/基址寄存器。有些指令需要附加四字节的常数字,采用小端法(倒序)编码
2.SEQ的时序(逐步深化)
- 要控制处理器中活动的时序,只需要寄存器和存储器的时钟控制
- 除了指令存储器只用来读指令故而可以看作组合逻辑之外,剩余的程序计数器、条件码寄存器、数据存储器和寄存器文件需要通过一个时钟信号来控制(控制时序)
- 在每个时钟周期内,程序计数器都会装载新的指令地址;只有执行整数运算指令的时候,才会装载条件码寄存器。只有执行rmmovl,pushl,call时,才会写数据存储器。
- Y86指令集的本质遵循这样一项组织原则:处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态
第六章
1.存储技术
- SRAM(静态):高速缓存存储器。将每个位存储在一个双稳态的存储器单元里面。(每个单元用一个六晶体管电路来实现;其属性是可以无限期保持在两个不同的典雅配置或者状态之一,其他的任何状态都是不稳定的)
- DRAM(动态):将每个位存储为对一个电容的充电(这个电容很小)。存储单元对干扰(如光线、噪音等)很敏感;当电容的电压被扰乱之后就永远不会恢复。优势是密集度低,成本低。
- DRAM的芯片中的单元被分成d个超单元,每个超单元都由w个DRAM单元组成。一个d*w的DRAM总共存储了dw位的信息。超单元被组织成一个r行c列的长方形阵列,这里rc = d。信息通过引脚的外部连接器流入和流出芯片。
- 每个DRAM芯片被连接到某个称为存储控制器的电路,这个电路可以一次传送w位到每个DRAM芯片或者依次从每个芯片传出w位。电路设计者将DRAM组织成二维而不是线性数组的一个原因是降低芯片上地址引脚的数量。
- DRAM芯片包装在存储器模块中,它是插到主版的扩展槽上的。
- 磁盘是保存大量数据的存储设备;但读取速度慢。
- 磁盘有若干盘片组成,密封在容器(磁盘驱动器)内;每个盘片的两个表面都有一组被称为磁道的同心圆;每个同心圆由一些间隙分隔成一组等容量磁道(通常是512字节),间隙中存储的是标识扇区的格式化位。
- 柱面:所有盘片表面到主轴中心距离相等的磁道的集合
- PROM:只能被编程一次。
- 可擦可写编程ROM(EPROM):被擦除和重写的次数可以达到10^3次
- 电子可擦除PROM(EEPROM):能够被编程的次数可以达到10^3次。
- 闪存:基于EEPROM。基于此的磁盘驱动器称为固态硬盘 存储在ROM设备中的程序通常称为固件;当一个计算机系统通电之后,它会运行存储在ROM中的固件
- 容量是指一个磁盘上可以记录的最大位数。决定因素:
- 记录密度;磁道密度;面密度(前两者乘积)
- 读写通过连在传动臂一段的读写头完成;可以定位在盘面上的任何磁道上;这样的机械运动称为寻道。每个盘面对应一个读写头。所有的读写头一致行动,即在任意时刻,所有的读写都发生在同一盘面上
2.磁盘结构
- 磁盘是保存大量数据的存储设备;但读取速度慢。
- 磁盘有若干盘片组成,密封在容器(磁盘驱动器)内;每个盘片的两个表面都有一组被称为磁道的同心圆;每个同心圆由一些间隙分隔成一组等容量磁道(通常是512字节),间隙中存储的是标识扇区的格式化位。
- 柱面:所有盘片表面到主轴中心距离相等的磁道的集合
3.存储器层次结构
- 存储器层次结构的中心思想是:对于每个k,位于k层的更快更小的存储设备作为位于(k+1)层的更大更慢的存储设备的缓存。
- 第(k+1)层的存储器被划分成连续的数据对象片,称为块;数据总是以块大小为传送单元在相邻两层之间来回拷贝的;在任何时刻,第k层的缓存包括第(k+1)层块的一个子集的拷贝。
- 缓存命中:当程序需要第(k+1)层的数据对象d的时候,首先会在第k层找d;如果d刚好缓存在第k层,那么就叫做缓存命中;反之,不命中
- 如果缓存不命中,那么第k层缓存就从第(k+1)层取出包含该数据的块,有可能会覆盖现有的块。覆=决定替换哪个块是由缓存的替换策略来控制的;例如,一个具有随机替换策略的缓存会随机选择;而LRU替换策略会选择被访问时间距今最远的块
4.高速缓存存储器
- 作用:连接CPU和主存
- 每个存储器地址有m位,形成M=2^m个不同地址。这m位被划分成t个标记位、s个组索引位和b个块偏移位。
- 这样一个机器的高速缓存被组织成S=2^s个高速缓存组的数组;每个数组包含E个高速缓存行;每行由一个B=2^b字节的数据块、一个有效位(指明这个行是否包含有效信息)、t=m-(b+s)个标记位(唯一标识存储在这个高速缓存行中的块)组成
- 高速缓存确定一个请求是否命中,然后抽搐被请求字的过程,分为:组选择,行匹配,字抽取
- 组选择:从w的地址中抽取组索引;这些位被解释成对应于一个组号的无符号整数
- 行匹配:对于直接映射高速缓存,行匹配是容易而且快的;因为每个组只有一行
- 字匹配:块偏移提供的是这个字的第一个字节是从哪个位置开始的
关键点
man:
使用man -k passwd会找到很多和passwd相关的帮助页
grep:
grep 可以对文件全文检索,支持正则表达式
cheat:
提供显示Linux命令使用案例,包括该命令所有的选项和简短但尚可理解的功能。
find:查找一个文件在系统中的什么位置
find的重要参数
-atime 最后访问时间
-ctime 创建时间
-mtime 最后修改时间
whereis
只能搜索二进制文件(-b),man帮助文件(-m)和源代码文件(-s)
which
which本身是 Shell 内建的一个命令,我们通常使用which来确定是否安装了某个指定的软件,因为它只从PATH环境变量指定的路径中去搜索命令
$ which man
重要工具
vim:
三种模式:
命令行模式,插入模式,底行模式
模式的切换 :
vim启动进入普通模式,处于插入模式或命令行模式时只需要按Esc或者Ctrl+[(这在vim课程环境中不管用)即可进入普通模式。
普通模式->插入模式:普通模式中按i(插入)或a(附加)键都可以进入插入模式,
普通模式->命令行模式:普通模式中按:进入命令行模式。
退出:命令行模式中输入wq回车后保存并退出vim
删除信息:
dd 删除整行
dw 删除一个单词(不适用中文)
d$或D 删除至行尾
d^ 删除至行首
dG 删除到文档结尾处
d1G 删至文档首部
*命令之前加上数字,表示一次删除多行
快速跳转(行间):
nG(n Shift+g) 游标移动到第 n 行(如果默认没有显示行号,请先进入命令模式,输入:set nu以显示行号)
gg 游标移动到到第一行
G(Shift+g) 到最后一行
小技巧:你在完成依次跳转后,可以使用Ctrl+o快速回到上一次(跳转前)光标所在位置,
复制(类似于删除d):普通模式中使用y复制
gcc(是GNU项目中符合ANSI C标准的编译系统)
预处理:gcc –E hello.c –o hello.i; gcc –E调用cpp
编 译:gcc –S hello.i –o hello.s; gcc –S调用ccl
汇 编:gcc –c hello.s –o hello.o; gcc -c 调用as
链 接:gcc hello.o –o hello ; gcc -o 调用ld
=>./hello(./当前目录)
gdb
程序保存退出后用gcc进行编译,一定要记得加上选项“-g”这样编译出来的可执行代码才包含调试信息
gcc -g test.c -o test
基本命令:
gdb programm (启动GDB)
b 设断点(要会设4种断点:行断点、函数断点、条件断点、临时断点)
run 开始运行程序
bt 打印函数调用堆栈
p 查看变量值
c 从当前断点继续运行到下一个断点
n 单步运行
s 单步运行
quit 退出GDB
四种断点
1.行断点
b [行数或函数名] <条件表达式>
2.函数断点
b [函数名] <条件表达式>
3.条件断点
b [行数或函数名] <if表达式>
4.临时断点
tbreak [行数或函数名] <条件表达式>
静态库的创建:
(1)使用归档工具ar,将目标文件集成在一起
# gcc -c unusgn_pow.c
# ar rscv libpow.a unsgn_pow.o
a - unsgn_pow.o
(2) 编译主程序来观看一下结果
# gcc -o pow_test pow_test.c -L. -lpow
# ./pow_test 2 10
2.^10=1024
"-L dir" :在库文件的搜索路径中添加dir目录
"-lname" 选项指示编译时连接到库文件libname.a或libname.so
动态库的创建:
- 使用gcc的-fPIC选项为动态库构造一个目标文件
# gcc -fPIC -Wall -c unsgn_pow.c
2.使用-shared选项和已创建的位置无关目标代码,生成动态库libpow.so
# gcc -shared -o libpow.so unsgn.so
3.编译程序(将链接到刚生成的动态库lipow.so)
# gcc -o pow_test pow_test.c -L. -lpow
makefile:
一个makfile通常包含的内容:
需要有make工具创建的目标体(target),通常指目标文件和可执行文件
需要创建的目标所以依赖的文件(dependency_file)
创建每个目标体所需要运行的命令(command)这一行必须由制表符Tab开头
参考资料来自闫佳歆同学
浙公网安备 33010602011771号