清华大学操作系统lab1_实验报告
操作系统实验lab1

实验一 Linux系统的基本操作1.目的要求熟悉Linux系统运行环境,掌握Linux操作系统上的基本操作。
2、实验内容1)登录Linux系统和使用GNOMEa)在启动系统,登陆进入系统后,桌面上有3个图标,它们的名字和作用是什么?它们和windows系统的什么软件功能相当?(1)名字:计算机作用:为用户提供管理计算机的接口,和windows的我的电脑作用相同。
(2)名字:Root的主文件夹作用:为当前的用户提供保存资料。
它和windows的我的文档作用相同。
(3)名字:回收站作用:存放用户所删除的文件它和windows的回收站作用相同b)在屏幕的最下方,有一个快捷栏,其中有哪些图标,它们的名字和作用是什么?它们和windows系统的什么软件功能相当?A.Hard disk(硬盘)作用:用于存储数据,文件等;和windows 磁盘功能相当work adapter(网络适配器) 作用:用于建立网络连接;和windows inode 功能相当C.Sound card(声卡) 作用:用于调节音量;和windows 音量控制器功能相当D.Printer (打印机) 作用:用于输出数据的打印;和windows 打印机功能相当E.Genesys logic USB storage( USB 插件) 作用:管理即插即用设备;和windowsUSB硬件功能相当F.Message log(信息记录) 作用:用于提醒用户系统消息;和windows 消息提醒功能相当2)Linux系统的基本命令a)列举打开Linux终端的两种方式,分别叙述其过程单击applications,选择accessories,再选择terminal单击右键,选择terminalb) 使用PWD命令可以查看用户当前所处的工作目录,你的工作目录是DIRb)使用______MORE___________命令可以查看当前文件夹的内容c)分别键入命令who,man date,cal5,exit解释各个命令具体实现的功能A.who指令显示了当前登陆在该机器上的所有用户的列表B.man date指令用来查看系统中关于date命令的使用说明C.cal 5命令:日历命令,显示本年12个月日历D.exit命令:退出终端3)Linux系统的文件、目录和权限a)查询当前用户所处的位置使用pwd命令b)在当前文件夹下创建一个名为os的文件夹Mkdir osc)使os目录成为当前目录Cd osd)创建一个名为file.c的文本文件,该文件放置在文件夹os中Cd os cat>file.ce)把file.c文件拷贝到用户主目录中(登陆进系统时所处的目录),文件名不变Cp /root/gaoting/file.c/root/file.cf)把主目录中的file.c文件更名为source.cMv –l file.c source.cg)返回到主目录Cd /h)使用命令"ls –l",其显示内容是什么?对各列内容进行解释?Drwxr-xr 2 gaoting gaoting 4096 mar 26 2011 desktop文件类型权限链接数所属用户所属组文件大小创建时间文件名i)删除文件夹osRm –rf osj)删除当前目录下所有以source开始的文件Rm source.*4)Linux通配符的使用。
操作系统实验实验报告

