操作系统(2)实验四
操作系统 课程实验-实验四页式虚拟存储管理中地址转换和缺页中断

实验四页式虚拟存储管理中地址转换和缺页中断一、实验目的深入了解页式存储管理如何实现地址转换;进一步认识页式虚拟存储管理中如何处理缺页中断。
二、实验预备知识页式存储管理中地址转换的方法;页式虚拟存储的缺页中断处理方法。
三、实验内容编写程序完成页式虚拟存储管理中地址转换过程和模拟缺页中断的处理。
实验具体包括:首先对给定的地址进行地址转换工作,若发生缺页则先进行缺页中断处理,然后再进行地址转换;最后编写主函数对所做工作进行测试。
假定主存64KB,每个主存块1024字节,作业最大支持到64KB,系统中每个作业分得主存块4块。
四、提示与讲解页式存储管理中地址转换过程很简单,假定主存块的大小为2n字节,主存大小为2m'字节和逻辑地址m位,则进行地址转换时,首先从逻辑地址中的高m-n位中取得页号,然后根据页号查页表,得到块号,并将块号放入物理地址的高m'-n位,最后从逻辑地址中取得低n位放入物理地址的低n位就得到了物理地址,过程如图6所示。
逻辑地址图6 页式存储管理系统地址转换示意图地址转换是由硬件完成的,实验中使用软件程序模拟地址转换过程,模拟地址转换的流程如图7所示(实验中假定主存64KB,每个主存块1024字节,即n=10,m'=16,物理地址中块号6位、块内地址10位;作业最大64KB,即m=16,逻辑地址中页号6位、页内地址10位)。
在页式虚拟存储管理方式中,作业信息作为副本放在磁盘上,作业执行时仅把作业信息的部分页面装入主存储器,作业执行时若访问的页面在主存中,则按上述方式进行地址转换,若访问的页面不在主存中,则产生一个“缺页中断”,由操作系统把当前所需的页面装入主存储器后,再次执行时才可以按上述方法进行地址转换。
页式虚拟存储管理方式中页表除页号和该页对应的主存块号外,至少还要包括存在标志(该页是否在主存),磁盘位置(该页的副本在磁盘上的位置)和修改标志(该页是否修改过)。
操作系统实验04 Linux 多进程编程

《操作系统》实验报告实验序号:实验四实验项目名称:实验04 Linux 多进程编程学号1207022103 姓名陈华荣专业、班网络工程实验地点实1-311 指导教师李桂森实验时间2014.10.26一、实验目的及要求1.通过本实验的学习,使学生掌握Linux多进程编程的基本方法。
2.实验内容:利用Linux多进程实现题目所要求的功能。
3.以学生自主训练为主的开放模式组织教学二、实验设备(环境)及要求PC机三、实验内容与步骤1、编写一个显示“HELLO”的c语言程序,并利用GCC编译,然后运行此程序。
(提示:若没有gcc,需先安装gcc编译程序)指令:Apt-get install updateApt-get install gccCd /home/normaluesrTouch helloworld.cVim helloeorld.c在helloworld里编辑进:#include<stdio.h>Int main(){Printf(“helloworld”);Return 0;}然后用gcc进行编译运行:或者直接2、进程的创建:编制一程序,利用系统调用fork()创建两个子进程。
程序运行时,系统中有一个父进程和两个子进程活动,分别让他们显示“A”、“B”和“C”,分析程序运行结果。
3、用ctrl+alt+F2切换到第二个终端(tty2)并使用另外一个用户登录(可利用第二个实验创建的用户登录),然后使用who命令查看用户登录情况。
用ctrl+alt+F1切换到第二个终端(tty1),修改第二步的程序,在每个进程退出前都加上一个sleep(20)的函数来延缓进程的退出,然后运行此程序,立即切换到tty2,使用ps -a命令查看系统运行的进程,观察程序创建的进程都有哪些?pid是多少?4、进程的管道通信:编制一程序,使用系统调用pipe()建立一管道,两个子进程P1和P2分别向管道各写一句话,父进程则从管道中读取出来并显示在屏幕。
操作系统原理实验四

实验4 进程控制1、实验目的(1)通过对WindowsXP进行编程,来熟悉和了解系统。
(2)通过分析程序,来了解进程的创建、终止。
2、实验工具(1)一台WindowsXP操作系统的计算机。
(2)计算机装有Microsoft Visual Studio C++6.0专业版或企业版。
3、预备知识(3)·CreateProcess()调用:创建一个进程。
(4)·ExitProcess()调用:终止一个进程。
4、实验编程(1)编程一利用CreateProcess()函数创建一个子进程并且装入画图程序(mspaint.exe)。
阅读该程序,完成实验任务。
源程序如下:# include < stdio.h ># include < windows.h >int main(VOID)﹛STARTUPINFO si;PROCESS INFORMA TION pi;ZeroMemory(&si,sizeof(si));Si.cb=sizeof(si);ZeroMemory(&pi,sizeof(pi));if(!CreateProcess(NULL,“c: \ WINDOWS\system32\ mspaint.exe”,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))﹛fprintf(stderr,”Creat Process Failed”);return—1;﹜WaitForSingleObject(pi.hProcess,INFINITE);Printf(“child Complete”);CloseHandle(pi.hProcess);CloseHandle(pi hThread);﹜在“命令提示符”窗口运行CL命令产生可执行程序4-1.exe:C:\ >CL 4-1.cpp实验任务:写出程序的运行结果。
操作系统(二)实验报告_上海大学计算机与科学系

操作系统(二)实验报告姓名:米博计算机工程与科学学院实验四 Linux文件系统实验一. 实验目的掌握操作系统中文件分类的概念。
了解Linux文件系统管理文件的基本方式和特点。
学会使用Linux文件系统的命令界面和程序界面的基本要领。
二.实验准备复习操作系统中有关文件系统的知识,熟悉文件的类型、i节点、文件属性、文件系统操作等概念。
熟悉《实验指导》第五部分“文件系统的系统调用”。
了解Linux文件系统的特点、分类。
阅读例程中给出的相应的程序段。
三.实验方法运行命令界面的各命令并观察结果。
用vi编写c程序(假定程序文件名为prog1.c)编译程序$gcc –o prog1.o prog1.c或$cc –o prog1.o prog1.c运行$./prog1.o观察运行结果并讨论。
四.实验内容及步骤1. 用shell命令查看Linux文件类型。
思考:Linux文件类型有哪些?用什么符号表示。
答:文件类型:没有后缀的文件、可执行文件、可读写的文本文件。
.conf —某个程序的配置文件.c — C语言程序源码文件.so —动态链接库文件.tcl — TCL脚本文件.cpp — C++语言程序源码文件.h — C或C++语言的头文件.o —程序对象文件.pl — Perl脚本文件.sh —shell批处理文件2. 用shell命令了解Linux文件系统的目录结构。
执行$ cd /lib$ ls -l|more看看/lib目录的内容,显示的函数都是系统函数。
再看看/etc,这里都是系统设置用的配置文件:/bin中是可执行程序;/home下包括了每个用户主目录。
3. 用命令分别建立硬链接文件和符号链接文件。
通过ls –il命令所示的inode、链接计数观察它们的区别。
找找一个其他目录中的文件,如:/home/zzl/mytese.c执行$ ln /home/zzl/mytest.c myt.c (建立硬链接文件)$ ln –s /home/zzl/mytest.c myt2.c (建立符号链接文件)思考:建立硬链接文件和建立符号链接文件有什么区别,体现在哪里?答:硬链接文件就是给文件取另外一个名字,链接使用inode是与元文件相同的。
操作系统实验四设备管理

图4-1 Lab4_1运行结果讨论:如输入磁盘号为C,显示的磁盘信息是整个硬盘信息,而不是C盘分区的信息。
如输入磁盘号为D,显示的磁盘信息与如输入磁盘号为C显示的磁盘信息相同。
用磁盘I/O API函数读出的磁盘信息是从硬盘的主引导区得到。
六、实验心得体会通过本次实验,我了解了磁盘的物理组织,不同磁盘不同的物理构造,如SSD和HDD,了解了其特点,以及如何通过用户态的程序直接调用磁盘I/O API函数(DeviceIoControl),使程序可以根据输入的驱动器号读取驱动器中磁盘的基本信息。
本次实验调试过程的前半段,我是使用Windows 10进行的,遇到了一些类型转化以及无输出的问题,纠结了很久没有弄出来,但是在Windows Server 2016中,没有任何问题,可以直接运行。
以后调试程序应尽量在目标机器上调试,防止出现问题。
附录程序清单清单4-11.#include <windows.h>2.#include <iostream>ing namespace std;4.#include <winioctl.h>5.#include <string.h>6.7.struct Disk //关于 Disk 结构的定义8.{9.HANDLE handle;10. DISK_GEOMETRY disk_info;11.};12.13.Disk disk;14.HANDLE Floppy;15.static _int64 sector;16.bool flag;17.Disk physicDisk(char driverLetter);18.19.void main(void)20.{21.char DriverLetter;22. cout << "请输入磁盘号:a/c" << endl;23. cin >> DriverLetter;//选择要查看的磁盘24. disk = physicDisk(DriverLetter);25.}26.27.Disk physicDisk(char driverLetter) //28.{29. flag = true;30. DISK_GEOMETRY* temp = new DISK_GEOMETRY;31.char device[9] = "\\\\.\\c:";32. device[4] = driverLetter;33. Floppy = CreateFile(device, //将要打开的驱动器名34. GENERIC_READ, //存取的权限35. FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享的权限36. NULL, //默认属性位37. OPEN_EXISTING, //创建驱动器的方式38. 0, //所创建的驱动器的属性39. NULL); //指向模板文件的句柄40.if (GetLastError() == ERROR_ALREADY_EXISTS) //如打开失败,返回错误代码41. {42. cout << "不能打开磁盘" << endl;43. cout << GetLastError() << endl;44. flag = false;45.return disk;46. }47.48.DWORD bytereturned;49.BOOL Result;50. disk.handle = Floppy;51. Result = DeviceIoControl(Floppy,52. IOCTL_DISK_GET_DRIVE_GEOMETRY,53. NULL,54. 0,55. temp,56.sizeof(*temp),57. &bytereturned,58. (LPOVERLAPPED)NULL);59.if (!Result) //如果失败,返回错误代码60. {61. cout << "打开失败" << endl;62. cout << "错误代码为:" << GetLastError() << endl;63. flag = false;64.return disk;65. }66.67. disk.disk_info = *temp;//输出整个物理磁盘的信息68. cout << driverLetter << "盘有: " << endl;69. cout << "柱面数为:" << (unsigned long)disk.disk_info.Cylinders.QuadPart << endl;70. cout << "每柱面的磁道数为:" << disk.disk_info.TracksPerCylinder << endl;71. cout << "每磁道的扇区数为:" << disk.disk_info.SectorsPerTrack << endl;72. cout << "每扇区的字节数为:" << disk.disk_info.BytesPerSector << endl;73. sector = disk.disk_info.Cylinders.QuadPart * (disk.disk_info.TracksPerCylinder) * (disk.disk_info.SectorsPerTrack);74.double DiskSize = (double)disk.disk_info.Cylinders.QuadPart * (disk.disk_info.TracksPerCylinder) * (disk.disk_info.SectorsPerTrack) * (disk.disk_info.BytesPerSector);75. cout << driverLetter << "盘所在磁盘总共有" << (long)sector << "个扇区" << endl;76. cout << "磁盘大为:" << DiskSize / (1024 * 1024) << "MB " << endl;77.delete temp;78.return disk;79.}。
实验四 操作系统存储管理实验报告

实验四操作系统存储管理实验报告一、实验目的本次操作系统存储管理实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配、回收、地址转换等关键技术,提高对操作系统存储管理机制的认识和应用能力。
二、实验环境操作系统:Windows 10开发工具:Visual Studio 2019三、实验原理1、内存分配方式连续分配:分为单一连续分配和分区式分配(固定分区和动态分区)。
离散分配:分页存储管理、分段存储管理、段页式存储管理。
2、内存回收算法首次适应算法:从内存低地址开始查找,找到第一个满足要求的空闲分区进行分配。
最佳适应算法:选择大小最接近作业需求的空闲分区进行分配。
最坏适应算法:选择最大的空闲分区进行分配。
3、地址转换逻辑地址到物理地址的转换:在分页存储管理中,通过页表实现;在分段存储管理中,通过段表实现。
四、实验内容及步骤1、连续内存分配实验设计一个简单的内存分配程序,模拟固定分区和动态分区两种分配方式。
输入作业的大小和请求分配的分区类型,程序输出分配的结果(成功或失败)以及分配后的内存状态。
2、内存回收实验在上述连续内存分配实验的基础上,添加内存回收功能。
输入要回收的作业号,程序执行回收操作,并输出回收后的内存状态。
3、离散内存分配实验实现分页存储管理的地址转换功能。
输入逻辑地址,程序计算并输出对应的物理地址。
4、存储管理算法比较实验分别使用首次适应算法、最佳适应算法和最坏适应算法进行内存分配和回收操作。
记录不同算法在不同作业序列下的内存利用率和分配时间,比较它们的性能。
五、实验结果与分析1、连续内存分配实验结果固定分区分配方式:在固定分区大小的情况下,对于作业大小小于或等于分区大小的请求能够成功分配,否则分配失败。
内存状态显示清晰,分区的使用和空闲情况一目了然。
动态分区分配方式:能够根据作业的大小动态地分配内存,但容易产生内存碎片。
2、内存回收实验结果成功回收指定作业占用的内存空间,内存状态得到及时更新,空闲分区得到合并,提高了内存的利用率。
实验四操作系统存储管理实验报告
实验四操作系统存储管理实验报告一、实验目的本次实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配与回收、页面置换算法等关键概念,并能够分析和解决存储管理中可能出现的问题。
二、实验环境本次实验在装有 Windows 操作系统的计算机上进行,使用了 Visual Studio 等编程工具和相关的调试环境。
三、实验内容(一)内存分配与回收算法实现1、首次适应算法首次适应算法从内存的起始位置开始查找,找到第一个能够满足需求的空闲分区进行分配。
在实现过程中,我们通过建立一个空闲分区链表来管理内存空间,每次分配时从表头开始查找。
2、最佳适应算法最佳适应算法会选择能够满足需求且大小最小的空闲分区进行分配。
为了实现该算法,在空闲分区链表中,分区按照大小从小到大的顺序排列,这样在查找时能够快速找到最合适的分区。
3、最坏适应算法最坏适应算法则选择最大的空闲分区进行分配。
同样通过对空闲分区链表的排序和查找来实现。
(二)页面置换算法模拟1、先进先出(FIFO)页面置换算法FIFO 算法按照页面进入内存的先后顺序进行置换,即先进入内存的页面先被置换出去。
在模拟过程中,使用一个队列来记录页面的进入顺序。
2、最近最久未使用(LRU)页面置换算法LRU 算法根据页面最近被使用的时间来决定置换顺序,最近最久未使用的页面将被置换。
通过为每个页面设置一个时间戳来记录其最近使用的时间,从而实现置换策略。
3、时钟(Clock)页面置换算法Clock 算法使用一个环形链表来模拟内存中的页面,通过指针的移动和页面的访问标志来决定置换页面。
四、实验步骤(一)内存分配与回收算法的实现步骤1、初始化内存空间,创建空闲分区链表,并为每个分区设置起始地址、大小和状态等信息。
2、对于首次适应算法,从链表表头开始遍历,找到第一个大小满足需求的空闲分区,进行分配,并修改分区的状态和大小。
3、对于最佳适应算法,在遍历链表时,选择大小最接近需求的空闲分区进行分配,并对链表进行相应的调整。
计算机操作系统实验四
计算机操作系统实验四计算机操作系统实验四一、实验目的本实验旨在通过实践,让学生熟悉并理解操作系统中进程调度和死锁的相关概念、算法和解决方法。
二、实验要求1.学习理解进程调度的基本概念和相关算法,包括先来先服务(FCFS)、短作业优先(SJF)、高响应比优先(HRRN)以及时间片轮转等算法。
2.掌握进程调度算法的实现原理和代码实现方法。
3.学习理解死锁的概念、产生原因以及解决方法,包括资源分配图法、银行家算法等。
4.掌握死锁相关算法的实现原理和代码实现方法。
5.进行相关实验操作,并记录实验结果和分析。
三、实验步骤1.进程调度实验1.1 实验环境配置在操作系统中配置相关环境,创建进程调度实验所需的实验环境,包括进程控制块(PCB)、进程队列、进程状态等。
1.2 先来先服务(FCFS)算法实现阐述先来先服务算法的实现原理,包括就绪队列、完成队列的管理和进程状态的切换。
1.3 短作业优先(SJF)算法实现阐述短作业优先算法的实现原理,包括作业调度表、就绪队列、完成队列的管理和进程状态的切换。
1.4 高响应比优先(HRRN)算法实现阐述高响应比优先算法的实现原理,包括计算响应比、优先级比较和进程状态的切换。
1.5 时间片轮转算法实现阐述时间片轮转算法的实现原理,包括设置时间片长度、就绪队列的管理和进程状态的切换。
1.6 实验结果分析运行各种进程调度算法,并记录实验结果,分析每种算法的优缺点和适用场景。
2.死锁实验2.1 死锁概念和产生原因阐述死锁的概念、产生原因,包括资源竞争、进程互斥、不可抢占和循环等。
2.2 资源分配图法实现阐述资源分配图法解决死锁的实现原理,包括资源分配图的构建和死锁检测算法的应用。
2.3 银行家算法实现阐述银行家算法解决死锁的实现原理,包括安全序列的判断和资源分配的策略。
2.4 实验结果分析运行资源分配图法和银行家算法,记录实验结果,分析算法的效果和应用场景。
四、实验结果及分析经过实验,我们得到了以下结果和分析:1.进程调度实验结果分析在不同的进程调度算法下,记录了各个进程在不同时刻的执行情况、等待时间和周转时间等指标。
操作系统实验四
一、实验名称实验四设备管理二、实验目的本实验着重于了解磁盘的物理组织,以及如何通过用户态的程序直接调用磁盘I/O API 函数(DeviceIoControl)根据输入的驱动器号读取驱动器中磁盘的基本信息,在Windows Server 2003环境进行。
三、实验内容(一)实验需求:(1)Windows Server 2003(2)Microsoft V isual Studio 2008(二)实验的内容:[1] 磁盘I/O API函数应用相关的API 介绍1.获取磁盘的基本信息的磁盘I/O API函数DeviceIoControl格式如下:BOOL DeviceIoControl( HANDLE hDevice, DWORD dwioControlCode,LPVOID lplnBuffer, DWORD nlnBufferSize,LPVOID lpOutBuffer, DWORD nOutBufferSize,LPDWORD lpBytesReturned,LPOVERLAPPED lpOverlapped );.hDevice:所要进行操作的设备的句柄,它通过调用CreateFile函数来获得。
.dwIoControlCode:指定操作的控制代码。
这个值用来辨别将要执行的指定的操作,以及对哪一种设备进行操作。
对磁盘应设置为IOCTL_DISK_GET_DRIVE_GEOMETRY。
.lpInBuffer:操作所要的输入数据缓冲区指针,NULL表示不需要输入数据。
.nInBufferSize:指定lpInBuffer所指向的缓冲区的大小(以字节为单位)。
.lpOutBuffer:接收操作输出的数据缓冲区指针,NULL表示操作没有产生输出数据。
输出数据的缓冲区要足够大,对磁盘它采用固定的数据结构DISK_GEOMETRY,格式如下:structDISK_GEOMETRY {unsigned bytesPerSector; unsigned sectorsPerTrack;unsigned heads; unsigned cylinders; }.nOutBufferSize:指定lpOutBuffer所指向的缓冲区的大小(以字节为单位)。
Windows操作系统实验四实验报告
Windows操作系统C/C++ 程序实验姓名:___________________学号:___________________班级:___________________院系:_________________________________年_____月_____日实验四Windows 2000/xp线程间通信一、背景知识二、实验目的三、工具/准备工作四、实验内容1. 文件对象步骤1:登录进入Windows 2000/xp Professional。
步骤2:在“开始”菜单中单击“程序”-“Microsoft Visual Studio 6.0”–“Microsoft Visual C++ 6.0”命令,进入Visual C++窗口。
步骤3:在工具栏单击“打开”按钮,在“打开”对话框中找到并打开实验源程序4-1.cpp。
步骤4:单击“Build”菜单中的“Compile 4-1.cpp”命令,并单击“是”按钮确认。
系统对4-1.cpp进行编译。
步骤5:编译完成后,单击“Build”菜单中的“Build 4-1.exe”命令,建立4-1.exe可执行文件。
操作能否正常进行?如果不行,则可能的原因是什么?____________________________________________________________________ ________________________________________________________________________步骤6:在工具栏单击“Execute Program”按钮,执行4-1.exe程序。
运行结果(如果运行不成功,则可能的原因是什么?) :____________________________________________________________________ ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________阅读和分析程序4-1,请回答问题:1) 清单4-1中启动了多少个单独的读写线程?____________________________________________________________________2) 使用了哪个系统API函数来创建线程例程?____________________________________________________________________3) 文件的读和写操作分别使用了哪个API函数?____________________________________________________________________ ________________________________________________________________________每次运行进程时,都可看到清单4-3中的每个线程从前面的线程中读取数据并将数据增加,文件中的数值连续增加。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统(2)实验四实验四文件操作与管理一、实验环境Visual C++二、实验目的随着社会信息量的极大增长,要求计算机处理的信息与日俱增,涉及到社会生活的各个方面。
因此,文件管理是操作系统的一个极为重要的组成部分。
学生应独立地用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。
从而对各种文件操作命令的实质内容和执行过程有比较深入的了解,掌握它们的实施方法,加深理解课堂上讲授过的知识。
三、实验要求(1)实际一个n个用户的文件系统,每个用户最多可保存m个文件。
(2)限制用户在一次运行中只能打开l个文件。
(3)系统应能检查打入命令的正确性,出错要能显示出错原因。
(4)对文件必须设置保护措施,如只能执行,允许读、允许写等。
在每次打开文件时,根据本次打开的要求,再次设置保护级别,即可有二级保护。
(5)对文件的操作至少应有下述几条命令:creat 建立文件。
delete 删除文件。
open 打开文件。
close 关闭文件。
read 读文件。
write 写文件。
四、实验内容(1)本实习设计一个10 个用户的文件系统,每个用户最多可保存10 个文件,一次运行中用户可打开 5 个文件。
(2)程序采用二级文件目录,即设置了主文件目录(MFD)和用户文件目录(UFD)。
前者应包含文件主(即用户)及他们的目录区指针;后者应给出每个文件主占有的文件目录,即文件名,保护码,文件长度以及他们存放的位置等。
另外为打开文件设置了运行文件目录(AFD),在文件打开时应填入打开文件号,本次打开保护码和读写指针等。
(3)为了便于实现,对文件的读写作了简化,在执行读写命令时,只修改读写指针,并不进行实际文件的读写操作。
五、设计思路1.因系统小,文件目录的检索使用了简单的线性搜索,而没有采用Hash等有效算法。
2.文件保护简单实用了三位保护码,对应于允许读、允许写和运行执行,如下所示:1 1 1允许写允许读允许执行如对应位为0,则不允许。
3.程序中使用的主要数据结构如下:①主文件目录和用户文件目录打开文件目录:4.程序框图:六、实验过程1.整个程序运行过程如下:输入用户名—>在MFD中查找—>显示UFD文件链表—>初始化AFD运行文件表—>输入操作命令—>执行操作命令—>保存文件目录—>打印文件目录—>结束2.MFD、UFD和AFD的结构定义如下:struct UFD{string filename;int pro[3];int codel;UFD *next;};struct MFD{string username;UFD *file;MFD *next;};struct AFD{int filenum;char filepro[3];UFD *point;AFD *next;};3.void init( ) 初始化函数将文件链表变成循环链表,方便执行插入和删除操作。
4.int checkUser( ) 检查用户检查输入的用户名是否在用户文件目录中。
5.void Create ( ) 创建一个文件选择CREATE命令后,查看该用户的UFD链表内是否还有空闲结点:(1)若有则设置该结点的内容,然后打开、修改AFD;(2)若无则报错并退出。
6.void Open( ) 打开一个文件选择OPEN命令后,输入要打开的文件名,在UFD查找是否有该文件名:(1)若有则打开并修改AFD;(2)若无则报错并退出。
7.void Close( ) 关闭一个文件选择CLOSE命令后,输入需要关闭的文件名,在UFD中搜索是否有该文件名。
(1)若无则报错;(2)若有,还要分两种情况:●通过检查,该文件并未被打开,则报错●存在该文件,且被打开,则正常调用void Close1(AFD *f),关闭文件。
8.void Delete( ) 删除一个文件选择DELETE命令后,输入需要删除的文件名,在UFD中搜索是否有该文件名:(1)若无则报错;(2)若有,还要分两种情况:●通过检查,该文件已被打开,则需要先关闭该文件,确定需要关闭该文件后,通过调用void Close1(AFD *f),关闭文件,然后删除该文件。
●存在该文件,且未被打开,则课正常删除该文件,即重新初始化该文件的UDF结点。
9.void Read( ) 读一个文件读文件的关键是保护码的判断。
选择了READ命令后,输入需要读的文件名,在UFD中搜索是否有该文件名:(1)若有,但该文件没被打开,则报错;(2)若有,且已被打开,此处要分两种情况:●如果保护码的读位为“0”,则不能对该文件进行读操作。
●否则,就通过文件号来读文件,即通过AFD中的point指针来查找该文件。
10.void Write( ) 写一个文件写文件的关键也是保护码的判断。
选择了WRITE命令后,输入需要读的文件名,在UFD中搜索是否有该文件名:(1)若有,但该文件没被打开,则报错;(2)若有,且已被打开,此处要分两种情况:●如果保护码的写位为‘0’,则不能对该文件进行写操作。
●否则,就可以通过文件号来写文件,即通过AFD中的point指针来查找。
11.Bye 退出选择了BYE命令后,程序退出并保存当前目录,然后将结果打印出来。
程序运行结果1.用户验证2.创建文件3.关闭、打开文件4.删除文件5.读写文件6.退出七、感想体会实验四主要是通过链表来实现对文件的管理的,要求设计一个10 个用户的文件系统,每个用户最多可保存10 个文件,一次运行中用户可打开 5 个文件。
程序采用了二级文件目录,设置了主文件目录和用户文件目录,另外为打开文件设置了运行文件目录,在文件打开时应填入打开文件号,本次打开保护码和读写指针。
在执行各种文件操作命令的时候,需要考虑多种情况,比如读写文件的时候就要考虑文件的保护码,以及该文件是否已被打开的问题;创建命令时要在用户的文件目录中寻找空闲的文件结点,即没有被使用的文件,对其进行文件名、保护码、文件长度的设置;删除命令就要考虑是否有这个文件,再查看此文件是否被打开,如果已经被打开,则要先关闭该文件,在进行删除,删除即对此文件结点进行初始化操作等等。
想清楚各项操作的分类情况之后,对每个函数进行编写就容易多了。
本次试验模拟了文件的管理操作,虽然只是一个小小的程序,也让我大致了解了计算机对于文件的管理是如何进行的。
由于是通过链表的操作实现的,也使我巩固了C++中的链表操作过程。
实验源代码:#include<iostream>#include<cstring>#include <iomanip>using namespace std;stringa[10]={"Carol","Lily","Lucy","Bob","A","B ","C","D","E","F"};stringcommand[7]={"CREATE","DELETE","OPEN","CLO SE","READ","WRITE","BYE"};struct UFD{string filename;int pro[3];int codel;UFD *next;};struct MFD{string username;UFD *file;MFD *next;};struct AFD{int filenum;char filepro[3];UFD *point;AFD *next;};AFD *openfile=NULL;MFD *user=NULL;MFD *thisuser; //当前用户void init() //初始化函数{int x=0;for(int i=0;i<10;i++){MFD *p;p=new MFD;p->username=a[x];UFD *fhead=NULL;for(int j=0;j<10;j++){UFD *q;q=new UFD;q->filename="******";for(int a=0;a<3;a++){q->pro[a]=0;}q->codel=0;q->next=fhead;fhead=q;p->file=fhead;if(j==9) //变成循环链表{UFD *r=fhead;while(r->next!=NULL){r=r->next;}r->next=fhead;}}p->next=user;user=p;x++;}//AFD的初始化for(int i=0;i<5;i++){AFD *f;f=new AFD;f->filenum=5-i;for(int j=0;j<3;j++){f->filepro[j]=0;}f->point=NULL;f->next=openfile;openfile=f;if(i==4) //打开文件链表设为循环链表{AFD *p=openfile;while(p->next!=NULL){p=p->next;}p->next=openfile;}}}int checkUser(string username){MFD *p;for(p=user;p!=NULL;p=p->next){if(p->username==username){break;} }if(p!=NULL){thisuser=p;return 1;}else{return 0;}}void show(){cout<<"YOUR FILE DIRECTORY"<<endl;cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<"FILE NAME";cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<"PROTECTION";cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<"CODE LENGTH"<<endl;MFD *p=thisuser;UFD *q=p->file;for(int i=0;i<10;i++){cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<q->filename;cout<<q->pro[0]<<q->pro[1]<<q->pro[2];cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<" ";cout<<setw(20)<<setiosflags(ios::left)< <setfill(' ')<<q->codel<<endl;q=q->next;}}void OpenMode(UFD *p,string name){AFD *f=openfile;int i;for(i=0;i<5;i++){if(f->point!=NULL&&f->point->filename== name){cout<<"THIS FILE IS ALREADY OPENED!"<<endl;return;}f=f->next;}for(i=0;i<5;i++){if(f->point==NULL)break;f=f->next;}if(i==5){cout<<"ERROR!YOU CAN'T OPEN THIS FILE,NUMBER MUST <=5!";}else{cout<<"ENTER THE OPEN MODE? ";string protect;cin>>protect;int j;for(j=0;j<3;j++){if(p->pro[j]!=protect[j]-48)break;}if(j!=3){cout<<"ERROR,OPEN MODE IS WRONG!"<<endl;return;}else{cout<<"THIS FILE IS OPENED,ITS OPEN NUMBER IS ";cout<<f->filenum<<endl;f->point=p;for(int j=0;j<3;j++){f->filepro[j]=p->pro[j];}}}return;}void Create(){cout<<"THE NEW FILE S NAME(LESS THAN 9 CHARS)? ";string name;cin>>name;cout<<"THE NEW FILE’S PROTECTION CODE? ";string protect;cin>>protect;UFD *p=thisuser->file;UFD *q=p;int n;for(n=0;n<10;n++){if(q->filename=="******")break;q=q->next;}if(n==10){cout<<"CREAT FAILED!!THERE IS NO SPACE,FILE NUMBERMUST<=10!"<<endl;return;}else{q->filename=name;for(int i=0;i<3;i++){q->pro[i]=protect[i]-48;}}cout<<"THE NEW FILE IS CREATED."<<endl;OpenMode(q,name);return ;}void Open(){cout<<"FILE NAME TO BE OPENED? ";string name;cin>>name;UFD *p=thisuser->file;UFD *q=p;int n;for(n=0;n<10;n++){if(q->filename==name)break;q=q->next;}if(n==10){cout<<"ERROR!THIS FILE IS NOT EXISTS!"<<endl;return;}else{OpenMode(q,name);}return ;}void Close1(AFD *f){f->point=NULL;for(int i=0;i<3;i++){f->filepro[i]=0;}cout<<"SUCCESS!THIS FILE IS CLOSED!"<<endl;return;}void Close(){cout<<"CLOSE THE FILE'S NAME: ";string name;cin>>name;UFD *p=thisuser->file;UFD *q=p;int n;for(n=0;n<10;n++){if(q->filename==name)break;q=q->next;}if(n==10){cout<<"ERROR!CAN'T FIND THIS FILE!"<<endl;return;}else{AFD *f=openfile;int i;for(i=0;i<5;i++){if(f->point==q)break;f=f->next;}if(n==5){cout<<"ERROR!THIS FILE IS NOT OPENED!"<<endl;return;}\else{Close1(f);}}return;}void Delete(){cout<<"DELETE FILENAME? ";string name;cin>>name;UFD *p=thisuser->file;UFD *q=p;int n;for(n=0;n<10;n++){if(q->filename==name)break;q=q->next;}if(n==10){cout<<"ERROR!CAN'T FIND THIS FILE!"<<endl;return;}else{AFD *f=openfile;int i;for(i=0;i<5;i++){if(f->point==q){cout<<"ERROR!THIS FILE IS OPENED! CLOSED IT?(Y/N)"<<endl;char y;cin>>y;if(y=='Y'){Close1(f);break;}else return;}f=f->next;}q->filename="******";q->codel=0;for(int x=0;x<3;x++){q->pro[x]=0;}cout<<"SUCCESS!THIS FILE IS BE DELETED! "<<endl;}return;}void Read(){cout<<"OPEN FILE NUMBER? ";int num;cin>>num;AFD *f=openfile;int i;for(i=0;i<5;i++){if(f->filenum==num&&f->point!=NULL)brea k;f=f->next;}if(i==5){cout<<"ERROR!THIS FILE IS NOT OPENED!"<<endl;return;}else{if(f->filepro[0]==1){cout<<"SUCCESS!REA DING!"<<endl;}else{cout<<"ERROR!THIS FILE CAN'T READ WITH READING RIGHT LIMITED!"<<endl;} }return;}void Write(){cout<<"OPEN FILE NUMBER? ";int num;cin>>num;AFD *f=openfile;int i;for(i=0;i<5;i++){if(f->filenum==num&&f->point!=NULL)brea k;f=f->next;}if(i==5){cout<<"ERROR!THIS FILE IS NOT OPENED!"<<endl;return;}else{if(f->filepro[1]==1){cout<<"HOW MANY CHARACTERS TO BE WRITTEN INTO THAT FILE? ";int code;cin>>code;f->point->codel=code;}else{cout<<"ERROR!THIS FILE CAN'T WRITE WITH WRITING RIGHT LIMITED!"<<endl;} }return;}void FileWork(int com){if(com==1){Create();}//执行createif(com==2){Delete();}//执行deleteif(com==3){Open();} //执行openif(com==4){Close();}//执行closeif(com==5){Read();}//执行readif(com==6){Write();}//执行writeif(com==7){cout<<"NOW YOUR FILE DIRECTORY IS FOLLOWING:"<<endl;show();} //执行byereturn;}int main(){cout<<"RUN"<<endl;init(); //初始化int x=0;while(x==0){cout<<"YOUR NAME?"<<" ";string username;cin>>username;x=checkUser(username);if(x==0)cout<<"YOUR NAME IS NOT IN THE USER NAME TABLE,TRY AGAIN."<<endl;}show();int com=0;while(com!=7){cout<<"COMMAND NAME? ";string s;cin>>s;int i;for(i=0;i<7;i++){if(s==command[i]){com=i+1;break;} }if(i==7){cout<<"COMMAND NAME GIVEN IS WRONG!"<<endl;cout<<"IT SHOULD BE ONE OF FOLLOWING : "<<endl;cout<<"CREATE, DELETE, OPEN, CLOSE, READ, WRITE, BYE .TRY AGAIN"<<endl;continue;}else{FileWork(com);}}return 0;}。