深入理解计算机系统LAB2
- 格式:docx
- 大小:112.27 KB
- 文档页数:12
操作系统lab2实验报告实验目的:本实验的目的是通过设计和实现一个简单的操作系统内核,加深对操作系统基本概念和原理的理解。
具体实验内容包括进程管理、内存管理和文件系统的设计与实现。
实验环境:1.操作系统:Linux2.编程语言:C语言一、实验背景1.1 操作系统简介操作系统是计算机系统中的一个重要组成部分,负责管理和控制计算机的各种资源,提供用户和应用程序的接口,以及协调和调度各种任务的执行。
1.2 实验目标本实验的主要目标是设计和实现一个简单的操作系统内核,包括进程管理、内存管理和文件系统等功能。
二、实验内容2.1 进程管理①进程创建描述进程创建的过程和相关数据结构,包括创建新进程的系统调用、进程控制块等。
②进程调度描述进程调度的算法和实现方式,包括进程调度队列、调度算法等。
③进程同步与通信描述进程同步和通信的机制和方法,包括信号量、互斥锁、条件变量等。
2.2 内存管理①内存分配描述内存分配的算法和实现方式,包括连续内存分配、非连续内存分配等。
②页面置换描述页面置换的算法和实现方式,包括最优页面置换算法、先进先出页面置换算法等。
2.3 文件系统①文件操作描述文件操作的系统调用和相关数据结构,包括文件打开、读写、关闭等。
②文件系统结构描述文件系统的组织结构和实现方式,包括超级块、索引节点、块位图等。
三、实验步骤3.1 环境搭建搭建实验环境,包括安装Linux操作系统、编译器等。
3.2 进程管理实现根据设计要求,实现进程创建、调度、同步与通信等功能。
3.3 内存管理实现根据设计要求,实现内存分配、页面置换等功能。
3.4 文件系统实现根据设计要求,实现文件操作和文件系统结构。
3.5 测试与调试编写测试用例,对实现的操作系统内核进行测试和调试,并记录实验结果。
四、实验结果分析分析测试结果,评估实验过程中遇到的问题和解决方法,总结操作系统内核的性能和功能特点。
五、实验总结对实验过程中的收获和经验进行总结,提出改进和优化的建议。
深⼊理解计算机系统第⼆版习题解答CSAPP2.13
从20世纪70年代末到80年代末,Digital Equipment的VAX计算机是⼀种⾮常流⾏的机型。
它没有布尔运算AND和OR指令,只有bis(位设置)和bic(位清除)这两种指令。
两种指令的输⼊都是⼀个数据字x和⼀个掩码字m。
它们⽣成⼀个结果z,z是由根据掩码m的位来修改x的位得到的。
使⽤bis指令,这种修改就是在m为1的每个位置上,将z对应的位设置为1。
使⽤bic指令,这种修改就是在m为1的每个位置,将z对应的位设置为0。
只使⽤这两个函数实现C语⾔的按位|和^运算。
1int bis(int x, int m);
2int bic(int x, int m);
3
4int bool_or(int x, int y)
5 {
6int result = bis(x, y);
7return result;
8 }
9
10int bool_xor(int x, int y)
11 {
12int result = bis(bic(x, y), bic(y, x));
13return result;
14 }。
LAB1实验报告语法检查:正确性检查:1.bitAnd源代码:return ~(~x|~y);思路:可以直接运用摩尔定律,写出与的等价形式。
2.getByte源代码:return (x>>(n<<3))&0xff;思路:向右移动3n位,再用11111111B按位与,截取出所需要的字节3.logicalShift源代码:int logic=~(((1<<31)>>n)<<1);return logic&(x>>n);思路:设置一个变量logic,并通过算数移位将其前n为设置成0,后面32-n位设置为1。
利用这个变量按位与移位后的x即可。
4.bitCount源代码:int bitCount(int x) {int result;int half_one=(0x55)|(0x55<<8);int one=(half_one)|(half_one<<16);int half_two=(0x33)|(0x33<<8);int two=(half_two)|(half_two<<16);int half_three=(0x0f)|(0x0f<<8);int three=(half_three)|(half_three<<16);int four=(0xff)|(0xff<<16);int five=(0xff)|(0xff<<8);result=(x&one)+((x>>1)&one);result=(result&two)+((result>>2)&two);result=(result+(result>>4))&three;result=(result+(result>>8))&four;result=(result+(result>>16))&five;return result;}思路:主要还是使用二分法,通过以为设置五个字符串:010101010101010101010101 0101 01010011 0011 0011 0011 0011 0011 0011 00110000 1111 0000 1111 0000 1111 0000 11110000 0000 1111 1111 0000 0000 1111 11110000 0000 0000 0000 1111 1111 1111 1111分别通过按位与统计1的个数,并将个数记录在下一个字符串1出现的位置。
实验二报告一、实验内容根据实验文件里的提示,补充15段代码,熟悉对整型和浮点型数的操作,并成功调试运行。
二、实验程序解释1.bitAnd要求只运用~和|符号实现and的功能。
a and b=not(not a or not b),根据德摩根律易得结果。
int bitAnd(int x, int y) {return ~(~x|~y);}2.getByte得到x的第n个字节的值,规定其中x的最低位为第0个字节,最高位为第3个字节。
如果是第0个字节,将x右移0个字节再利用掩码0xFF将高位的三个字节置为0。
如果是求第1个字节,将x右移1个字节,同理利用掩码。
可以知道,将x右移n个字节也就是n*8位、即(n<<3)位。
接下来清除前三个高位字节,保留最低字节的信息,与0xFF进行&运算。
int getByte(int x, int n) {int t;t=x>>(n<<3);t=t&0xFF;return t;}3.LogicalShift逻辑右移是将移动后补充的高位置0,而算数右移时补充的和符号位相同。
对于字x,需要进行逻辑右移n位。
将x用sxxxxxxx表示,s为符号位,算术右移n-1位的结果为ss…sxx..(有n个s)。
想要得到的结果是00…xxx..(n个0),所以如果能得到s’s’…s’111..(n个s’)的话,按位与就能得到结果。
首先提取符号位t,1左移31位得到100..00,与x进行按位与操作得到s000..0,接着算术右移n位,得到ss..s00..00(n+1个s),再左移1位,得到s..s0..0(n个s),取反得到s’s’..s’111..1。
这样就能得到逻辑右移n位的结果了。
注意,在得到s’s’…111的过程中,不能直接将s00.. 0右移n-1位,考虑特殊情况,n为0时,右移-1位是不正确的。
int logicalShift(int x, int n) {int t=(1<<31)&x;t=~((t>>n)<<1);t=(x>>n)&t;return t;}4.bitCount要求计算32位二进制数x中1个个数。
深⼊理解计算机系统(CSAPP)课后实验CSAPPLAB1——DataLab实验说明《深⼊理解计算机系统》是卡内基梅隆⼤学计算机专业的计算机体系课程的标配教材,可以在B站看其配套⽹课()。
课程由书的作者两个⼈共同执教,⽐较适合有C语⾔的基础的同学作为计算机体系构建的课程。
但是,仅仅看书收获还是有限的,所以为了加强Coding,⽽不是纸上谈兵,还需要做这本书配套的实验,全书总共9个实验,本次讲解Lab1。
实验条件准备实验环境使⽤Ubuntu,为了减少环境搭建成本,我们使⽤虚拟机来进⾏。
我之前⽤过VMWare,但感觉不是很舒服,⽽且还要找破解版⽐较⿇烦。
所以,这次使⽤VituralBox,这是开源的虚拟机,免费,⾜够实验使⽤。
虚拟机环境搭建⾸先,去VituralBox官⽹下载虚拟机安装包(),⼀般是Windows的吧,如果想下载其他版本的,点这个。
下载完毕,管理员权限安装,⼀路点Next就好了。
按照⼀般配置虚拟机的套路,我们应该去Ubuntu之类的官⽹下载系统镜像来进⾏安装。
但实际上,这个步骤可以省⼀省,直接去下载⼈家配置好环境的虚拟机镜像就好,⼀键配置妙不妙呀~我这⾥是⽤之前下载的⼀个清华操作系统课程提供的系统镜像(),⾥⾯已经配置好了,虚拟机的管理员密码是1个空格,⼀般提⽰输密码就输这个下载好镜像之后解压缩,注意,这个压缩包格式是.xz(某明星),这⾥实测WINRAR和BANDZIP可以解压,其他的没测试过。
解压之后是⼀个6G多的.vdi⽂件,在硬盘⾥新建⼀个⽂件夹,把.vdi⽂件拖进去。
然后打开VituralBox,点击创建,系统类型选择Linux,Ubuntu64位,给虚拟机起个名字,然后选择刚刚新的⽂件夹作为虚拟机⽬录,点下⼀步。
现在是选择内存⼤⼩,随意,⼤点没那么卡,⼩点可以同时开多⼏个,建议2GB以上,再下⼀步。
选择⽤已有的虚拟硬盘⽂件,然后打开⽬录,选中刚刚那个.vdi⽂件,点击创建。
操作系统lab2实验报告操作系统 Lab2 实验报告一、实验目的本次实验着重学习操作系统内存管理的相关概念和技术,包括页表的建立和管理,以及虚拟内存系统的实现和优化。
通过完成本实验,我们能够加深对操作系统内存管理机制的理解,并掌握相关的实现方法。
二、实验环境本次实验使用的实验环境为 Linux 操作系统(具体版本号)、GCC 编译器(具体版本号)以及所提供的模拟器。
三、实验内容本次实验主要包括以下几个任务:1. 理解虚拟内存和物理内存的概念,掌握页表的结构和管理方法。
2. 编写代码实现一个简单的页表建立和管理的模拟器,包括页表的初始化、地址映射和页表的更新。
3. 实现一个简单的虚拟内存系统,包括页的加载、替换等操作。
4. 对实现的虚拟内存系统进行性能优化,包括缓存算法的改进、预加载等策略的应用。
四、实验步骤及结果1. 理解虚拟内存和物理内存的概念在本次实验中,我们将使用虚拟内存系统来管理进程的地址空间。
虚拟内存是操作系统提供给进程的一种抽象概念,它为每个进程提供了一个独立的、连续的地址空间。
物理内存是实际存在的计算机内存,由物理地址组成。
2. 编写页表管理模拟器代码根据实验要求,我们需要编写代码模拟页表的建立和管理过程。
首先,我们需要实现页表的初始化函数,用于初始化页表的数据结构。
接着,我们需要实现地址映射函数,用于将虚拟地址映射到物理地址。
最后,我们需要实现页表的更新函数,用于更新页表中的相关信息。
3. 实现虚拟内存系统在本次实验中,我们需要实现一个简单的虚拟内存系统。
虚拟内存系统可以将虚拟地址映射到物理地址,并且可以实现页的加载和替换操作。
我们需要实现页面加载函数,用于将页面加载到内存中。
同时,我们还需要实现页面替换函数,当内存空间不足时,根据特定的算法选择待替换的页,并将其移出内存。
4. 性能优化为了提高虚拟内存系统的性能,我们可以采用一些优化策略。
例如,我们可以改进缓存算法,通过提前缓存一些可能会被访问的页面,减少缺页次数。
LAB1实验报告实验目的:使用课程知识拆除一个“Binary Bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。
实验简介:一个“Binary Bombs”(二进制炸弹,简称炸弹)是一个Linux可执行C程序,包含phase1~phase6共6个阶段。
炸弹运行各阶段要求输入一个字符串,若输入符合程序预期,该阶段炸弹被“拆除”,否则“爆炸”。
实验目标是你需要拆除尽可能多的炸弹。
运行结果:通关密码储存在0014301-151420131.txt文件中。
成功运行结果截图:实验中的六组密码:PHASE1:字符串比较本关比较简单,根据课件中的提示用GDB将最先压栈的那个字符串常量打印出来,然后将其作为密码输入,比较成功后即通关。
08048ab2 <phase_1>:8048ab2: 83 ec 14 sub $0x14,%esp8048ab5: 68 04 9f 04 08 push $0x8049f048048aba: ff 74 24 1c pushl 0x1c(%esp)8048abe: e8 4d 04 00 00 call 8048f10 <strings_not_equal> 将地址0x8049f04中的值打印出来:即“The future will be better tomorrow.”PHASE2:循环在查看汇编语言的时候,会看到有调用一个read_six_number函数,猜测此题是让输入六个数字。
08048ad3 <phase_2>:8048ad3: 56 push %esi8048ad4: 53 push %ebx8048ad5: 83 ec 2c sub $0x2c,%esp8048ad8: 8d 44 24 10 lea 0x10(%esp),%eax8048adc: 50 push %eax8048add: ff 74 24 3c pushl 0x3c(%esp)8048ae1: e8 46 05 00 00 call 804902c <read_six_numbers>8048ae6: 83 c4 10 add $0x10,%esp8048ae9: 83 7c 24 08 01 cmpl $0x1,0x8(%esp)------→判定是否为1 8048aee: 74 1e je 8048b0e <phase_2+0x3b>8048af0: e8 12 05 00 00 call 8049007 <explode_bomb>8048af5: eb 17 jmp 8048b0e <phase_2+0x3b>8048af7: 8b 03 mov (%ebx),%eax8048af9: 01 c0 add %eax,%eax----→进行自加,扩大两倍 8048afb: 39 43 04 cmp %eax,0x4(%ebx)8048afe: 74 05 je 8048b05 <phase_2+0x32>8048b00: e8 02 05 00 00 call 8049007 <explode_bomb>8048b05: 83 c3 04 add $0x4,%ebx8048b08: 39 f3 cmp %esi,%ebx8048b0a: 75 eb jne 8048af7 <phase_2+0x24>8048b0c: eb 0a jmp 8048b18 <phase_2+0x45>8048b0e: 8d 5c 24 08 lea 0x8(%esp),%ebx8048b12: 8d 74 24 1c lea 0x1c(%esp),%esi8048b16: eb df jmp 8048af7 <phase_2+0x24>→循环8048b18: 83 c4 24 add $0x24,%esp8048b1b: 5b pop %ebx8048b1c: 5e pop %esi8048b1d: c3 ret有汇编语言进行分析,不难看出,这道题目要求输入六个数字,并且要求第一个数字为1,之后跳入一个循环,将第一个数字加倍和已有的数字进行比较,所以不难看出所需要的密码是1,2,4,8,16,32这六个数字。
PHASE3:条件分支语句这道题的汇编语句明显变长了,但是由于PPT中已经提示这是条件分支语句,以此为切入点,此题也不难分析。
08048b1e <phase_3>:8048b1e: 83 ec 1c sub $0x1c,%esp8048b21: 8d 44 24 08 lea 0x8(%esp),%eax8048b25: 50 push %eax8048b26: 8d 44 24 10 lea 0x10(%esp),%eax8048b2a: 50 push %eax8048b2b: 68 0f a1 04 08 push $0x804a10f→打印该值为”%d%d”8048b30: ff 74 24 2c pushl 0x2c(%esp)8048b34: e8 87 fc ff ff call 80487c0 <__isoc99_sscanf@plt> 上面这一段调用了一个函数sscanf(),查询可知这个函数的原型为:int sscanf(const char *buffer,const char *format,[argument ]...);即读取输入的字符串,并以指定的格式赋给参数。
其中一个参数在地址0x804a10f中。
可知需要输入两个整数。
8048b39: 83 c4 10 add $0x10,%esp8048b3c: 83 f8 01 cmp $0x1,%eax8048b3f: 7f 05 jg 8048b46 <phase_3+0x28>8048b41: e8 c1 04 00 00 call 8049007 <explode_bomb>8048b46: 83 7c 24 0c 07 cmpl $0x7,0xc(%esp)---------→不大于78048b4b: 77 66 ja 8048bb3<phase_3+0x95>-→否则引爆有这些可以得知第一个参数的信息,可以看出这是一个不大于7的数,因此缩小了选择,不难猜出可能是分支条件。
8048b4d: 8b 44 24 0c mov 0xc(%esp),%eax8048b51: ff 24 85 80 9f 04 08 jmp *0x8049f80(,%eax,4)8048b58: b8 0c 03 00 00 mov $0x30c,%eax8048b5d: eb 05 jmp 8048b64 <phase_3+0x46>8048b5f: b8 00 00 00 00 mov $0x0,%eax8048b64: 2d d5 03 00 00 sub $0x3d5,%eax8048b69: eb 05 jmp 8048b70 <phase_3+0x52>8048b6b: b8 00 00 00 00 mov $0x0,%eax8048b70: 05 35 01 00 00 add $0x135,%eax8048b75: eb 05 jmp 8048b7c <phase_3+0x5e>8048b77: b8 00 00 00 00 mov $0x0,%eax8048b7c: 2d e9 02 00 00 sub $0x2e9,%eax8048b81: eb 05 jmp 8048b88 <phase_3+0x6a>8048b83: b8 00 00 00 00 mov $0x0,%eax8048b88: 05 e9 02 00 00 add $0x2e9,%eax8048b8d: eb 05 jmp 8048b94 <phase_3+0x76>8048b8f: b8 00 00 00 00 mov $0x0,%eax8048b94: 2d e9 02 00 00 sub $0x2e9,%eax8048b99: eb 05 jmp 8048ba0 <phase_3+0x82>8048b9b: b8 00 00 00 00 mov $0x0,%eax8048ba0: 05 e9 02 00 00 add $0x2e9,%eax8048ba5: eb 05 jmp 8048bac <phase_3+0x8e>8048ba7: b8 00 00 00 00 mov $0x0,%eax8048bac: 2d e9 02 00 00 sub $0x2e9,%eax8048bb1: eb 0a jmp 8048bbd <phase_3+0x9f>8048bb3: e8 4f 04 00 00 call 8049007 <explode_bomb> 上面是各种分支情况,看起来比较复杂,先放一放8048bb8: b8 00 00 00 00 mov $0x0,%eax8048bbd: 83 7c 24 0c 05 cmpl $0x5,0xc(%esp)--- 参数不能大于58048bc2: 7f 06 jg 8048bca <phase_3+0xac>8048bc4: 3b 44 24 08 cmp 0x8(%esp),%eax8048bc8: 74 05 je 8048bcf <phase_3+0xb1>8048bca: e8 38 04 00 00 call 8049007 <explode_bomb>8048bcf: 83 c4 1c add $0x1c,%esp8048bd2: c3 ret可以看出参数不能大于五,因此这道题可能有多组解,不过结合分支语句,不难看出当第一个参数比较大的时候,计算量比较小,所以我选择了第一个参数为5,代入进行逐步计算,可以得到此时的值为-745。
PHASE4:递归调用栈这一步是递归调用栈,所以有两部分汇编代码,其中一个是被调用的函数,简单地看一下代码,应该是一个递归的函数。
先分析主程序部分的代码,其中也有sscanf函数:08048c2c <phase_4>:8048c2c: 83 ec 1c sub $0x1c,%esp8048c2f: 8d 44 24 08 lea 0x8(%esp),%eax8048c33: 50 push %eax8048c34: 8d 44 24 10 lea 0x10(%esp),%eax8048c38: 50 push %eax8048c39: 68 0f a1 04 08 push $0x804a10f---→输出为”%d%d”8048c3e: ff 74 24 2c pushl 0x2c(%esp)8048c42: e8 79 fb ff ff call 80487c0 <__isoc99_sscanf@plt>8048c47: 83 c4 10 add $0x10,%esp8048c4a: 83 f8 02 cmp $0x2,%eax----→返回值为2 从上面这部分看出我们需要输入两个参数,且两个都是整数型的。