操作系统实验实验报告一、实验目的操作系统是计算机系统中最为关键的核心软件,它管理着计算机的硬件资源和软件资源,为用户提供了一个方便、高效、稳定的工作环境。
本次操作系统实验的目的在于通过实际操作和实践,深入理解操作系统的基本原理和核心概念,掌握操作系统的基本功能和操作方法,提高对操作系统的认识和应用能力。
二、实验环境本次实验使用的操作系统为 Windows 10 专业版,开发工具为Visual Studio 2019,编程语言为 C 和 C++。
实验硬件环境为一台配备Intel Core i7 处理器、16GB 内存、512GB SSD 硬盘的个人计算机。
三、实验内容(一)进程管理实验1、进程创建与终止通过编程实现创建新的进程,并在完成任务后终止进程。
在实验中,我们使用了 Windows API 函数 CreateProcess 和 TerminateProcess 来完成进程的创建和终止操作。
通过观察进程的创建和终止过程,深入理解了进程的生命周期和状态转换。
2、进程同步与互斥为了实现进程之间的同步与互斥,我们使用了信号量、互斥量等同步对象。
通过编写多线程程序,模拟了多个进程对共享资源的访问,实现了对共享资源的互斥访问和同步操作。
在实验中,我们深刻体会到了进程同步与互斥的重要性,以及不正确的同步操作可能导致的死锁等问题。
(二)内存管理实验1、内存分配与释放使用 Windows API 函数 VirtualAlloc 和 VirtualFree 进行内存的分配和释放操作。
通过实验,了解了内存分配的不同方式(如堆分配、栈分配等)以及内存释放的时机和方法,掌握了内存管理的基本原理和操作技巧。
2、内存分页与分段通过编程模拟内存的分页和分段管理机制,了解了内存分页和分段的基本原理和实现方法。
在实验中,我们实现了简单的内存分页和分段算法,对内存的地址转换和页面置换等过程有了更深入的理解。
(三)文件系统实验1、文件操作使用 Windows API 函数 CreateFile、ReadFile、WriteFile 等进行文件的创建、读取和写入操作。
操作系统 实验报告

操作系统实验报告操作系统实验报告引言:操作系统是计算机系统中最重要的软件之一,它负责管理计算机硬件资源,并提供程序运行环境。
操作系统的设计和实现是计算机科学领域的重要研究方向之一。
本篇实验报告将介绍我们在操作系统实验中所进行的实践和实验结果。
一、实验目的我们的实验目的是通过实践操作系统的基本功能,深入理解操作系统的原理和实现方式。
具体来说,我们的实验目标包括:1. 学习并掌握操作系统的基本概念和原理;2. 理解操作系统与硬件之间的交互过程;3. 实践操作系统的进程管理、内存管理和文件系统等功能;4. 分析操作系统的性能和优化策略。
二、实验环境我们使用了一台配置较高的计算机作为实验环境,该计算机配备了一块主频为2.5GHz的多核处理器、8GB内存和500GB硬盘。
我们选择了一款常见的操作系统作为实验平台,以便于进行实验和调试。
三、实验过程1. 进程管理在进程管理实验中,我们实现了进程的创建、调度和终止等功能。
首先,我们编写了一个简单的程序,用于创建多个进程并进行调度。
然后,我们通过观察进程的执行顺序和时间片分配情况,分析操作系统的调度算法对系统性能的影响。
2. 内存管理在内存管理实验中,我们实现了内存的分配和回收等功能。
我们编写了一个模拟程序,用于模拟内存的分配和释放过程。
通过观察内存分配的效率和内存碎片的情况,我们评估了不同的内存管理算法的性能。
3. 文件系统在文件系统实验中,我们实现了文件的创建、读写和删除等功能。
我们编写了一个简单的文件操作程序,用于测试文件系统的性能和可靠性。
通过观察文件系统的读写速度和文件恢复的效果,我们评估了不同的文件系统实现方式的优劣。
四、实验结果通过实验,我们获得了以下结果:1. 进程管理实验中,我们发现不同的调度算法对系统性能的影响差异较大。
短作业优先算法在短时间内能够提高系统的响应速度,而时间片轮转算法则能够保证公平性。
2. 内存管理实验中,我们发现不同的内存管理算法对内存利用率和碎片情况有很大的影响。
《操作系统》课内实验报告

