2016西安交通大学操作系统实验报告
操作系统实验报告

实验二进程管理(二)进程的控制实验思考题:1.可执行文件加载时进行了哪些处理?解:可执行文件加载时首先是创建一个新进程的fork系统调用,然后用于实现进程自我终止的exit系统调用;改变进程原有代码的exec系统调用;用于将调用进程挂起并等待子进程终止的wait系统调用;获得进程标识符的getpid系统调用等处理过程。
2.什么是进程同步?wait(0)是如何实现进程同步的?解:进程同步是指对多个相关进程在执行次序上进行协调,以使并发执行的主进程之间有效地共享资源和相互合作,从而使程序的执行具有可在现行。
首先程序在调用fork()机那里了一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。
实验三进程间的通信(一)信号机制实验一.参考程序#include<stdio.h>#include<signal.h>#include<unistd.h>Void waiting(),stop();Intwait_mark;Main(){Int P1,P2,stdout;While((P1=fork())==-1); /*创建子进程P1*/If(P1>0){While((p2=fork())==-1); /*创建子进程P2*/If(P2>0){Wait_mark=1;Signal(SIGINT,stop); /*接收到^C信号,转stop*/ Waiting();Kill(P1,16); /*向P1发软中断信号16*/Kill(P2,17); /*向P2发软中断信号17*/Wait(0); /*同步*/Wait(0);Printf(“Parent process is killed!\n”);Exit(0);}Else{Wait_mark=1;Signal(17,stop); /*接收到软中断信号17,转stop*/ Waiting();Lockf(stdout,1,0);Printf(“Child process 2 is killed by parent!\n);Lockf(stdout,0,0);Exit(0);}}Else{Wait_mark=1;Signal(16,stop); /*接收到软中断信号16,转stop*/ Waiting();Lockf(stdout,1,0);Printf(“Child process 1 is killed by parent!\n”);Lockf(stdout,0,0);Exit(0);}}Void waiting(){While(wait_mark!=0);}Void stop(){Wait_mark=0;}二.思考:1.该程序段前面部分用了两个wait(0),他们起什么作用?解:用了两个wait(0)的作用是同时使两个子进程P1和P2发出软中断信号,而不用等待。
操作系统实验报告

