学习任务
- 复习Linux命令,特别是man -k, cheat, grep -nr xxx /usr/include
- 复习vi, gcc, gdb,make的使用
- 复习教材内容ch01 ch02 ch03 ch04 ch06 ch07
- 复习前面的考题(答案解析见http://group.cnblogs.com/topic/73060.html) ,下次考试考每次考试错的最多的题目
- 期中总结发一篇Blog
知识点总结
man命令调用手册页
man
手册通常被分为8个区段,要查看相应区段的内容,就在 man 后面加上相应区段的数字即可:
1 一般命令
2 系统调用
3 库函数,涵盖了C标准函数库
4 特殊文件(通常是/dev中的设备)和驱动程序 5 文件格式和约定 6 游戏和屏保 7 杂项 8 系统管理命令和守护进程
man有一个-k 选项用起来非常好,这个选项让你学习命令、编程时有了一个搜索引擎,可以举一反三。结合后面学习的grep 命令和管道,可以多关键字查找:
man -k key1 | grep key2 | grep key3 | ...
grep 命令
管道是一种通信机制,通常用于进程间的通信(也可通过socket进行网络通信),它表现出来的形式就是将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)。
grep命令的一般形式为:
grep [命令选项]... 用于匹配的表达式 [文件]...
使用grep命令查找宏
grep -nr /usr/include
cheat 命令
它提供显示Linux命令使用案例,包括该命令所有的选项和简短但尚可理解的功能。
用户权限管理
-
查看用户
$ who am i
-
创建用户
要创建用户需要 root 权限,要用到 sudo 这个命令。使用这个命令有两个大前提,一是要知道当前登录用户的密码,二是当前用户必须在 sudo 用户组。
$ sudo adduser 用户名
- 用户组
在 Linux 里面每个用户都有一个归属(用户组),用户组简单地理解就是一组用户的集合,它们共享一些资源和权限,同时拥有私有资源。
查看用户属于的用户组:
$ groups 用户名
或
$ cat /etc/group | sort
将其它用户加入 sudo 用户组:
$ su 当前用户 //获得root权限
$ groups 待添加用户
$ sudo usermod -G sudo 待添加用户 //将用户添加到sudo用户组
$ groups 待添加用户
-
删除用户
$ sudo deluser 待删除用户 --remove-home
Linux 文件的基本操作
-
新建
$ touch 文件名 $ mkdir 目录名
使用 -p 参数,同时创建父目录(如果不存在该父目录):
$ mkdir -p father/son/grandson
-
复制
使用cp(copy)命令复制一个文件或目录到指定目录。
$ cp 文件名 指定目录
要成功复制目录需要加上-r或者-R参数,表示递归复制:
$ cp -r father family
- 删除
使用rm(remove files or directories)命令,删除一个文件或目录:
$ rm test
- 移动文件与文件重命名
使用mv(move or rename files)命令,移动文件(剪切)。
$ mv 源目录文件 目的目录
重命名文件
$ mv 旧的文件名 新的文件名:
Vim编辑器
vim常用基本模式
- 普通模式(Normal mode)
- 插入模式(Insert mode)
- 命令行模式(Command line mode)
游标移动
按键 说明
h 左
l 右(小写L)
j 下
k 上
w 移动到下一个单词
b 移动到上一个单词
插入模式
在普通模式下使用下面的键将进入插入模式,并可以从相应的位置开始输入
命令 说明
i 在当前光标处进行编辑
I 在行首插入
A 在行末插入
a 在光标后插入编辑
o 在当前行后插入一个新行
O 在当前行前插入一个新行
cw 替换从光标所在位置后到一个单词结尾的字符
保存文档
从普通模式输入:进入命令行模式,输入w回车,保存文档。输入:w 文件名可以将文档另存为其他文件名或存到其它路径下
退出vim
从普通模式输入:进入命令行模式,输入wq回车,保存并退出编辑
命令 说明
:q! 强制退出,不保存
:q 退出
:wq! 强制保存并退出
:w <文件路径> 另存为
:saveas 文件路径 另存为 :x 保存并退出 :wq 保存并退出
普通模式下输入Shift+zz即可保存退出vim
删除文本
进入普通模式,使用下列命令可以进行文本快速删除
命令 说明
x 删除游标所在的字符
X 删除游标所在前一个字符
Delete 同x
dd 删除整行
dw 删除一个单词(不适用中文)
d$或D 删除至行尾
d^ 删除至行首
dG 删除到文档结尾处
d1G 删至文档首部
在命令之前加上数字,表示一次删除多行,如:2dd表示一次删除2行
gcc编译器
常用选项
-c 只编译不链接,生成目标文件.o
-S 只编译不汇编,生成汇编代码
-E 只进行预编译,不做其他处理 -g 在可执行程序中包含标准调试信息 -o file 将file文件指定为输出文件 -v 打印出编译器内部编译各过程的命令行信息和编译器的版本 -I dir 在头文件的搜索路径列表中添加dir目录
库选项
- -static 进行静态编译,即链接静态库,禁止使用动态库
- -shared 1.可以生成动态库文件
2.进行动态编译,尽可能的链接动态库,没有动态库时才会链接同名静态库 - -L dir 在库文件的搜索路径列表中添加dir目录
- -lname 链接称为libname.a或者libname.so的库文件。
如果两个库文件都存在,根据编译方式是static还是shared进行链接 - -fPIC 生成使用相对地址的位置无关的目标代码,
- (-fpic) 然后通常使用gcc的-static选项从该pic目标文件生成动态库文件。
编译过程
- 预处理: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** 创建可执行目标文件
gdb调试
使用GCC编译时要加“-g”参数
基本命令
- gdb programm(启动GDB)
- b 设断点(4种断点:行断点、函数断点、条件断点、临时断点)
- run 开始运行程序
- bt 打印函数调用堆栈
- p 查看变量值
- c 从当前断点继续运行到下一个断点
- n 单步运行
- s 单步运行
- quit 退出GDB
四种断点:
-
行断点
b [行数或函数名] <条件表达式>
-
函数断点
b [函数名] <条件表达式>
-
条件断点
b [行数或函数名] <if表达式>
-
临时断点
tbreak [行数或函数名] <条件表达式>
Makefile
Makefile的一般写法:
test(目标文件): prog.o code.o(依赖文件列表) tab(至少一个tab的位置) gcc prog.o code.o -o test(命令) .......
使用带宏的 Makefile
Makefile还可以定义和使用宏(也称做变量),从而使其更加自动化,更加灵活,在Makefile中定义宏的格式为:
macroname = macrotext
使用宏的格式为:
$(macroname)
书本知识汇总
第1章 计算机系统漫游
信息就是位十上下文
查看源文件可以用od 命令 :
od -tc -tx1 hello.c
操作系统内核是应用程序和硬件之间的媒介。
它提供三个基本的抽象:
1)文件是对I/O的抽象;
2)虚拟存储器是对主存和磁盘的抽象;
3)进程是对处理器、主存抽象和I/O设备的设备最后,网络提供了计算机系统之间通信的手段。从特殊系统的角度来看,网络就是一种I/O设备。
第2章 信息的表示和处理
小端法“高对高,低对低”大端与之相反。
布尔代数:二进制是计算机编码存储和操作信息的核心。
C语言中的位级运算:C语言支持按位的布尔运算。与、或、非、异或、同或
C语言中的逻辑运算:&&与 ||或 !非
C语言中的移位运算:x<>k:右移k位
扩展一个数字的位表示:在不同字长的整数之间转换又保持数值不变。
0扩展:简单的在表示的开头加0。 符号扩展:将补码数字转换成更大类型的数据。规则在表中添加最高有效位的值的副本。
IEEE浮点表示:标准 V=(-1)^sM2^E
符号:s 决定这个数是正数还是负数。
尾数:M 二进制小数。
阶码:E 对浮点数加权,权重是2 的E次幂。
将浮点数的位划分成三段分别进行编码:
一个单独的符号位直接编码符号。
K位的阶码字段exp=ek-1……e1e0编码阶段
N位小数字段
舍入:浮点运算只能近似的表示示数运算想要找到最接近x的值就是舍入,问题的关键在于在两个可能的值中间确定舍入方向。
向偶数舍入:也叫向最接近的值舍入。是默认方法。 将数字向上或向下舍入使的结果的最低有效数字是偶数。 其他三种方式产生实际值的确界。
第3章 程序的机器级表示
ISA:
指令集体系结构,机器级程序的格式和行为,它定义了处理器状态、指令的格式以及每条指令对状态的影响。
程序计数器(通常称为PC,用%eip表示),指示将要执行的下一条指令在存储器中的地址。
整数寄存器文件:存储地(对应于C语言的指针)或整数数据。
条件码寄存器:保存着最近执行的算数或逻辑指令的状态信息,用来实现控制或者数据流中的条件变化。
浮点寄存器:用来存放浮点数据。
编译过程:
C预处理器插入宏和头文件:gcc -E xxx.c -o xxx.i
编译器产生源代码的汇编代码:gcc -S xxx.i -o xxx.s
汇编器化成二进制目标代码:gcc -c xxx.s -o xxx.o
链接器生成最终可执行文件:gcc xxx. -o xxx
用objdump -d xxx.o -o xxx.s 反汇编
栈
1 遵循“后进先出”的原则
2 push压栈,pop出栈
3 栈顶:总是从这端插入和删除元素 4 栈顶元素的地址是最低的 5 栈指针%esp保存着栈顶元素的地址
算术和逻辑操作
加载有效地址:实际是将有效地址写入目的操作数,目的操作数必须是寄存器。
一元操作:只有一个操作数,可以是寄存器也可是存储器位置。
二元操作:源操作数是第一个,可以是立即数、寄存器、存储器
目的操作数是第二个,可以是寄存器、存储器
两个不能同时为存储器。
移位:第一个是移位量,用单个字节编码(只允许0-31位的移位),可以是立即数或者放在单字节寄存器%cl中
算术右移SAR,填上符号位;逻辑右移SHR,填上0。 目的操作数可以是一个寄存器或存储器。
控制中最核心的是跳转语句:
有条件跳转(实现if,switch,while,for)
无条件跳转jmp(实现goto)
条件码寄存器
描述了最近的算术或逻辑操作的属性,可以检测这些寄存器来执行条件分支指令
常用条件码:CF ZF SF OF
注意leal不改变任何条件码
IA32通过程序栈来实现过程调用。栈用来:
传递过程参数 存储返回信息 保存寄存器 本地存储
最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针。程序执行时,栈指针可以移动,大多数信息的访问都是相对于帧指针的。
栈向低地址方向增长。
call指令
指明被调用过程起始的指令地址,效果是将返回地址入栈,并跳转到被调用过程的起始处。
ret指令
从栈中弹出地址,并跳转到这个位置,使用这个指令栈指针要指向call指令存储返回地址的位置。
函数返回值存在%eax中
第4章 处理器体系结构
Y86指令
movl:irmovl、rrmovl、mrmovl、rmmovl,分别 显式地指明源和目的地的格式。第一个字母表明源的类型,i(立即数)、r(寄存器)或m(存储器 ),第二个字母代表目的,可以是r或者m。
OPl(整数操作指令):addl、subl、andl和xorl。只对寄存器数据进行操作,同时还设置条件码。
jXX(跳转指令):jmp、jle、jl、je、jne、jge、jg,根据分支指令的类型和条件码的设置来选择分支。
cmovXX(条件传送指令):cmovle、cmovl、cmove、cmovne、cmovge和comvg,与寄存器-寄存器传送指令rrmovl一样,但只有当条件码满足所需要的约束时才会更新目的寄存器的值。
call和ret:call指令将返回地址入栈,然后跳转到目的地址。ret指令从这样的过程调用中返回。
pushl和popl:入栈和出栈。
halt:停止指令的执行。
指令编码
指令的字节级编码规则:高4位为代码部分,低四位为功能部分,功能值只有在一组相关指令共用一个代码时才有用。
8个程序寄存器当中,每个都有相应的0~7的寄存器标识符。程序寄存器存在CPU中的一个寄存器文件中,这个文件就是一个小的、以寄存器ID作为地址的随机访问存储器。
附加寄存器指示符字节:指定一个或者两个寄存器。
附加4字节的常数字:作为irmovl的立即数数据,rmmovl和mrmovl的地址指示符的偏移量,以及分支指令和调用指令的目的地址。
Y86异常
状态码:描述程序执行的总体状态。
值 名字 含义
1 AOK 正常操作
2 HLT 处理器执行halt指令(指令停止)
3 ADR 遇到非法地址
4 INS 遇到非法指令
逻辑设计和硬件控制语言HCL
实现一个数字系统需要的三个组成部分:计算对位进行操作的函数的组合逻辑、存储位的存储器元素,以及控制存储器元素更新的时钟信号。
Y86顺序实现
取指:从存储器读取指令字节,地址为程序计数器(PC)的值。指令指示符字节两个四位部分,称为icode(指令代码)和ifun(指令功能)。vaIP(下一条指令的地址)=PC+已取出指令的长度。
译码:从寄存器文件读入最多两个操作数,得到valA和/或valB。
执行:算数逻辑单元(ALU)根据ifun的值执行指令指明的操作,计算存储器引用的有效地址,或者增加或减少栈指针。得到的值称为valE。也可根据条件码执行跳转。
访存:将数据写入存储器,或者从存储器读出数据。读出的值为valM。
写回:最多可以写两个结果到寄存器文件。
更新PC:将PC设置成下一条指令的地址。
第6章 存储器层次结构
SRAM与DRAM的对比:
SRAM DRAM 不需要刷新 以纳秒为周期刷新 存取速度快 存取速度慢 对光电噪声不敏感 光电因素易导致电压改变 晶体管多密集度低 电容小,密集度高 功耗贵代价高 功耗低
-
访问主存
-
总线:数据流通过称为总线的共享电子电路在处理器和DRAM之间传送。是一组并行的导线,能携带地址、数据和控制信号。
-
总线事务:CPU和主存之间的数据传送的过程。读事务,从主存传数据到CPU;写事务,从CPU传数据到主存。
-
I/O桥:将系统总线的电子信号翻译成存储器总线的电子信号。系统总线连接CPU和I/O桥,控制总线连接I/O桥和主存。
-
磁盘存储
-
磁盘构造:磁盘由盘片构成,表面覆盖着磁性记录材料,中央有一个可以旋转的主轴 ,旋转速率大约为5400-15000每分钟。磁盘的每个表面是一组称为磁道的同心圆组成,每个磁道被划分为一组扇区,扇区之间由一些间隙隔开,间隙存储用来标识扇区的格式化位。
-
磁盘容量由以下技术因素决定:
-
记录密度(位/英寸):磁道一英寸的段中可以放入的位数。
-
磁道密度(道/英寸):从盘片中心出发半径上一英寸的段内可以有的磁道数
-
面密度(位/平方英寸):记录密度与磁道密度的乘积。
-
-
磁盘操作:磁盘用读/写头来读写存储在磁性表面的位,而读写头连接到一个传动臂 一端,通过移动转动臂将读写头定位在磁道上的机械运动称为寻道。磁盘以扇区大小的块来读写数据,对扇区的访问时间有三个主要的组成部分:
-
寻道时间:转动臂将读/写头定位到包含目标扇区的磁道上所需时间。
-
旋转时间:驱动器等待目标扇区的第一个位旋转到读/写头下的时间。最大为1/RPM,平均旋转时间是Tmax的一半。
-
传送时间:读写并传送该扇区内容的时间。平均传送时间为:1/RPM*1/平均扇区数
-
-
逻辑磁盘块:现代磁盘将盘面的构造视为一个B个扇区大小的逻辑块序列,磁盘控制器维护着逻辑块号和实际磁盘扇区之间的映射关系。逻辑块号可识别为一个盘面、磁道、扇区三元组,唯一的标识了相对应的物理扇区。内存可以看成字节数组、磁盘可以看成块数组。
-
连接到I/O设备:所有的I/O设备都是通过I/O总线连接到CPU和主内存。有三种不同类型:
-
通用串行总线:一个广泛的使用标准,用于连接各种外围I/O设备。
-
图形卡(或适配器):包含硬件和软件逻辑,代表CPU在显示器上画像素。
-
主机总线适配器: 将一个或者多个磁盘连接到I/O总线,使用一个特别的主机总线接口定义的通信协议。
-
-
访问磁盘:CPU使用一种称为存储器映射I/O的技术向I/O设备发出命令,地址空间中为I/O设备通信保留的地址称为I/O端口。
固态硬盘
固态硬盘是一种基于闪存的存储技术。一个硬盘包由一个或者多个闪存芯片和内存翻译层组成,闪存芯片替代旋转磁盘中的机械驱动器,而闪存翻译层将对逻辑块的请求翻译成对底层物理设备的访问
局部性
-
时间局部性(temporal locality):被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。
-
空间局部性(spatial locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。
-
一个连续向量中,每隔k个元素进行访问,被称为步长为k的引用模式,具有步长为1的引用模式称为顺序引用模式,随着步长增加空间局部性下降。
-
双重嵌套循环按照行优先顺序读取数组元素。(因为C数组在存储器中是按照行顺序来存放的)
-
存储器层次结构
存储器层次结构中的缓存
高速缓存是一个小而快速的存储设备,作为存储在更大、更慢的设备中的数据对象的缓冲区域。每一层存储器被划分成连续的数据对象片,称为块,每个块都有唯一的对象和名字。数据总是以块大小为传送单元在第k层和第k+1层之间来回拷贝。
-
缓存命中:当程序需要第k+1层的某个数据对象d时,首先在当前存储的第k层的一个块中查找d,如果d刚好在第k层中,则称为缓存命中。
-
缓存不命中:如果k层中没有缓存数据d,则称为缓存不命中,此时要从k+1层取出包含d的块,可能会覆盖(替换/驱逐)现在的一个块(牺牲块)。决定该替换哪个快是缓存的替换策略来控制的。(例如,随机替换策略/LRU策略)
-
缓存不命中的种类
-
强制性不命中/冷不命中:第k层缓存是空的(冷缓存),只是短暂的状态,不会在反复访问存储器使得缓存暖身之后的稳定状态出现。
-
冲突不命中:第k+1层的第i块,必须放置在第k层的块(i mod 4)中,这种限制性的放置策略引起冲突不命中。
-
高速缓存存储器
通用的高速缓存存储器结构
高速缓存的大小C = S * E * B。
-
s个组索引位:一个无符号整数,说明字必须存储在哪个组中。
-
t个标记位:组中的哪一行包含这个字。
-
b个块偏移位:在B个字节的数据块中的字偏移。
高速缓存参数的性能影响
-
不命中率:不命中数量/引用数量
-
命中率:1-不命中率
-
命中时间:从高速缓存传送一个字到CPU所需的时间,包括组选择,行匹配,字抽取的时间。
-
不命中处罚:由于不命中所需要的额外时间。
影响性能的因素
-
高速缓存大小的影响:较大的高速缓存可能会提高命中率,但使大存储器运行的更快是更难一些的。
-
块大小的影响:较大的块能利用程序中可能存在的空间局部性,帮助提高命中率;但块越大意味着高速缓存行较少,损害时间局部性。
-
相联度的影响:相联度较大(E值较大)优点是降低了高速缓存由于冲突不命中出现抖动的可能性,但成本较高。
-
写策略的影响:直写高速缓存易实现,而且能使用独立于高速缓存的写缓冲区,用来更新存储器,不命中开销小。写回高速缓存引起的传送比较少,允许更多的到存储器的宽带用于执行DMA的I/O设备。越下层越可能使用写回。
期中个人总结
课程进行到一半,学习上的不足还是有很多。通过期中总结,把过去已经学习了的知识点重新复习了一遍,之前不熟悉或者不理解的地方,在复习的时候也有重新理解并反复消化。
个人认为定时的回头复习是很重要的,遗忘的速度很快,因此课堂的测试很重要,可以帮助我们重新巩固一遍上周的知识,从而明白自己的漏洞在哪里。因此,我也有越来越认真的面对每一次测试,当做是对自己上一周学习的检验。
书读一遍是不够的,代码敲打一遍也是不够的,必须要反复练习消化,才能真正掌握知识。
这门课程的学习过程中,我逐渐理解了学习的方法,在于效率,学习的时间有限,如何在有限的时间内提高掌握知识的效率,是很重要的。而学习也不是一个一蹴而就的事情,是需要付出脑力劳动,循序渐进,由表及里,慢慢浸透的过程。从一开始的一无所知,到现在的课程期中,我都在不断琢磨改善自己的学习方法。
同时我们也和老师在不断磨合,老师的任务要求、测试、课堂讲解,促进了我们的学习,也让我们在学习的时候没有误入歧途。
我认为老师在课上提前点拨下一周重点,并且重复上一周重点,是很有效的。
之前的家庭作业没有跟上,之后会努力跟上全部作业的。谢谢老师。