《操作系统》课内实验报告一、实验目的本次《操作系统》课内实验的主要目的是通过实际操作和观察,深入理解操作系统的基本原理和功能,掌握常见操作系统命令的使用,提高对操作系统的实际应用能力和问题解决能力。
二、实验环境本次实验在计算机实验室进行,使用的操作系统为 Windows 10 和Linux(Ubuntu 发行版)。
实验所使用的计算机配置为:Intel Core i5 处理器,8GB 内存,500GB 硬盘。
三、实验内容1、进程管理在 Windows 系统中,通过任务管理器观察进程的状态、优先级、CPU 使用率等信息,并进行进程的结束和优先级调整操作。
在 Linux 系统中,使用命令行工具(如 ps、kill 等)实现相同的功能。
2、内存管理使用 Windows 系统的性能监视器和资源监视器,查看内存的使用情况,包括物理内存、虚拟内存的占用和分配情况。
在 Linux 系统中,通过命令(如 free、vmstat 等)获取类似的内存信息,并分析内存的使用效率。
3、文件系统管理在 Windows 系统中,对文件和文件夹进行创建、复制、移动、删除等操作,了解文件的属性设置和权限管理。
在 Linux 系统中,使用命令(如 mkdir、cp、mv、rm 等)完成相同的任务,并熟悉文件的所有者、所属组和权限设置。
4、设备管理在 Windows 系统中,查看设备管理器中的硬件设备信息,安装和卸载设备驱动程序。
在 Linux 系统中,使用命令(如 lspci、lsusb 等)查看硬件设备,并通过安装内核模块来支持特定设备。
四、实验步骤1、进程管理实验(1)打开 Windows 系统的任务管理器,切换到“进程”选项卡,可以看到当前系统中正在运行的进程列表。
(2)选择一个进程,右键点击可以查看其属性,包括进程 ID、CPU 使用率、内存使用情况等。
(3)通过“结束任务”按钮可以结束指定的进程,但要注意不要随意结束系统关键进程,以免导致系统不稳定。
操作系统--实验一实验报告