实验二进程调度1.目的和要求通过这次实验,理解进程调度的过程,进一步掌握进程状态的转变、进程调度的策略,进一步体会多道程序并发执行的特点,并分析具体的调度算法的特点,掌握对系统性能的评价方法。
2.实验内容阅读教材《计算机操作系统》第二章和第三章,掌握进程管理及调度相关概念和原理。
编写程序模拟实现进程的轮转法调度过程,模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。
假设初始状态为:有n个进程处于就绪状态,有m个进程处于阻塞状态。
采用轮转法进程调度算法进行调度(调度过程中,假设处于执行状态的进程不会阻塞),且每过t个时间片系统释放资源,唤醒处于阻塞队列队首的进程。
程序要求如下:1)输出系统中进程的调度次序;2)计算CPU利用率。
3.实验环境Windows操作系统、VC++6.0C语言4设计思想:(1)程序中进程可用PCB表示,其类型描述如下:struct PCB_type{int pid ; //进程名int state ; //进程状态2——表示“执行”状态1——表示“就绪”状态0——表示“阻塞”状态int cpu_time ; //运行需要的CPU时间(需运行的时间片个数)}用PCB来模拟进程;(2)设置两个队列,将处于“就绪”状态的进程PCB挂在队列ready中;将处于“阻塞”状态的进程PCB挂在队列blocked中。
队列类型描述如下:struct QueueNode{struct PCB_type PCB;Struct QueueNode *next;}并设全程量:struct QueueNode *ready_head=NULL,//ready队列队首指针*ready_tail=NULL , //ready队列队尾指针*blocked_head=NULL,//blocked队列队首指针*blocked_tail=NULL; //blocked队列队尾指针(3)设计子程序:start_state();读入假设的数据,设置系统初始状态,即初始化就绪队列和阻塞队列。
操作系统实验报告(2)

计算机实验报告(2)操作系统部分一、基本要求和内容1.了解操作系统的基本功能.2.认识WINDOWS桌面的各部分组成,掌握基本的桌面操作.3.掌握各种基本操作对象的操作方法.4.学会使用WINDOWS帮助.5.了解基本的DOS命令和基本的命令行操作方法.6.熟练掌握文件操作方法.7.掌握对图标的操作方法(移动/拖曳/单击/双击/右击等等).8.熟悉资源管理器窗口和”我的电脑”(“计算机”)窗口.9.掌握启动控制面板的方法,了解控制面板的主要功能,掌握使用控制面板对软硬件进行设置的方法。
10.掌握“运行”对话框的使用方法。
11.了解“任务管理器”的简单使用方法。
12.熟悉“画图”“记事本”“计算器”“写字板”等常用应用程序。
13.开始POWERPOINT的基本使用.二、通过上机实验解决下列问题1. CTRL+ALT+DEL 组合键的功能是:打开【任务管理器】窗口2.全角和半角的区别是:半角是一个字符,全角是两个字符3. CTRL+A组合键的功能是:全部选中CTRL+C组合键的功能是:复制CTRL+V组合键的功能是:粘贴CTRL+X组合键的功能是:剪切CTRL+Z组合键的功能是: 撤销ALT+PRINTSCREEN组合键的功能是:复制当前窗口、对话框或其他对象到剪贴板中任务栏隐藏时通过什么组合键可以看到任务栏:Ctrl+Alt+Del进行窗口切换的组合键是:ALT+Tab4.“画图”应用程序默认保存文件类型是:*.png“记事本”应用程序默认保存文件类型是: *.txt.DOC是什么文件类型Word文档.EXE是什么文件类型可执行文件(程序文件)5.鼠标的基本操作方法包括:指向、单击、双击和拖动鼠标指针附近有漏沙钟表示当前的状态是: 沙漏是等待,因为程序先是从硬盘上读取,然后再到内存,芯片在其期间进行运算,再没真正的打开程序时,系统认为它没正真的启动6.资源管理器左下角窗格(即”文件夹”窗口)显示的是:系统中的所有资源以分层树型的结构显示出来7.一般情况下,对文件进行重命名时,不应该修改文件的扩展名,因为: 如果修改了后缀名则会导致文件属性更改,文件无法打开8.文件的属性主要包括哪些:“只读”、“存档”、“隐藏”9.选择多个连续的文件可以采用哪些方法:使用鼠标先选定第一个文件或文件夹,然后按住Shift键,用鼠标单击最后一个文件或文件夹,这样在第一个对象和最后一个对象之间的所有文件或文件夹将全部被选中,包括第一个和最后一个文件或文件夹。
《操作系统》存储管理实验报告

《操作系统》存储管理实验报告操作系统是计算机系统中最基础、最核心的软件之一,负责管理计算机硬件资源和提供资源的分配与调度。
而存储管理是操作系统中的重要组成部分,它负责管理计算机的内存,包括内存的分配、回收、保护等操作。
本文将针对存储管理进行实验,并撰写实验报告。
本次实验主要涉及以下内容:内存的分配与回收、内存的保护。
实验过程中,我首先根据操作系统的要求,设计了相应的算法用于内存的分配与回收。
并通过编写程序,验证了算法的正确性。
随后,我进一步研究了内存的保护机制,通过设置访问权限位和访问控制表,实现了对内存的合理保护。
在内存的分配与回收方面,我设计了一种简单的算法,首次适应算法。
具体实现如下:首先,将内存分为若干个块,每个块的大小为固定值。
当需要分配内存时,首先遍历内存块列表,找到第一个大小合适的块,将其分配给进程。
当进程终止时,将其占用的内存块回收,以便后续进程使用。
通过编写程序进行测试,结果表明该算法能够正确地进行内存的分配与回收。
在内存的保护方面,我采用了访问权限位和访问控制表的方式进行。
具体实现如下:首先,为每个进程分配一组访问权限位,记录了该进程能够访问的内存区域。
同时,设置一个访问控制表,记录了每个内存块的权限。
当进程访问一些内存块时,首先检查该进程的访问权限位,再与访问控制表中的权限进行比较,以确定该进程是否有权限访问该内存块。
通过编写程序进行测试,证明了该机制能够有效地保护内存。
总结来说,本次实验主要涉及了操作系统中的存储管理部分,包括内存的分配与回收、内存的保护。
通过设计算法和编写程序,我成功地实现了这些功能,并验证了其正确性。
通过本次实验,我进一步加深了对操作系统存储管理的理解,提高了编程和设计的能力。
操作系统课程设计试验报告2

四川大学操作系统课程设计报告学院:软件学院专业:软件工程年级:2014级组编号:组成员:张弛提交时间:2016年3月15日指导教师评阅意见:.. . . .指导教师评阅成绩:XXX1:XXX1:XXX1:XXX1:XXX1:实验项目一项目名称:Week02实验目的:熟悉Linux的使用实验时间:2016.3.15人员分工:实验环境:Ubuntu 15.10实验内容:∙Lab1---设置网络地址按以下步骤设置网络地址,并截图说明:○打开终端○输入ifconfig命令查看当前网络设置(截图表示)○使用ping命令确定要设置的IP地址未被占用○用ifconfig命令来设置虚拟机的IP地址命令格式:ifconfig eth0 IP○用ifconfig命令来查看网络状态,确认设置是否成功(截图表示)∙Lab2 --- 修改配置文件按以下步骤,通过修改网络配置文件来配置网络1.打开终端2.输入ifconfig命令查看当前网络状态(截图表示)3.使用ping命令确定要设置的IP地址未被占用4.在图形界面下进入目录/etc/sysconfig/network-scripts5.打开文件ifcfg-eth0,保留以下已有的选项,添加没有的选项,删除或注释文件中多余的选项:(截图表示)DEVICE=eth0IPADDR=192.168.0.110(该为新的IP地址)NETMASK=255.255.255.0GATEWAY=10.255.255.254(可选,该为本网络的网关地址)ONBOOT=yes1.保存配置文件并在终端输入命令 service network restart2.在终端输入命令ifconfig eth0来查看是否操作成功(截图表示)∙Lab3 --- SSH安装和使用按以下步骤来实现SSH在Windows系统上的安装和使用,并截图1.安装SSH2.从桌面启动SSH Secure File Transfer Client3.点击Quick Connect按钮4.在弹出的窗口中,在Hostname中输入虚拟机的IP地址,UserName中输入用户名(一般为root),其他的保持默认,然后点击Connect按钮5.在弹出的窗口中输入虚拟机密码(截图表示)6.连接成功后将主机上的以自己学号命名的word文件拷贝到虚拟机上的/usr/local/目录下(截图表示)7.从桌面启动SSH Secure Shell Client并连接8.连接成功后用cd命令进入目录/usr/local9.输入ls命令查看我们传输的文件是否存在(截图表示)∙Lab4 --- VMwareTools安装和使用按以下方式使用VmwareTools来Windows和虚拟机下的Linux之间的文件传输,并截图1.在虚拟机上点击菜单VM并选择Install Vmware Tools2.用cd命令进入目录/mnt/cdrom3.用ls查看是否有VMwareTools-XXX.tar.gz文件(截图表示)4.拷贝此文件:cp VMareTools-XXX.tar.gz /usr/local5.用cd命令进入目录/usr/local并用ls命令确认VMareTools-XXX.tar.gz已存在(截图表示)6.解压此文件 tar -zxvf VMareTools-XXX.tar.gz7.进入目录cd vmware-tools-distrib8.执行安装 ./vmware-install.pl安装过程中要求做一些配置,只需要敲回车即可,一直到安装完成。
操作系统课内实验报告

西安交通大学实验报告操作系统实验报告刘烜乐享科技计算机36班操作系统实验实验一:用户接口实验实验目的1)理解面向操作命令的接口Shell。
2)学会简单的shell编码。
3)理解操作系统调用的运行机制。
4)掌握创建系统调用的方法。
操作系统给用户提供了命令接口和程序接口(系统调用)两种操作方式。
用户接口实验也因此而分为两大部分。
首先要熟悉Linux的基本操作命令,并在此基础上学会简单的shell 编程方法。
然后通过想Linux内核添加一个自己设计的系统调用,来理解系统调用的实现方法和运行机制。
在本次实验中,最具有吸引力的地方是:通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这对我们初步了解操作系统的生成过程极为有利。
实验内容1)控制台命令接口实验该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell和进行简单的shell 编程。
查看bash版本。
在 shell 提示符下输入:$echo $BASH_VERSION我们的版本是(2)建立 bash 脚本,输出 Hello word在编辑器中输入以下内容#!/bin/bashecho Hello World!执行脚本使用指令:$./script编写bash脚本,统计/my目录下c语言文件的个数通过 bash 脚本,可以有多种方式实现这个功能,而使用函数是其中个一个选择。
在使用函数之前,必须先定义函数。
进入自己的工作目录,编写名为 count 的文件脚本程序:#! /bin/bashfunction count{echo –n " Number of matches for $1: " #接收程序的第一个参数ls $1|wc –l #对子程序的第一个参数所在的目录进行操作}将 count 文件复制到当前目录下,然后在当前目录下建立文件夹,在 my 目录下建立几个 c 文件,以便用来进行测试2)系统调用实验该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。
操作系统实验报告1

