# 2017-2018-1 20155232 《信息安全系统设计基础》第十一周学习总结
2017-2018-1 20155232 《信息安全系统设计基础》第十一周学习总结
教材学习内容总结
本周学习第9章:
- 虚拟存储器的三个重要能力:
1.它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,高效的使用了主存
2.它为每个进程提供了一致的地址空间,从而简化了存储器管理
3.它保护了每个进程的地址空间不被其他进程破坏
- 物理和虚拟寻址
1.物理寻址
计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组,每字节都有一个唯一的物理地址PA。根据物理地址寻址的是物理寻址。
2.虚拟寻址
使用虚拟寻址时,CPU通过生成一个虚拟地址VA来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址,相关硬件为存储器管理单元MMU。
3.地址翻译
把一个虚拟地址转换为物理地址的任务。需要CPU硬件和操作系统之间的紧密合作。
- Linux虚拟存储器系统
Linux为每个进程维持一个单独的虚拟地址空间:内核虚拟存储器和进程虚拟存储器。内核虚拟存储器包含内核中的代码和数据。
- 作用
允许虚拟地址空间有间隙;内核不用记录那些不存在的页,这样的页也不用占用存储器
-
虚拟存储器:虚拟页VP,每个虚拟页大小为P=2^平字节
-
物理存储器——物理页PP,也叫页帧,大小也为P字节。
-
DRAM缓存的组织结构
1.不命中处罚很大
2.是全相联的——任何虚拟页都可以放在任何的物理页中。
3.替换算法精密
4.总是使用写回而不是直写。
-
页表:是一个数据结构,存放在物理存储器中,将虚拟页映射到物理页,就是一个页表条目的数组。
-
Linux缺页异常处理
MMU在试图翻译虚拟地址A时,触发缺页。这个异常导致控制转移到缺页处理程序,执行如下步骤:
缺页处理程序搜索区域结构链表。把A和每个区域的vm_start和vm_end做比较。如果不合法,触发段错误。
- fork函数
当fork函数被当前进程调用时:
内核为新进程创建内核数据结构,并分配给它唯一一个PID。
为新进程创建虚拟存储器。
- execve函数:使用execve函数将a.out程序加载到存储器的过程
具体的步骤如下:
删除已存在的用户区域。
映射私有区域。
映射共享区域。
设置程序计数器。
-
mmap函数
-
可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域中 mmap();
-
munmap函数删除虚拟存储器的区域 munmap()。
-
动态存储器分配
-
显示分配器-malloc和free
-
隐式分配器/垃圾收集器
-
系统调用malloc函数,从堆中分配块
-
系统调用free函数来释放已分配的堆块:
-
垃圾收集器是一种动态存储分配器。,自动释放程序已经不再需要的已分配块(垃圾)。
-
Mark&Sweep垃圾收集器
-
C程序中常见的与存储器有关的错误
间接引用坏指针:scanf错误
读未初始化的存储器:假设堆存储器被初始化为0
允许栈缓冲区溢出:缓冲区溢出错误
假设指针和它们指向的对象是相同大小的
造成错位错误
引用指针,而不是它所指向的对象
误解指针运算
引用不存在的变量
引用空堆块中的数据
引起存储器泄露
教材学习中的问题和解决过程
-
段错误的几种典型有什么?如何解决?
-
解决:
在编程中以下几类做法容易导致段错误,基本上是错误地使用指针引起的。
1)访问系统数据区,尤其是往系统保护的内存地址写数据最常见就是给一个指针以0地址。
2)内存越界(数组越界,变量类型不一致等): 访问到不属于你的内存区域。
段错误产生的原因
1.访问不存在的内存地址
#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = NULL;
*ptr = 0;
}
2.访问系统保护的内存地址
#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = (int *)0;
*ptr = 100;
}
3.访问只读的内存地址
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char *ptr = "test";
strcpy(ptr, "TEST");
}
4.栈溢出
#include<stdio.h>
#include<stdlib.h>
void main()
{
main();
}
- 段错误的调试方法
1.使用printf输出信息
这个是看似最简单但往往很多情况下十分有效的调试方式,也许可以说是程序员用的最多的调试方式。简单来说,就是在程序的重要代码附近加上像printf这类输出信息,这样可以跟踪并打印出段错误在代码中可能出现的位置。
为了方便使用这种方法,可以使用条件编译指令#ifdef DEBUG和#endif把printf函数包起来。这样在程序编译时,如果加上-DDEBUG参数就能查看调试信息;否则不加该参数就不会显示调试信息。
2.使用gcc和gdb
3.使用core文件和gdb
4.使用objdump
- 使用catchsegv
具体的解决步骤参考
- 内存泄露和内存溢出有何不同?
- 内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。有人比喻是“操作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以“内存泄漏”是从操作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。
- 内存溢是指在一个域中输入的数据超过它的要求而且没有对此作出处理引发的数据溢出问题,多余的数据就可以作为指令在计算机上运行。通常在运行大型软件或游戏时,软件或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。此时软件或游戏就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件或游戏一段时间。
代码调试中的问题和解决过程
本周暂无代码调试问题
代码托管
上周考试错题总结
无
结对及互评
点评模板:
暂无
本周结对学习情况
-
- 结对学习内容
- 共同学习课本9章和实验楼内容
- 分析课本中代码遇到的问题
- 结对学习内容
思考
本次的内容是学习第九章,这周内容有点难理解,看完最后一节C程序中常见的与存储器有关的错误,看完之后觉得似曾相识,之前编程过程中就遇到很多类似的问题,每次都不知道是社么原因导致的,直接复制错误信息,搜索然后解决,现在大致能弄懂是什么原因引起的错误了。下次编代码遇到类似的错误时就能够更好的解决这些问题。
学习进度条
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第四周 | 12/12 | 1/1 | 20/20 | |
第五周 | 271/283 | 1/2 | 15/15 | |
第6周 | 276/283 | 2/3 | 18/18 | |
第7周 | 150/283 | 4/4 | 21/23 | |
第8周 | 294/283 | 4/4 | 24/27 | |
第9周 | 289/283 | 4/4 | 29/23 | |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。 | ||||
耗时估计的公式 | ||||
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。 |
-
计划学习时间:23小时
-
实际学习时间:29小时
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)