操作系统课程实验指导书【实验名称】:并发程序设计(实验1)【实验目的】:掌握在程序中创建新进程的方法,观察并理解多道程序并发执行的现象。
【实验原理】:fork():建立子进程。
子进程得到父进程地址空间的一个复制。
返回值:成功时,该函数被调用一次,但返回两次,fork()对子进程返回0,对父进程返回子进程标识符(非0值)。
不成功时对父进程返回-1,没有子进程。
【实验内容】:首先分析一下程序运行时其输出结果有哪几种可能性,然后实际调试该程序观察其实际输出情况,比较两者的差异,分析其中的原因。
void main (void){ int x=5;if( fork( ) ){x+=30;printf (“%d\n”,x);}elseprintf(“%d\n”,x);printf((“%d\n”,x);}【实验要求】:每个同学必须独立完成本实验、提交实验报告、源程序和可执行程序。
实验报告中必须包含预计的实验结果,关键代码的分析,调试记录,实际的实验结果,实验结果分析等内容。
【预计的实验结果】355355【关键代码分析】1,这个实验代码只有几行,看起来很简单。
可以看到,重点就是fork()函数和一个if else 条件分支语句。
2,关于fork()函数,它是Linux的系统调用。
函数定义:int fork( void );返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1函数说明:一个现有进程可以调用fork函数创建一个新进程。
由fork创建的新进程被称为子进程(child process)。
fork函数被调用一次但返回两次。
两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。
注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间,它们之间共享的存储空间只有代码段。
3,如果不知道fork()函数的作用的话,一定会对为什么会有两组输出结果感到疑惑。
OS-lab1实验报告

OS-lab1实验报告lab1实验报告⼀、实验思考题Thinking 1.1也许你会发现我们的readelf程序是不能解析之前⽣成的内核⽂件(内核⽂件是可执⾏⽂件)的,⽽我们之后将要介绍的⼯具readelf则可以解析,这是为什么呢?(提⽰:尝试使⽤readelf -h,观察不同)答:通过readelf -h读取vmlinux和testELF的结果如下图所⽰:vmlinux:testELF:从Data属性⼀栏中可以看到vmlinux为⼤端存储⽽testELF为⼩端存储,我们的readelf程序只能对⼩端存储进⾏解析,所以⽆法解析内核⽂件。
Thinking 1.2内核⼊⼝在什么地⽅?main 函数在什么地⽅?我们是怎么让内核进⼊到想要的 main 函数的呢?⼜是怎么进⾏跨⽂件调⽤函数的呢?答:内核⼊⼝在0x8000_0000,main函数在0x8001_0000。
通过执⾏跳转指令jal跳转到main函数。
跨⽂件调⽤函数时,会先将需要的参数保存在寄存器a0-a3中,然后执⾏跳转指令跳转⾄函数执⾏,将返回值保存在寄存器v0-v1中。
⼆、实验难点图⽰本次实验中⽐较难的地⽅,我认为是如何读懂已有的代码。
⽐如对于Exercise 1.2,如果不提前仔细了解ELF的⽂件⼤体结构。
乍⼀看kerelf.h的代码是很迷茫的。
这样“冗长”的⼀个结构体到底是什么意思,结构体中的各个变量代表着什么属性,只有结合注释和理论的知识才能理解,从⽽加以运⽤。
对于Exercise 1.5,这⼀点就更加明显了。
想要完成Exercise 1.5,需要阅读三个代码⽂件,了解printf函数的具体实现过程,需要了解这三个⽂件之中与printf实现相关的函数功能以及具体实现⽅法,⽐如printf.c中的myoutput函数和printf函数,这两个函数与我们需要补写的内容密切相关。
了解了这两个函数之后再去读print.c的函数内容,才能⽐较好的理解lp_Print函数的具体实现过程。
操作系统 (第一个实验)

操作系统实验报告哈尔滨工程大学计算机科学与技术学院第一讲实验环境的使用一、实验概述1. 实验名称实验环境的使用2. 实验目的(1)熟悉操作系统集成实验环境OS Lab的基本使用方法。
(2)练习编译、调试EOS操作系统内核以及EOS应用程序。
3. 实验类型(验证、设计)验证型实验4. 实验内容(1)学习OS Lab的基本使用方法;(2)EOS内核项目的生成和调试;(3)EOS应用程序项目的生成和调试。
二、实验环境EOS操作系统和OS Lab集成实验环境,主要运用了C语言。
三、实验过程1.源程序并附上注释/* 定义控制台应用程序的入口点*/#include "console.h"int main(int argc, char* argv[]){/* TODO: 在此处添加自己的代码*/int Func(int n); //声明Func()函数int n=0;n=Func(10); //调用Func()函数printf("Hello world!\n"); //输出return 0;}int Func(int n) //定义Func()函数{n=n+1;return n;}2.程序运行时的初值和运行结果(1)启动OS Lab在安装有OS Lab的计算机上,可以使用两种不同的方法来启动OS Lab:在桌面上双击“Tevation OS Lab”图标;或者点击“开始”菜单,在“程序”中的“Tevation OS Lab”中选择“Tevation OS Lab”。
OS Lab每次启动后都会首先弹出一个用于注册用户信息的对话框(可以选择对话框标题栏上的“帮助”按钮获得关于此对话框的帮助信息)。
在此对话框中填入学号和姓名后,点击“确定”按钮完成本次注册。
(2)学习OS Lab的基本使用方法:1)新建Windows控制台应用程序项目新建一个Windows控制台应用程序项目的步骤如下:1.1) 在“文件”菜单中选择“新建”,然后单击“项目”。
清华大学操作系统实验lab1实验报告