《操作系统》实验报告实验序号:01 实验项目名称:操作系统环境学号1107xxx 姓名xxx 专业、班级软件工程1103 实验地点计—502 指导教师徐冬时间2013.9.23 实验目的1) 了解和学习Windows系统管理工具及其使用;2) 熟悉Windows系统工具的内容和应用;由此,进一步熟悉Windows操作系统的应用环境。
工具/准备工作在开始本实验之前,请回顾教科书的相关内容。
需要准备一台运行Windows 操作系统的计算机。
实验内容与步骤1. 计算机管理2. 事件查看器3. 性能监视4. 服务5. 数据库 (ODBC)为了帮助用户管理和监视系统,Windows提供了多种系统管理工具,其中最主要的有计算机管理、事件查看器和性能监视等。
如图2所示。
图2 基于虚拟机的操作系统计算环境管理步骤1:登录进入Windows。
步骤2:在“开始”菜单中单击“设置”-“控制面板”命令,双击“管理工具”图标。
在本地计算机“管理工具”组中,有哪些系统管理工具,基本功能是什么:1) Internet 信息服务;管理IIS,Internet 和Intranet站点的WEB服务器。
2) Server Extensions 管理器;Server Extensions管理器。
3)计算机管理;管理磁盘以及使用其他系统工具来管理本地或远程的计算机。
4)性能;显示系统性能图表以及配置数据日志和警报。
5)本地安全策略;查看和修改本地安全策略,如用户权限和审核策略。
6)事件查看器;显示来自于Windows和其他程序的监视与排错消息。
7)组件服务;配置和管理COM+应用程序。
1. 计算机管理使用“计算机管理”可通过一个合并的桌面工具来管理本地或远程计算机,它将几个Windows管理实用程序合并到一个控制台目录树中,使管理员可以轻松地访问特定计算机的管理属性和工具。
步骤3:在“管理工具”窗口中,双击“计算机管理”图标。
“计算机管理”使用的窗口与“Windows资源管理器”相似。
《操作系统》课程实验报告

