学习目标:(链接是我每周博客中的相应部分和老师发布的考试答案)

1.复习Linux命令(信息安全系统设计基础第一周学习总结),特别是man -k, cheat, grep -nr xxx /usr/include
2.复习vi, gcc, gdb,make的使用(信息安全系统设计基础第二周学习总结
3.复习教材内容
ch01
ch02(信息安全系统设计基础第三周学习总结
ch03(信息安全系统设计基础第四周学习总结
ch04(信息安全系统设计基础第五周学习总结
ch06(信息安全系统设计基础第六周学习总结
ch07
4.复习前面的考题(历次考试答案解析

一、重要知识点总结

(一)Linux命令

1.man -k

man -k k1 | grep k2 | grep k3 ...
  • 模糊查找,查找含有关键字的内容

  • man 中的不同区段代表相应的内容,通过限定查找内容的区段,可以过滤出更简洁的结果,共有8个区段:

      1	Linux中的一般命令
      2	系统调用
      3	库函数,涵盖了C语言的标准函数库
      4	特殊文件(通常是/dev中的设备)和驱动程序
      5	文件格式和约定
      6	游戏和屏保
      7	杂项
      8	系统管理命令和守护进程
    
  • 查看某命令在指定区段内的解释时用法:

      man 区段号 命令
    

2.cheat

  • 以举例的方式告诉我们某个命令或者函数的用法。

3.grep -nr XXX /usr/include

  • 查找某个宏。

4.其它查找方法

- find		一般查找
- locate	急速查找
- whereis	查找文件所在文件夹
- which		查找可执行文件所在文件夹

(二)编译程序

1.、Vim

(1)六种模式

普通模式
插入模式
可视模式
选择模式
命令行模式
Ex模式

(2)常用命令总结

  • 插入

      i		在当前光标处进行编辑
      a		在光标后插入编辑
    
  • 退出

      :q!     强制退出,不保存
      :q      退出
      :wq!    强制保存并退出
      :wq     保存并退出
      :w <文件路径>       另存为
    
  • 删除

      x       删除游标所在的字符
      dd      删除整行
    
  • 行间跳转

      nG(n Shift+g)   光标移动到第n行
    
  • 复制与粘贴

      nyy		复制光标所在及其后的整行共n行
      p		代表粘贴至光标后
    
  • 功能设定

      :set autoindent(ai)		设置自动缩进
      :set cindent(cin)		设置C语言风格缩进
      :set nu					以显示行号
    

2.GCC编译

(1)常用选项

-c		只编译不链接,生成目标文件.o
-S		只编译不汇编,生成汇编代码
-E		只进行预编译,不做其他处理
-g		在可执行程序中包含标准调试信息

(2)编译过程

原文件->预处理->编译->汇编->连接->可执行文件
  • 预处理:gcc –E xxx.c –o xxx.i

    • gcc –E调用cpp 生成中间文件
  • 编 译:gcc –S xxx.i –o xxx.s

    • gcc –S调用ccl翻译成汇编文件
  • 汇 编:gcc –c xxx.s –o xxx.o

    • gcc -c调用as翻译成可重定位目标文件
  • 链 接:gcc xxx.o –o xxx

    • gcc -o调用ld**创建可执行目标文件
  • 运行可执行文件 ./xxx
    在命令行上运行这个可执行目标文件需要输入它的名字(-o后若不指定生成文件名,则默认为a.out)

3.GDB调试

(1)基本命令

  • 进入GDB

      gcc -g xxx.c -o xxx
      gdb xxx
    
  • 查看源码

      (gdb) l			进行行号提示
      (gdb) b n		在第n行设置断点
      (gdb) r			运行代码,运行至断点处
      
      (gdb) n			单步运行
      (gdb) c			使程序继续往下运行,直到再次遇到断点或程序结束
      (gdb) q			退出GDB
      (gdb) watch n	在"n"设置了观察点,观察变量的变化情况
    

(2)四种断点

  • 函数断点

      b   函数名 条件表达式
    
  • 行断点

      b   行数或函数名  条件表达式
    
  • 条件断点

      b   行数或函数名  if表达式
    
  • 临时断点

      tbreak  行数或函数名  条件表达式
    

4.makefile

  • 用途:实现自动化编译

  • 格式:

      target(目标文件)... : prerequisites(要生成那个target所需要的文件或是目标)...
      	command(任意的Shell命令,就是make需要执行的命令)
      ...
    
  • 这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。

  • Makefile中的宏,也称作变量,有两种定义方式

      递归展开方式		VAR=var
      简单方式		VAR:=var
    
  • 使用变量的格式为

      $(VAR)
    

(三)教材总结(很多之前的博客都已经写过,只写重要的点,不展开)

1.第一章:计算机系统漫游

(1)信息=位+上下文

系统中所有信息的都是由一串位表示的,区分不同数据对象的唯一方法是它的上下文。

(2)冯式结构

CPU执行指令的操作:加载、存储、操作、跳转

(3)存储系统核心思想———缓存

(4)操作系统核心抽象

文件、虚存、进程、虚拟机

(5)查看源文件用od 命令 : od -tc -tx1 hello.c

2.链接

(1)链接器的两个任务

- 符号解析
- 重定位

(2)目标文件的三种形式

- 可重定位目标文件
- 可执行目标文件
- 共享目标文件

(3)目标文件格式

- a.out		可执行文件
- COFF		一般目标文件格式
- PE			可移植可执行文件格式
- ELF		可执行可连接文件格式

(4)readelf命令

用于显示一个/多个elf格式目标文件的信息

(5)全局符号

- 强符号:函数和已经初始化的全局变量
- 弱符号:未初始化的全局变量
  • 规则:

      - 不允许有多个强符号
      - 若有一个强符号和多个弱符号,选强符号
      - 若有多个弱符号,任选一个
    

(6)处理目标文件的工具

- AR			创建静态库,插入、删除、列出和提取成员
- STRINGS		列出一个目标文件中所有可打印的字符串
- STRIP			从目标文件中删除符号表中定义的符号
- NM			列出一个目标文件中节的名字和大小
- READELF		显示一个目标文件的完整结构
- OBJDUMP		二进制工具之母,可以显示一个目标文件中所有的信息

3.信息的表示和处理

(1)三种数字

无符号数、有符号数(2进制补码)、浮点数
  • 补码是利用寄存器的长度是固定的特性简化数学运算,只要一个加法器就可以实现所有的数学运算。
  • 进制转换:拿二进制作中间结果

(2)信息存储

  • gcc -m32 可以在64位机上(比如实验楼的环境)生成32位的代码

  • 字节顺序是网络编程的基础

      - 小端是“高对高、低对低”
      - 大端是“高对低、低对高”
    
  • 逻辑运算(结果是1或0)和位运算(结果是位向量)

      只要一个与非门,就可以完成所有的逻辑运算。
    
  • 掩码是位运算的重要应用,对特定位可以置一,可以清零

(3)整数表示与运算

  • C语言中有符号数和无符号数的转换规则,位向量不变——信息就是位+上下文。

  • 0扩展和符号扩展

      零扩展:要将一个无符号数转换为一个更大的数据类型,只需简单的最高位前加0。
      符号扩展:将一个补码数字转换为一个更大的数据类型,在表示中添加最高有效位值的副本。
    
  • 截断数字

      截断一个数字可能会改变其值,这也是值溢出的一种形式。
    
  • 计算机执行的“整数运算”实际上是一种模运算。

  • 表示数字的有限字长限制了可能的值的取值范围。

  • 无论运算数是以无符号形式还是补码形式表示,都有完全一样或者非常类似的位级行为。

(4)浮点数——IEEE浮点表示

  • IEEE浮点标准用V = (-1)^s × M × 2^E的形式来表示一个数

      - 符号:s决定这个数是负数(s=1)还是正数(s=0),而对于数值0的符号位解释作为特殊情况处理。
      - 尾数:M是一个二进制小数,它的范围是1~2-ε,或者是0~1-。
      - 阶码:E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。
    
  • 将浮点数的位表示划分为三个字段,分别对这些值进行编码:

      - 一个单独的符号位s直接编码符号s。
      - k位的阶码字段exp = ek-1…e1e0编码阶码E。
      - n位小数字段frac = fn-1…f1 f0编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。
    

4.程序的机器级表示

(1)寻址方式三代

DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
8086的分段模式
IA32的带保护模式的平坦模式

(2)ISA指令集体系结构

  • 机器级程序的格式和行为,它定义了处理器状态、指令的格式以及每条指令对状态的影响。

      - 程序计数器(通常称为PC,用%eip表示),指示将要执行的下一条指令在存储器中的地址。
      - 整数寄存器文件:存储地(对应于C语言的指针)或整数数据。
      - 条件码寄存器:保存着最近执行的算数或逻辑指令的状态信息,用来实现控制或者数据流中的条件变化。
      - 浮点寄存器:用来存放浮点数据。
    

(3)编译过程:

- 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 反汇编

(4)算术和逻辑操作

  • 加载有效地址

      leal,从存储器读数据到寄存器,而从存储器引用的过程实际上是将有效地址写入到目的操作数。目的操作数必须是一个寄存器。
    
  • 一元操作和二元操作

      一元操作:只有一个操作数,既是源又是目的,可以是一个寄存器或者存储器。
      二元操作:第二个操作数既是源又是目的,两个操作数不能同时是存储器。
    

(5)栈帧

  • 栈帧结构

      - 为单个过程分配的栈叫做栈帧,寄存器%ebp为帧指针,而寄存器指针%esp为栈指针,程序执行时栈指针移动,大多数信息的访问都是相对于帧指针。
      - 栈向低地址方向增长,而栈指针%esp指向栈顶元素。
    
  • 转移控制

      - call:目标是指明被调用过程起始的指令地址,效果是将返回地址入栈,并跳转到被调用过程的起始处。
      - ret:从栈中弹出地址,并跳转到这个位置。
      - 函数返回值存在%eax中
    

5.处理器体系结构

(1)Y86指令集体系结构

  • 程序员可见的状态(Y86程序中的每条指令都会读取或修改处理器状态的某些部分)

      - 8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp和%ebp。
      - 条件码:ZF(零)、SF(符号)、OF(有符号溢出)
      - 程序计数器(PC):存放当前正在执行的指令的地址
      - 存储器:很大的字节数组,保存着程序和数据。Y86系统用虚拟地址来引用存储器的位置,硬件和操作系统软件联合起来将虚拟地址翻译成实际或者物理地址。
      - 状态码(stat):表明程序执行的总体状态。(异常处理)
    
  • 指令编码规则

      高4位为代码部分,低四位为功能部分
    
  • Y86异常(状态码:描述程序执行的总体状态。)

      值		名字		含义
      1		AOK		正常操作
      2		HLT		处理器执行halt指令(指令停止)
      3		ADR		遇到非法地址
      4		INS		遇到非法指令
    

(2)逻辑设计和硬件控制语言HCL

  • 实现一个数字系统需要的三个组成部分

      - 计算对位进行操作的函数的组合逻辑
      - 存储位的存储器元素
      - 控制存储器元素更新的时钟信号
    

6.存储器层次结构

(1)三种常见存储技术:RAM/ROM/磁盘

  • 随机访问存储器(RAM)

      静态RAM(SRAM)
      动态RAM(DRAM)
    
  • 非易失性存储器(ROM)

    • 可编程ROM(PROM):只能被编程一次。PROM每个存储单元有一种熔丝,只能用高电流熔断一次。
    • 可擦写可编程ROM(EPROM):紫外线光照射过窗口,EPROM就被清除为0,被擦除和重编程的次数为1000次。
    • 电子可擦除ROM(EEPROM):不需要一个物理上独立的编程设备,因此可以直接在印制电路卡上编程,能够编程的次数为10^5。
    • 闪存:基于EEPROM,为大量的电子设备提供快速而持久的非易失性存储。
  • 磁盘

      - 磁盘结构:盘片、磁道、扇区、间隙、柱面
      - 磁盘容量:记录密度、磁道密度、面密度
      - 访问时间:寻道时间+旋转时间+传送时间
      - 访问磁盘:CPU使用一种称为存储器映射I/O的技术向I/O设备发出命令,地址空间中为I/O设备通信保留的地址称为I/O端口。
    
  • 逻辑磁盘块

  • 数据总线、控制总线、地址总线

  • 系统总线、存储总线、I/O总线

  • 读写事务:读事务,从主存传数据到CPU;写事务,从CPU传数据到主存。

(2)局部性

局部性原理:一个编写良好的计算机程序倾向于引用邻近于其他最近引用过的数据项,或者最近引用过的数据项本身。有良好局部性的程序比局部性差的程序运行的更快,在硬件层引入高速缓存存储器就体现了局部性原理。
  • 对程序数据引用的局部性

      - 时间局部性(temporal locality):被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。
      - 空间局部性(spatial locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。
    
  • 取指令的局部性

      - 程序指令是存放在存储器中的,CPU读取这些指令的过程中评价一个程序关于取指令的局部性。
      - 代码区别与程序数据的一个重要属性就是在运行时指令是不能被修改的。
    
  • 重复引用同一个变量的程序有良好的时间局部性

  • 对于具有步长为k的引用模式的程序,步长越小,空间局部性越好。

  • 对于取指令来说,循环具有良好的时间和空间局部性。循环体越小,迭代次数越多局部性越好。

(3)存储器层次结构

  • 中心思想:每层存储设备都是下一层的“缓存”

      - 缓存命中:当程序需要第k+1层的某个数据对象d时,首先在当前存储的第k层的一个块中查找d,如果d刚好在第k层中,则称为缓存命中。
      - 缓存不命中:如果k层中没有缓存数据d,则称为缓存不命中,此时要从k+1层取出包含d的块,可能会覆盖(替换/驱逐)现在的一个块(牺牲块)。
      - 决定该替换哪个快是缓存的替换策略来控制的。
    
  • 缓存不命中的种类

      - 强制性不命中/冷不命中:第k层缓存是空的(冷缓存),只是短暂的状态,不会在反复访问存储器使得缓存暖身之后的稳定状态出现。
      - 冲突不命中:第k+1层的第i块,必须放置在第k层的块(i mod 4)中,这种限制性的放置策略引起冲突不命中。
    
  • 不命中率:不命中数量/引用数量

  • 命中率:1-不命中率

  • 高速缓存存储器结构

    • 高速缓存的结构用元组(S,E,B,m)来描述,高速缓存的大小C = S * E * B

        - s个组索引位:一个无符号整数,说明字必须存储在哪个组中。
        - t个标记位:组中的哪一行包含这个字。
        - b个块偏移位:在B个字节的数据块中的字偏移。
      

二、实践操作

(一)动态库与静态库

	.c				源码
	.a(.lib)		静态库
	.so(.dll)		动态库

(1)静态库

gcc -c add.c sub.c				编译所用.c文件为.o
ar rcsv libmath.a add.o sub.o	创建math静态库
gcc -o main main.c -L. -lmath	创建可执行文件
./main							运行
  • 参数

      gcc	-c		只编译,不连接成为可执行文件.
      ar	-r		在库中插入模块(替换)
      	-c		创建一个库
      	-s		写入一个目录文件索引到库中
      .L -lmath			在当前目录下查找math库文件
    

(2)动态库(共享库)

gcc -fPIC -Wall -c add.c sub.c			编译
gcc -shared -o libmath.so add.o sub.o	创建math共享库
gcc -o main main.c -L. -lmath			创建可执行文件
./main									运行
  • 参数

      -fPIC	指示编译器生成与位置无关的代码
      -shared 指示链接器创建一个共享的目标文件
    

(二)正则表达式

正则表达式( regular expression,简写为 regexes),是用来操作和检验字符串数据的一种强大工具,是采用某种模式去匹配一类字符串的一个公式。
  • 规则

    • ‘多种字符’ 表达式:正则表达式中的一些表示方法,可以匹配 '多种字符 ' 其中的任意一个字表达符式。

        \d		0~9 中的任意一个数字
        \w		任一字母或数字或下划线,即A~Z、a~z、0~9、_中任一个
        \s		包括空格、制表符、换页符等空白字符中任意一个
        .		匹配除换行符( \n)以外任意一个字符
        [ ]		匹配其中任意字符,但每次匹配只匹配一个
        [^ ]	匹配除其中的任意字符,每次匹配只匹配一个
      
    • 简单的转义字符

        \ 		表示后面的字符本身
      
    • 修饰匹配次数

        {n}		表达式重复n次,如"a{5}" 相当于"aaaaa"
        {m,n}	表达式至少重复m次,最多重复n次,如:"ba{1,3}"可以匹配"ba"或"baa"或"baaa"
        {m,}	表达式至少重复m次,比如:"\w\d{2,}"可以匹配 "a12","_456"等
        ?	表达式出现 0次或者 1次,相当于 {0,1}
        +	表达式至少出现 1次,相当于 {1,}
        *	表达式不出现或出现任意次,相当于{0, }
      
  • 匹配方法

      ^		从字符串开始的地方匹配
      $		从字符串结束的地方匹配
      |		可以匹配左或者右
    
      贪婪模式		尽可能多的匹配
      非贪婪模式	尽可能少的匹配
    

三、自己的收获与不足

1.硬知识、软知识和元知识

  • 本学期课程一开始,老师就提出关于这个这三种知识的观点,我深受启发:

      - 硬知识:学习的知识点,技能,我觉得这是那种可以百度出来的,每次考试都背了很多,一考完就忘的知识。
      - 软知识:通过长期实践中总结和体会出来的东西,我觉得它应该是长期经验形成的一种思维方式。
      - 元知识:知识的知识。我理解它就是一些最基本的、具有高复用性的知识,是对知识的认识方式。
    
  • 进入大学以后,我经常思考到底如何学习,不断地反思自己。联想一下自己一直以来的学习过程,可能之前过于看重对硬知识的记忆,到大学之后,变得越来越力不从心。

  • 我记得上学期学java的时候老师在课堂上曾经说过,很多人学了很久的东西,但是最终还是停留在很熟练的初学者的阶段,甚至还不能算是合格,这句话对我触动很大,我觉得自己之前学的很多东西都是这样,就像office办公软件,如果不是我考MOS、去参加比赛,我可能从来没有想过office里我们最常用的word就有这么多从来没有使用过的功能。

  • 尝试不断改变自己的学习方式,其实就是在不断培养自己形成软知识和元知识的能力。我觉得老师进行课堂改革的本意可能也是如此,各种实践项目和加分项只是督促我们建立这种学习方式的形式而已。

  • 这三种知识的分类,在我的理解应该是对于在学习中如何构建知识框架的指导,是怎样通过已有的知识来把握新知识脉络的方法。这样的思路对我今后的学习,尤其是自学,有很大的帮助。

2.搜索能力

  • “搜商”是一种很重要的能力,在这学期的学习中,这种能力的重要性尤为突出。就拿学习这个markdown来讲,功能了解和操作方法都是百度来的。
  • 在学习Linux命令的时候,老师就强调man、cheat、find......这一系列帮助文档、查找工具的重要性。就像百度一样,在Linux中,有问题就可以去找man,查找东西可以locate,某个命令的man看不懂还可以cheat,尽量通过自己的搜索一步步的解决问题,而不是不动脑子的照搬。
  • 如果完全让我们自己去搜索需要的东西,搞清某个实验的学习目标和实现其主要功能的方法步骤并不容易(比如这学期学习的信息安全概论实验,感觉方向性很不明确,自己提前做实验的时候无从下手,花了很多的时间结果检查的时候老师问的一些问题甚至还没有想到过),感觉娄老师写这么多的学习任务、教材导读、每章重点和实验楼指导真的是非常辛苦。

3.关于读书

  • 刚开始看到厚的教材,我觉得这一个学期肯定不好过,估计每天就光看着这个书时间都不够。但是这几周下来,对于如何阅读每一章节我也有了自己的方法:先看教材导读,再去通篇阅读,从重点习题出发理解相应内容。
  • 但是如果要把每一个点吃透需要更多的时间,不是考点的地方我就囫囵吞枣样的一带而过,导致有些问题还是没有搞清楚。
  • 上学期的汇编我学的很差,结果没想到这本书有很多地方都与之前的汇编有紧密联系,让我学得又吃力又后悔,这就是欠债。相反,我的EDA学得还不错,在HCL的部分感觉就轻松了很多。

四、课程建议和意见

  1. 这个课程刚开始的时候,我觉得任务量还是有些大。虽然我知道Linux老师在上学期java课程中就说过,但是我没有及时的学习,又是有欠债,这确实是我的问题。但是在大多同学都确实都没有接触过的时候,一周做的那12个实验里几乎全都是新知识,当时的重点也没有明确,每天拿出好几个小时去阅读和操作,还卡在一些现在看来都不是问题的问题上,花在写博客上的时间也很多。我觉得现在这种每次有导读和重点的形式就很好。
  2. 加分种类繁多,有些搞不清到底这些加分那些是我必须去做的,只能是能抢到就做。还有那个深化实践类项目是每个人都必须做的吗?刚开始的时候给的是十一那节课没来的人,后来就变成群里抢的了,不太清楚这个到底是属于哪部分的。

参考资料


参考资料1:20135317信息安全系统设计基础第一周学习总结
参考资料2:20135317信息安全系统设计基础第二周学习总结
参考资料3:20135317信息安全系统设计基础第三周学习总结
参考资料4:20135317信息安全系统设计基础第四周学习总结
参考资料5:20135317信息安全系统设计基础第五周学习总结
参考资料6:20135317信息安全系统设计基础第六周学习总结
参考资料7:历次考试答案解析
参考资料8:正则表达式PDF