练习1、理解通过make生成执行文件的过程。
[练习1.1] 操作系统镜像文件ucore.img 是如何一步一步生成的?在proj1执行命令make V=可以得到make指令执行的过程从这几条指令中可以看出需要生成ucore.img首先需要生成bootblock,而生成bootblock需要先生成bootmain.o和bootasm.o还有sign,这三个文件又分别由bootmain.c、bootasm.S、sigh.c来生成。
ld -m elf_i386 -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o –o obj/bootblock.o这句话用于生成bootblock,elf_i386表示生成elf头,0x7C00为程序的入口。
'obj/bootblock.out' size: 440 bytes这句话表示生成的bootblock的文件大小,因为大小不到512字节,所以需要给blootblock填充,填充的功能在sign.c中有所体现,最后两字节设置为了0x55,0xAAbuf[510] = 0x55;buf[511] = 0xAA;FILE *ofp = fopen(argv[2], "wb+");size = fwrite(buf, 1, 512, ofp);[练习1.2] 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?前面已经提到过:引导扇区的大小为512字节,最后两个字节为标志性结束字节0x55,0xAA,做完这样的检查才能认为是符合规范的磁盘主引导扇区。
Sign.c文件中有作检查:if (size != 512) {fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);return -1;}练习2:使用qemu执行并调试lab1中的软件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验1:系统软件启动过程练习1:(1)操作系统镜像文件ucore.img 是如何一步一步生成的?在命令行中输入“make V=”1、首先把C的源代码进行编译成为.o文件,也就是目标文件(红色方框内)2、ld命令将这些目标文件转变成可执行文件,比如此处的bootblock.out(绿色方框内)3、dd命令把bootloder放到ucore.img count的虚拟硬盘之中4、还生成了两个软件,一个是Bootloader,另一个是kernel。
(2)一个被系统认为是符合规范的硬盘主引导扇区的特征:在/lab1/tools/sign.c中我们可以了解到规范的硬盘引导扇区的大小为512字节,硬盘结束标志位55AA练习2:(1)从CPU 加电后执行的第一条指令开始,单步跟踪BIOS 的执行改写Makefile文件lab1-mon: $(UCOREIMG)$(V)$(TERMINAL) -e "$(QEMU) -S -s -d in_asm -D $(BINDIR)/q.log -monitor stdio -hda $< -serial null"$(V)sleep 2$(V)$(TERMINAL) -e "gdb -q -x tools/lab1init"在调用qemu时增加-d in_asm -D q.log参数,便可以将运行的汇编指令保存在q.log 中。
(2)在初始化位置0x7c00 设置实地址断点,测试断点正常。
在tools/gdbinit结尾加上set architecture i8086b *0x7c00 //在0x7c00处设置断点。
continuex /2i $pc //显示当前eip处的汇编指令(3)将执行的汇编代码与bootasm.S 和bootblock.asm 进行比较,看看二者是否一致。
Notice:在q.log中进入BIOS之后的跳转地址与实际应跳转地址不相符,汇编代码也与bootasm.S 和bootblock.asm不相同。
这是由于在gdb之中调试的原因,可以直接输入make debug,在生成的qemu虚拟机之中进行调试可以看到在虚拟机中运行的汇编代码,之后再与bootasm.S 和bootblock.asm 进行比较。
与bootasm.S和bootblock.asm中的代码相同。
练习3:分析bootlloader进入保护模式的过程(/lab1/boot/bootasm.S).globl startstart:.code16# 关中断,并清除方向标志,即将DF 置“0”,这样(E)SI 及(E)DI 的修改为增量clicld# 清零各数据段寄存器:DS、ES、FSxorw %ax, %axmovw %ax, %dsmovw %ax, %esmovw %ax, %ss# 使能A20 地址线,这样80386 就可以突破1MB 访存现在,而可访问4GB 的32 位地址空间seta20.1:inb $0x64, %al # 等待8042键盘控制器不忙testb $0x2, %aljnz seta20.1movb $0xd1, %aloutb %al, $0x64seta20.2:inb $0x64, %al # 等待8042键盘控制器不忙testb $0x2, %aljnz seta20.2movb $0xdf, %al # 打开A20outb %al, $0x60# 初始化gdtlgdt gdtdesc# 进入保护模式movl %cr0, %eaxorl $CR0_PE_ON, %eaxmovl %eax, %cr0# 长跳转ljmp $PROT_MODE_CSEG, $protcseg.code32protcseg:# 设置段寄存器,并建立堆栈movw $PROT_MODE_DSEG, %axmovw %ax, %ds # -> DS: Data Segmentmovw %ax, %es # -> ES: Extra Segmentmovw %ax, %fs # -> FSmovw %ax, %gs # -> GSmovw %ax, %ss # -> SS: Stack Segment# 设置堆栈movl $0x0, %ebpmovl $start, %esp # 栈顶为0x7c00# 进入bootmain,不再返回call bootmainspin:jmp spin练习4:分析bootloader加载ELF格式的OS的过程读一个扇区的流程可参看bootmain.c 中的readsect 函数实现。
大致如下:1. 读I/O 地址0x1f7,等待磁盘准备好;2. 写I/O 地址0x1f2~0x1f5,0x1f7,发出读取第offseet 个扇区处的磁盘数据的命令;3. 读I/O 地址0x1f7,等待磁盘准备好;4. 连续读I/O 地址0x1f0,把磁盘扇区数据读到指定内存。
static voidreadsect(void *dst, uint32_t secno) {// wait for disk to be readywaitdisk();outb(0x1F2, 1); // count = 1outb(0x1F3, secno & 0xFF);outb(0x1F4, (secno >> 8) & 0xFF);outb(0x1F5, (secno >> 16) & 0xFF);outb(0x1F6, ((secno >> 24) & 0xF) | 0xE0);outb(0x1F7, 0x20); // cmd 0x20 - read sectors// wait for disk to be readywaitdisk();// read a sectorinsl(0x1F0, dst, SECTSIZE / 4);}该函数封装在readseg函数中,该函数完成读取任意的长度。
Notice: uint32_t secno = (offset / SECTSIZE) + 1; # 0号扇区已被引导占用。
最后在bootmain函数中完成加载ELF格式os的操作:1: 读取ELF的头部2: 判断ELF文件是否是合法3: 将描述表的头地址存在ph4: 按照描述表将ELF文件中数据载入内存5: 根据ELF头部储存的入口信息,找到内核的入口(不再返回)Notice:可能会出现内存长度>文件长度的现象多读入部分包含bss节,需要清0练习5:实现函数调用堆栈跟踪函数print_stackframe(void) {uint32_t ebp = read_ebp(), eip = read_eip();int i, j;for (i = 0; ebp != 0 && i < STACKFRAME_DEPTH; i ++) {cprintf("ebp:0x%08x eip:0x%08x args:", ebp, eip);uint32_t *args = (uint32_t *)ebp + 2;//(uint32_t)calling arguments [0..4] = the contents in address (unit32_t)ebp +2 [0..4]for (j = 0; j < 4; j ++) {cprintf("0x%08x ", args[j]);}cprintf("\n");print_debuginfo(eip - 1);/*call print_debuginfo(eip-1) to print the C calling function name and line number, etc.*/eip = ((uint32_t *)ebp)[1];ebp = ((uint32_t *)ebp)[0];//popup a calling stackframe}Notice:ss:ebp指向的堆栈位置储存着caller的ebp,以此为线索可以得到所有使用堆栈的函数ebp。
ss:ebp+4指向caller调用时的eip,ss:ebp+8等是(可能的)参数。
练习6:(1)中断向量表中一个表项占多少字节?其中哪几位代表中断处理代码的入口?中断向量表一个表项占用8字节,其中2-3字节是段选择子,0-1字节和6-7字节拼成位移,入口地址=段选择子+段内偏移量。
(2) 完善kern/trap/trap.c中对中断向量表进行初始化的函数idt_init可以在/lab1/kern/mm/mmu.h中可以找到SETGATE函数,查找其具体操作。
idt_init(void) {extern uintptr_t __vectors[];int i;for (i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i ++) {SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL); //设置IDT }lidt(&idt_pd); //载入IDT表(3) 完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数case IRQ_OFFSET + IRQ_TIMER:ticks ++; //一次中断累加1if (ticks % TICK_NUM == 0) {print_ticks();}break;扩展:(1)内核态切换到用户态:lab1_switch_to_user(void) {asm volatile ("sub $0x8, %%esp \n"// esp-8 为下一步复制的栈帧留好tf_ss和tf_esp的位置"int %0 \n""movl %%ebp, %%esp":: "i"(T_SWITCH_TOU));}case T_SWITCH_TOU:if (tf->tf_cs != USER_CS) {switchk2u = *tf;switchk2u.tf_cs = USER_CS;switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;//在执行int120前系统在核心态,int不会引起栈的切换switchk2u.tf_eflags |= FL_IOPL_MASK;*((uint32_t *)tf - 1) = (uint32_t)&switchk2u;}break;最后iret时返回5个值。