《操作系统》课程实验报告一、实验目的本次《操作系统》课程实验的主要目的是通过实际操作和观察,深入理解操作系统的工作原理、进程管理、内存管理、文件系统等核心概念,并掌握相关的操作技能和分析方法。
二、实验环境1、操作系统:Windows 10 专业版2、开发工具:Visual Studio Code3、编程语言:C/C++三、实验内容(一)进程管理实验1、进程创建与终止通过编程实现创建新进程,并观察进程的创建过程和资源分配情况。
同时,实现进程的正常终止和异常终止,并分析其对系统的影响。
2、进程同步与互斥使用信号量、互斥锁等机制实现进程之间的同步与互斥。
通过模拟多个进程对共享资源的访问,观察并解决可能出现的竞争条件和死锁问题。
(二)内存管理实验1、内存分配与回收实现不同的内存分配算法,如首次适应算法、最佳适应算法和最坏适应算法。
观察在不同的内存请求序列下,内存的分配和回收情况,并分析算法的性能和优缺点。
2、虚拟内存管理研究虚拟内存的工作原理,通过设置页面大小、页表结构等参数,观察页面的换入换出过程,以及对系统性能的影响。
(三)文件系统实验1、文件操作实现文件的创建、打开、读取、写入、关闭等基本操作。
观察文件在磁盘上的存储方式和文件系统的目录结构。
2、文件系统性能优化研究文件系统的缓存机制、磁盘调度算法等,通过对大量文件的读写操作,评估不同优化策略对文件系统性能的提升效果。
四、实验步骤(一)进程管理实验步骤1、进程创建与终止(1)使用 C/C++语言编写程序,调用系统函数创建新进程。
(2)在子进程中执行特定的任务,父进程等待子进程结束,并获取子进程的返回值。
(3)通过设置异常情况,模拟子进程的异常终止,观察父进程的处理方式。
2、进程同步与互斥(1)定义共享资源和相关的信号量或互斥锁。
(2)创建多个进程,模拟对共享资源的并发访问。
(3)在访问共享资源的关键代码段使用同步机制,确保进程之间的正确协作。
(4)观察并分析在不同的并发情况下,系统的运行结果和资源竞争情况。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告实验一:用户接口实验一.实验目的1.理解面向操作命令的接口Shell。
2.学会简单的shell编码。
3.理解操作系统调用的运行机制。
4.掌握创建系统调用的方法。
操作系统给用户提供了命令接口和程序接口(系统调用)两种操作方式。
用户接口实验也因此而分为两大部分。
首先要熟悉Linux的基本操作命令,并在此基础上学会简单的shell编程方法。
然后通过想Linux内核添加一个自己设计的系统调用,来理解系统调用的实现方法和运行机制。
在本次实验中,最具有吸引力的地方是:通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这对我们初步了解操作系统的生成过程极为有利。
二.实验内容1)控制台命令接口实验该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell 和进行简单的shell编程。
➢查看bash版本。
➢编写bash脚本,统计/my目录下c语言文件的个数2)系统调用实验该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。
➢编程调用一个系统调用fork(),观察结果。
➢编程调用创建的系统调用foo(),观察结果。
➢自己创建一个系统调用mycall(),实现功能:显示字符串到屏幕上。
➢编程调用自己创建的系统调用。
三.实验步骤系统调用实验:1.首先将Linux-3.0.tar.bz2拷贝到/usr/src目录下——命令:cp linux-3.0.tar.bz2 /usr/src/2.打开终端,获得root权限——命令:sudo –s3.进入/usr/src目录——命令:cd /usr/src4.解压linux源码——命令:tar xvzf linux-3.0.tar.bz25.进入目录linux-3.0.5——命令:cd linux-3.06.添加系统调用——操作:gedit kernel/myservice.c 在文本编辑器中添加#include <linux/kernel.h>#include <linux/linkage.h>asmlinkage void sys_mycall(){printk(KERN_INFO "Hello, world!\n");return;}7.修改kernel/Makefile添加生成myservice.c添加到Makefile的编译规则中:obj-y += myservice.o8..修改arch/x86/include/asm/unistd_32.h,添加以下内容:#define __NR_mycall SYS_ID//SYS_ID表示新添加系统调用的调用号并修改文件中的NR_syscalls,将其值增加19.修改arxh/x86/include/asm/syscalls.h添加以下内容:asmlinkage void sys_mycall();10.修改arch/x86/kernel/syscall_table_32.S,添加以下内容:.long sys_mycall11.配置内核(仅仅修改local versions即可)——命令:make menuconfig12.编译内核——命令:make –j4 bzImage(开4个线程编译)13.编译内核模块——命令:make –j4 modules14.安装内核模块——命令:make modules_install15.安装内核——命令:make install16.重启系统,在系统选择页面选择进入自己编译的linux-3.0内核17.在桌面建立测试的C程序test.c程序内容如下:#include <stdio.h>int main(int argc, char *argv[]){syscall(SYS_ID); // SYS_ID表示新添加系统调用的调用号return 0;}18.编译程序——gcc test.c –o a.out19.运行程序——./a.out20.查看内核日志(printk的输出信息在内核日志中):dmesg四.实验结果1.成功完成内核编译的任务,结果显示图如下:2.下图为添加系统调用结果五.实验小结这次实验的内核编译需要进行一系列比较花时间的操作过程,但同时也锻炼了实际动手能力,在实践中对于操作系统这门课有了进一步的了解。
同时,在本次实验中,学习了linux系统的使用方法,掌握了很多的基本命令,也明白了添加系统调用的方法,为以后的学习提供了很大的帮助。
实验四:一个简单文件系统的实现一.实验目的1.熟悉Ext文件系统的原理2.根据Ext文件系统的数据结构和构建方法,自行实现一个简单的内存文件系统二.实验内容1.设计并实现一个一级(单用户)文件系统程序a.提供以下操作:a)文件创建/删除接口命令create/deleteb)目录创建/删除接口命令mkdir/rmdirc)显示目录内容命令lsb.创建的文件不要求格式和内容2.设计并实现一个二级文件系统程序a.提供用户登录;b.文件、目录要有权限三.实验原理1.Ext文件系统结构:2.3.引导块BootBlock每个硬盘分区的开头1024字节,即0 byte至1023 byte是分区的启动扇区。
存放由ROM BIOS自动读入的引导程序和数据,但这只对引导设备有效,而对于非引导设备,该引导块不含代码。
这个块与ext2没有任何关系。
4.超级块SuperBlock每个分区均有一个super block块,定义了文件系统的全局信息,包括块的大小,总块数,空闲块,索引结点数,各种位图和i节点表的地址和大小等信息。
5.数据块位图这是ext2管理存储空间的方法。
即位图法。
每个位对应一个数据块,位值为0表示空闲,1表示已经分配。
数据块位图定义为一个块大小。
于是,一个组中的数据块个数就决定了。
假设块大小为b 字节。
可以区别的块数为b*8个6.数据块DataBlocks每个组的数据最大个数是在块大小定义后就确定了的。
所以组容量也就确定了。
假设块大小为b 字节。
那么组容量就确定为(b*8)*b字节若1块=4K,则组块大小=4K*8*4K=128M7.inode位图与数据块位图相似,用来表示索引结点是否已经被使用。
假设块大小为b 字节,每个索引结点数据结构大小为128字节。
最多可以有b*8个索引结点,索引结点表需要占用的存储空间大小为(b*8)*128字节。
即(b*8)*128/b=8*128个块8.inode表索引结点表由若干个索引结点数据结构组成,需要占用若干个块。
Ext2中的每个索引结点数据结构大小为128字节。
每个索引结点即对应一个文件或是目录。
是对其除文件名(目录名)以外的所有属性的描述。
例如:文件类型,文件创建时间,访问时间,修改时间,文件所占数据块的个数,指向数据块的指针。
其中,数据块指针是由15个元组的数据组成四.实验步骤运行结果1.根据要求编写源程序,实验源代码见附录1。
2. 运行程序,运行结果如图:1.根据提示输入help,结果如图:2.输入ls 列出根目录下的项目,然后创建文件目录c 再输入ls观察是否创建成功:5.进入文件目录c并在c中创建文件a6.打开a,并读取a7. 关闭a 9.删除a9. 删除文件目录c五.实验小结本次实验要求建立一个文件系统,由于在专业课上的基本知识学习比较薄弱,所以参考了网上的一些代码,进行了一些修改后最后获得结果。
最后,也算完成了一个简单的文件系统,具备了题目中的要求。
但在以后的学习中,还要对这一方面的知识进行一些补充。
附录1:实验源码:#include <stdio.h>#include <time.h>#include <string.h>#include <signal.h>#define DATA_BLOCK 263680 //数据块起始地址#define BLOCK_SIZE 512 //块大小#define DISK_START 0 //磁盘开始地址#define BLOCK_BITMAP 512 //块位图起始地址#define INODE_BITMAP 1024//inode 位图起始地址#define INODE_TABLE 1536//索引节点表起始地址#define INODE_SIZE 64 //struct inode的大小struct group_desc{char bg_volume_name[16]; //卷名unsigned short bg_block_bitmap; //保存块位图的块号unsigned short bg_inode_bitmap; //保存索引结点位图的块号unsigned short bg_inode_table; //索引结点表的起始块号unsigned short bg_free_blocks_count; //本组空闲块的个数unsigned short bg_free_inodes_count; //本组空闲索引结点的个数unsigned short bg_used_dirs_count; //本组目录的个数char bg_pad[4]; //填充(0xff)};struct inode{unsigned short i_mode; //文件类型及访问权限unsigned short i_blocks; //文件的数据块个数unsigned long i_size; //大小( 字节)unsigned long i_atime; //访问时间unsigned long i_ctime; //创建时间unsigned long i_mtime; //修改时间unsigned long i_dtime; //删除时间unsigned short i_block[8]; //指向数据块的指针char i_pad[24]; //填充(0xff)};struct dir_entry{ //目录项结构unsigned short inode; //索引节点号unsigned short rec_len; //目录项长度unsigned short name_len; //文件名长度char file_type; //文件类型(1: 普通文件,2: 目录.. )char name[9]; //文件名};char Buffer[512]; //针对数据块的缓冲区char tempbuf[4097]; //unsigned char bitbuf[512]; //位图缓冲区unsigned short index_buf[256];short fopen_table[16]; // 文件打开表unsigned short last_alloc_inode; // 最近分配的节点号unsigned short last_alloc_block; // 最近分配的数据块号unsigned short current_dir; // 当前目录的节点号struct group_desc super_block[1]; // 组描述符缓冲区struct inode inode_area[1]; // 节点缓冲区struct dir_entry dir[32]; // 目录项缓冲区char current_path[256]; // 当前路径名unsigned short current_dirlen;FILE *fp;void update_group_desc(){fseek(fp,DISK_START,SEEK_SET);fwrite(super_block,BLOCK_SIZE,1,fp);}void reload_group_desc()//载入组描述符{fseek(fp,DISK_START,SEEK_SET);fread(super_block,BLOCK_SIZE,1,fp);}void update_inode_bitmap()//更新inode位图{fseek(fp,INODE_BITMAP,SEEK_SET);fwrite(bitbuf,BLOCK_SIZE,1,fp);}void reload_inode_bitmap()//载入inode位图{fseek(fp,INODE_BITMAP,SEEK_SET);fread(bitbuf,BLOCK_SIZE,1,fp);}void update_block_bitmap()//更新block位图{fseek(fp,BLOCK_BITMAP,SEEK_SET);fwrite(bitbuf,BLOCK_SIZE,1,fp);}void reload_block_bitmap()//载入block位图{fseek(fp,BLOCK_BITMAP,SEEK_SET);fread(bitbuf,BLOCK_SIZE,1,fp);}void update_inode_entry(unsigned short i)//更新第i个inode入口{fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);fwrite(inode_area,INODE_SIZE,1,fp);}void reload_inode_entry(unsigned short i)//载入第i个inode入口{fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);fread(inode_area,INODE_SIZE,1,fp);}void reload_dir(unsigned short i)//更新第i个目录{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fread(dir,BLOCK_SIZE,1,fp);}void update_dir(unsigned short i)//载入第i个目录{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fwrite(dir,BLOCK_SIZE,1,fp);}void reload_block(unsigned short i)//载入第i个数据块{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fread(Buffer,BLOCK_SIZE,1,fp);}void update_block(unsigned short i)//更新第i个数据块{fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);fwrite(Buffer,BLOCK_SIZE,1,fp);}int alloc_block()//分配一个数据块,返回数据块号;{unsigned short cur=last_alloc_block;unsigned char con=128;int flag=0;if(super_block[0].bg_free_blocks_count==0){printf("There is no block to be alloced!\n");return(0);}reload_block_bitmap();cur=cur/8;while(bitbuf[cur]==255){if(cur==511)cur=0;else cur++;}while(bitbuf[cur]&con){con=con/2;flag++;}bitbuf[cur]=bitbuf[cur]+con;last_alloc_block=cur*8+flag;update_block_bitmap();super_block[0].bg_free_blocks_count--;update_group_desc();return last_alloc_block;}void remove_block(unsigned short del_num)//删除一个block {unsigned short tmp;tmp=del_num/8;reload_block_bitmap();switch(del_num%8)//更改block位图{case 0:bitbuf[tmp]=bitbuf[tmp]&127;break;case 1:bitbuf[tmp]=bitbuf[tmp]&191;break;case 2:bitbuf[tmp]=bitbuf[tmp]&223;break;case 3:bitbuf[tmp]=bitbuf[tmp]&239;break;case 4:bitbuf[tmp]=bitbuf[tmp]&247;break;case 5:bitbuf[tmp]=bitbuf[tmp]&251;break;case 6:bitbuf[tmp]=bitbuf[tmp]&253;break;case 7:bitbuf[tmp]=bitbuf[tmp]&254;break;}update_block_bitmap();super_block[0].bg_free_blocks_count++;update_group_desc();}//int get_inode()//分配一个inode,返回序号{unsigned short cur=last_alloc_inode;unsigned char con=128;int flag=0;if(super_block[0].bg_free_inodes_count==0){printf("There is no Inode to be alloced!\n");return 0;}reload_inode_bitmap();cur=(cur-1)/8;while(bitbuf[cur]==255){if(cur==511)cur=0;else cur++;}while(bitbuf[cur]&con){con=con/2;flag++;}bitbuf[cur]=bitbuf[cur]+con;last_alloc_inode=cur*8+flag+1;update_inode_bitmap();super_block[0].bg_free_inodes_count--;update_group_desc();return last_alloc_inode;}//void remove_inode(unsigned short del_num){unsigned short tmp;tmp=(del_num-1)/8;reload_inode_bitmap();switch((del_num-1)%8)//更改block位图{case 0:bitbuf[tmp]=bitbuf[tmp]&127;break;case 1:bitbuf[tmp]=bitbuf[tmp]&191;break;case 2:bitbuf[tmp]=bitbuf[tmp]&223;break;case 3:bitbuf[tmp]=bitbuf[tmp]&239;break;case 4:bitbuf[tmp]=bitbuf[tmp]&247;break;case 5:bitbuf[tmp]=bitbuf[tmp]&251;break;case 6:bitbuf[tmp]=bitbuf[tmp]&253;break;case 7:bitbuf[tmp]=bitbuf[tmp]&254;break;}update_inode_bitmap();super_block[0].bg_free_inodes_count++;update_group_desc();}// dirvoid dir_prepare(unsigned short tmp,unsigned short len,int type) //新目录和文件初始化.and ..{reload_inode_entry(tmp);//得到新目录的节点入口地址if(type==2)//目录{inode_area[0].i_size=32;inode_area[0].i_blocks=1;inode_area[0].i_block[0]=alloc_block();dir[0].inode=tmp;dir[1].inode=current_dir;dir[0].name_len=len;dir[1].name_len=current_dirlen;dir[0].file_type=dir[1].file_type=2;for(type=2;type<32;type++)dir[type].inode=0;strcpy(dir[0].name,".");strcpy(dir[1].name,"..");update_dir(inode_area[0].i_block[0]);inode_area[0].i_mode=01006;//drwxrwxrwx:目录}else{inode_area[0].i_size=0;inode_area[0].i_blocks=0;inode_area[0].i_mode=0407;//drwxrwxrwx:文件}update_inode_entry(tmp);}//unsigned short reserch_file(char tmp[9],int file_type,unsigned short *inode_num,unsigned short *block_num,unsigned short *dir_num){ //查找文件并改写缓冲区里节点号,所在目录节点的数据块号(0~7)、目录项所在号unsigned short j,k;reload_inode_entry(current_dir);j=0;while(j<inode_area[0].i_blocks){reload_dir(inode_area[0].i_block[j]);k=0;while(k<32){if(!dir[k].inode||dir[k].file_type!=file_type||strcmp(dir[k].name,tmp))k++;else{*inode_num=dir[k].inode;*block_num=j;*dir_num=k;return 1;}}j++;}return 0;}//void cd(char tmp[9]){unsigned short i,j,k,flag;flag=reserch_file(tmp,2,&i,&j,&k);if(flag){current_dir=i;if(!strcmp(tmp,"..")&&dir[k-1].name_len){current_path[strlen(current_path)-dir[k-1].name_len-1]='\0';current_dirlen=dir[k].name_len;}else if(!strcmp(tmp,"."));else if(strcmp(tmp,"..")){current_dirlen=strlen(tmp);strcat(current_path,tmp);strcat(current_path,"/");}}else printf("The directory %s not exists!\n",tmp);}//void del(char tmp[9])unsigned short i,j,k,m,n,flag;m=0;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){flag=0;while(fopen_table[flag]!=dir[k].inode&&flag<16)flag++;if(flag<16)fopen_table[flag]=0;reload_inode_entry(i);while(m<inode_area[0].i_blocks)remove_block(inode_area[0].i_block[m++]);inode_area[0].i_blocks=0;inode_area[0].i_size=0;remove_inode(i);reload_inode_entry(current_dir);dir[k].inode=0;//if(k!=0)dir[k-1].rec_len+=dir[k].rec_len ;update_dir(inode_area[0].i_block[j]);inode_area[0].i_size-=16;m=1;while(m<inode_area[i].i_blocks){flag=n=0;reload_dir(inode_area[0].i_block[m]);while(n<32){if(!dir[n].inode)flag++;n++;}if(flag==32){remove_block(inode_area[i].i_block[m]);inode_area[i].i_blocks--;while(m<inode_area[i].i_blocks)inode_area[i].i_block[m]=inode_area[i].i_block[++m];}}update_inode_entry(current_dir);}else printf("The file %s not exists!\n",tmp);}//void mkdir(char tmp[9],int type)unsigned short tmpno,i,j,k,flag;reload_inode_entry(current_dir); //获得当前目录的索引节点给inode_area[0]if(!reserch_file(tmp,type,&i,&j,&k)) //未找到同名文件{if(inode_area[0].i_size==4096) //目录项已满{printf("Directory has no room to be alloced!\n");return;}flag=1;if(inode_area[0].i_size!=inode_area[0].i_blocks*512)//目录中有某些个块中32个项未满{i=0;while(flag&&i<inode_area[0].i_blocks){reload_dir(inode_area[0].i_block[i]);j=0;while(j<32){if(dir[j].inode==0){flag=0;break;}j++;}i++;}tmpno=dir[j].inode=get_inode();dir[j].name_len=strlen(tmp);dir[j].file_type=type;strcpy(dir[j].name,tmp);update_dir(inode_area[0].i_block[i-1]);}else//全满{inode_area[0].i_block[inode_area[0].i_blocks]=alloc_block();inode_area[0].i_blocks++;reload_dir(inode_area[0].i_block[inode_area[0].i_blocks-1]);tmpno=dir[0].inode=get_inode();dir[0].name_len=strlen(tmp);dir[0].file_type=type;strcpy(dir[0].name,tmp);//初始化新块for(flag=1;flag<32;flag++)dir[flag].inode=0;update_dir(inode_area[0].i_block[inode_area[0].i_blocks-1]);}inode_area[0].i_size+=16;update_inode_entry(current_dir);dir_prepare(tmpno,strlen(tmp),type);}else //已经存在同名文件或目录{if(type==1)printf("File has already existed!\n");else printf("Directory has already existed!\n");}}//void rmdir(char tmp[9]){unsigned short i,j,k,flag;unsigned short m,n;if(!strcmp(tmp,"..")||!strcmp(tmp,".")){printf("The directory can not be deleted!\n");return;}flag=reserch_file(tmp,2,&i,&j,&k);if(flag){reload_inode_entry(dir[k].inode); //找到要删除的目录的节点并载入if(inode_area[0].i_size==32) //只有.and ..{inode_area[0].i_size=0;inode_area[0].i_blocks=0;//reload_dir(inode_area[0].i_block[0]);//dir[0].inode=0;//dir[1].inode=0;remove_block(inode_area[0].i_block[0]);reload_inode_entry(current_dir);//得到当前目录的节点并更改当前目录项remove_inode(dir[k].inode);dir[k].inode=0;update_dir(inode_area[0].i_block[j]);inode_area[0].i_size-=16;flag=0;m=1;while(flag<32&&m<inode_area[0].i_blocks){flag=n=0;reload_dir(inode_area[0].i_block[m]);while(n<32){if(!dir[n].inode)flag++;n++;}if(flag==32){remove_block(inode_area[0].i_block[m]);inode_area[0].i_blocks--;while(m<inode_area[0].i_blocks)inode_area[0].i_block[m]=inode_area[0].i_block[++m];}}update_inode_entry(current_dir);}else printf("Directory is not null!\n");}else printf("Directory to be deleted not exists!\n");}//void ls(){int i,j,k,tmpno,no;i=0;printf("items type mode size\n");reload_inode_entry(current_dir);while(i<inode_area[0].i_blocks){k=0;reload_dir(inode_area[0].i_block[i]);while(k<32){if(dir[k].inode){printf("%s",dir[k].name);if(dir[k].file_type==2){j=0;reload_inode_entry(dir[k].inode);if(!strcmp(dir[k].name,".."))while(j++<13)printf(" ");else if(!strcmp(dir[k].name,"."))while(j++<14)printf(" ");else while(j++<15-dir[k].name_len)printf(" ");printf("<DIR> ");switch(inode_area[0].i_mode&7){case 1:printf("____x");break;case 2:printf("__w__");break;case 3:printf("__w_x");break;case 4:printf("r____");break;case 5:printf("r___x");break;case 6:printf("r_w__");break;case 7:printf("r_w_x");break;}printf(" ----");}else if(dir[k].file_type==1){j=0;reload_inode_entry(dir[k].inode);while(j++<15-dir[k].name_len)printf(" ");printf("<FILE> ");switch(inode_area[0].i_mode&7){case 1:printf("____x");break;case 2:printf("__w__");break;case 3:printf("__w_x");break;case 4:printf("r____");break;case 5:printf("r___x");break;case 6:printf("r_w__");break;case 7:printf("r_w_x");break;}printf(" %d bytes ",inode_area[0].i_size);}printf("\n");}k++;reload_inode_entry(current_dir);}i++;}}// fileunsigned short search_file(unsigned short Ino)//在打开文件表中查找是否已打开文件{unsigned short fopen_table_point=0;while(fopen_table_point<16&&fopen_table[fopen_table_point++]!=Ino);if(fopen_table_point==16)return 0;return 1;}//void read_file(char tmp[9])//读文件{unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k); //返回文件目录项的信息if(flag){if(search_file(dir[k].inode)){reload_inode_entry(dir[k].inode);if(!(inode_area[0].i_mode&4))//i_mode:111b:读,写,执行{printf("The file %s can not be read!\n",tmp);return;}for(flag=0;flag<inode_area[0].i_blocks;flag++){reload_block(inode_area[0].i_block[flag]);Buffer[512]='\0';printf("%s",Buffer);}if(flag==0)printf("The file %s is empty!\n",tmp);else printf("\n");}else printf("The file %s has not been opened!\n",tmp);}else printf("The file %s not exists!\n",tmp);}void write_file(char tmp[9])//写文件{unsigned short flag,i,j,k,size=0,need_blocks;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode)){reload_inode_entry(dir[k].inode);if(!(inode_area[0].i_mode&2))//i_mode:111b:读,写,执行{printf("The file %s can not be writed!\n",tmp);return;}while(1){tempbuf[size]=getchar();if(tempbuf[size]=='#'){tempbuf[size]='\0';break;}if(size>=4096){printf("Sorry,the max size of a file is 4KB!\n");tempbuf[size]='\0';break;}size++;}need_blocks=strlen(tempbuf)/512;if(strlen(tempbuf)%512)need_blocks++;if(need_blocks<9){while(inode_area[0].i_blocks<need_blocks){inode_area[0].i_block[inode_area[0].i_blocks]=alloc_block();inode_area[0].i_blocks++;}j=0;while(j<need_blocks){if(j!=need_blocks-1){reload_block(inode_area[0].i_block[j]);memcpy(Buffer,tempbuf+j*BLOCK_SIZE,BLOCK_SIZE);update_block(inode_area[0].i_block[j]);}else{reload_block(inode_area[0].i_block[j]);memcpy(Buffer,tempbuf+j*BLOCK_SIZE,strlen(tempbuf)-j*BLOCK_SIZE);if(strlen(tempbuf)>inode_area[0].i_size){Buffer[strlen(tempbuf)-j*BLOCK_SIZE]='\0';inode_area[0].i_size=strlen(tempbuf);}update_block(inode_area[0].i_block[j]);}j++;}update_inode_entry(dir[k].inode);}else printf("Sorry,the max size of a file is 4KB!\n");}else printf("The file %s has not opened!\n",tmp);}else printf("The file %s does not exist!\n",tmp);}//void close_file(char tmp[9])//关闭文件{unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode)){flag=0;while(fopen_table[flag]!=dir[k].inode)flag++;fopen_table[flag]=0;printf("File: %s! closed\n",tmp);}else printf("The file %s has not been opened!\n",tmp);}else printf("The file %s does not exist!\n",tmp);}void open_file(char tmp[9]){unsigned short flag,i,j,k;flag=reserch_file(tmp,1,&i,&j,&k);if(flag){if(search_file(dir[k].inode))printf("The file %s has opened!\n",tmp);else{flag=0;while(fopen_table[flag])flag++;fopen_table[flag]=dir[k].inode;printf("File %s! opened\n",tmp);}}else printf("The file %s does not exist!\n",tmp);}// formatvoid initialize_disk(){int i=0;printf("Creating the ext2 file system\n");printf("Please wait ");while(i<1){printf("... ");// sleep(1);i++;}printf("\n");last_alloc_inode=1;last_alloc_block=0;for(i=0;i<16;i++)fopen_table[i]=0;//清空缓冲表for(i=0;i<BLOCK_SIZE;i++)Buffer[i]=0;// 清空缓冲区,通过缓冲区清空文件,即清空磁盘fp=fopen("FS_zqw_zzw.txt","w+b");fseek(fp,DISK_START,SEEK_SET);for(i=0;i<4611;i++)fwrite(Buffer,BLOCK_SIZE,1,fp);//清空文件,即清空磁盘全部用0填充reload_group_desc();reload_inode_entry(1);reload_dir(0);strcpy(current_path,"[root@ /"); //该路径名strcpy(super_block[0].bg_volume_name,"EXT2FS"); //改卷名,初始化组描述符内容super_block[0].bg_block_bitmap=BLOCK_BITMAP;super_block[0].bg_inode_bitmap=INODE_BITMAP;super_block[0].bg_inode_table=INODE_TABLE;super_block[0].bg_free_blocks_count=4096;super_block[0].bg_free_inodes_count=4096;super_block[0].bg_used_dirs_count=0;// 初始化组描述符内容update_group_desc(); //更新组描述符内容reload_block_bitmap();reload_inode_bitmap();inode_area[0].i_mode=518;inode_area[0].i_blocks=0;inode_area[0].i_size=32;inode_area[0].i_atime=0;inode_area[0].i_ctime=0;inode_area[0].i_mtime=0;inode_area[0].i_dtime=0;inode_area[0].i_block[0]=alloc_block();inode_area[0].i_blocks++;current_dir=get_inode();update_inode_entry(current_dir);dir[0].inode=dir[1].inode=current_dir;dir[0].name_len=0;dir[1].name_len=0;dir[0].file_type=dir[1].file_type=2;//1:文件;2:目录strcpy(dir[0].name,".");strcpy(dir[1].name,"..");update_dir(inode_area[0].i_block[0]);printf("The ext2 file system has been installed!\n");}void initialize_memory(){int i=0;last_alloc_inode=1;last_alloc_block=0;for(i=0;i<16;i++)fopen_table[i]=0;strcpy(current_path,"[root@ /");current_dir=1;fp=fopen("FS_zqw_zzw.txt","r+b");if(fp==NULL){printf("The File system does not exist!\n");initialize_disk();return ;}reload_group_desc();}void format(){initialize_disk();initialize_memory();}void help(){printf(" ext文件系统模拟\n");printf(" 可以使用的命令: \n");printf(" 1.进入文件目录: cd+dir_name 7.创建文件目录: mkdir+dir_name \n");printf(" 2.创建文件: mkf+file_name 8.删除目录: rmdir+dir_name \n");printf(" 3.删除文件: rm+file_name 9.读取文件: read+file_name \n");printf(" 4.打开文件: open+file_name 10.写文件: write+file_name \n");printf(" 5.关闭文件: close+file_name 11.退出: quit \n");printf(" 6.列出项目: ls 12.查看帮助: help \n");printf(" 13.format disk : format \n");}// mainint main(char argc,char **argv){char command[10],temp[9];initialize_memory();printf("输入help查看帮助\n");while(1){printf("%s]#",current_path);scanf("%s",command);if(!strcmp(command,"cd")){scanf("%s",temp);cd(temp);}else if(!strcmp(command,"mkdir")) {scanf("%s",temp);mkdir(temp,2);}else if(!strcmp(command,"mkf")) {scanf("%s",temp);mkdir(temp,1);}else if(!strcmp(command,"rmdir")) {scanf("%s",temp);rmdir(temp);}else if(!strcmp(command,"rm")) {scanf("%s",temp);del(temp);}else if(!strcmp(command,"open")) {scanf("%s",temp);open_file(temp);}else if(!strcmp(command,"close")) {scanf("%s",temp);close_file(temp);}else if(!strcmp(command,"read")) {scanf("%s",temp);read_file(temp);}else if(!strcmp(command,"write")) {scanf("%s",temp);write_file(temp);}else if(!strcmp(command,"ls"))ls();else if(!strcmp(command,"format")){char tempch;printf("Format will erase all the data in the Disk\n");printf("Are you sure?y/n:\n");scanf(" %c",&tempch);if(tempch=='Y'||tempch=='y'){fclose(fp);initialize_disk();}elseprintf("Format Disk canceled\n");}else if(!strcmp(command,"help"))help();else if(!strcmp(command,"quit"))break;else printf("No this Command,Please check!\n");}return 0;}。