1、操作系统课程设计一、 课程设计目的本设计的目的是实现操作系统和相关系统软件的设计,其中涉及进程编程、I/O 操作、存 储 管理、文件系 统等操作系统概念。二、 课程设计要求(1)对进行认真分析,列出实验具体步骤,写出符合题目要求的程序清单,准备出调试程序使用的数据。(2)以完整的作业包的形式提交原始代码、设计文档和可运行程序。提交的光盘应当包括:设计题目,程序清单,运行 结果分析,所选取的算法及其优缺点,以及通过上机取得了哪些经验。程序清单要求格式规范,注意加注释(包含关键字、方法、变量等),在每个模块前加注释,注 释不得少于 20%。课程设计要求同时上交打印文档,设计报告包括设计题目,算法分
2、析,关键代码及其数据结构说明,运行结果分析以及上机实践的经验总结。设计一:设计任务:模拟 Linux 文件系统在任一 OS 下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的模拟 Linux 文件系统。1. 在现有机器硬盘上开辟 100M 的硬盘空间,作 为设定的硬盘空间。2. 编写一管理程序 simdisk 对此空间进行管理,以模拟 Linux 文件系统,要求:(1( 盘块大小 1k (2( 空闲盘块的管理:Linux 位图法(3( 结构:超级块, i 结点区, 根目录区3. 该 simdisk 管理程序的功能要求如下:(1) info: 显 示整个系统信息 (参考 Linux 文件
3、系统 的系统信息) ,文件可以根据用户进行读写保护。目录名和文件名支持全路径名和相对路径名,路径名各分量间用“/”隔开。(2) cd : 改变目录:改变当前工作目录,目录不存在时给出出错信息。(3) dir : 显示目录:显示指定目录下或当前目录下的信息,包括文件名、物理地址、保护码、文件长度、子目 录等(带/s 参数的 dir 命令,显示所有子目录)。(4) md : 创建目录:在指定路径或当前路径下创 建指定目录。重名 时给出错信息。(5) rd : 删除目录:删除指定目录下所有文件和子目录。要删目录不空时,要给出提示是否要删除。(6) newfile : 建立文件。(7) cat : 打
4、开文件。(8) copy : 拷贝文件,除支持模拟 Linux 文件系 统内部的文件拷贝外, 还支持 host 文件系统与模拟 Linux 文件系统间的文件拷贝,host 文件系统的文件命名为,如:将 windows 下 D:盘的文件datasampletest.txt 文件拷贝到模拟 Linux 文件系统中的/test/data 目录,windows 下 D:盘的当前目录为 D:data,则使用命令:simdisk copy D:datasampletest.txt /test/data或者:simdisk copy D:sampletest.txt /test/data(9) del :
5、删除文件:删除指定文件,不存在 时给出出错信息。(10)check: 检测并恢复文件系统:对文件系统中的数据一致性进行检测,并自动根据文件系统的结构和信息进行数据再整理。4. 程序的总体流程为:(1) 初始化文件目录;(2) 输出提示符,等待接受命令,分析键入的命令;(3) 对合法的命令,执行相应的处理程序,否 则输出错误信息, 继续等待新命令,直到键入 EXIT 退出为止。设计二:设计任务:模拟文件系统的前端操作 shell实现一个简单的 shell(命令行解释器)。将设计一的管理程序 simdisk 作为后台进程运行,利用本设计任务的 shell操作 simdisk。本设计任务在于学会如何
6、实现在前端的 shell 进程和后端的 simdisk 进程之间利用共享内存进行进程间通信(IPC)。设计三:设计任务:模拟文件系统的操作管理实现多个进程同时对模拟文件系统进行操作。设计管理程序 simdisk 的用户访问权限管理。访问模拟文件系统的每个进程都属于某个用户,管理程序simdisk 根据其 访问权限决定其 对模拟文件系统的操作。对模拟文件系统的操作要求做到:共享读,互斥写。本设计任务在于学会如何实现信息的安全管理和进程同步。注:要求从课程设计的整体来考虑设计任务一、二、三,并分阶段实现。三、 开发环境Windows 7Microsoft visual studio 2008四、
7、主要实现过程1. 概要设计对于开闭 100MB 的使用空 间, 对此的理解应该是除了磁盘信息描述意外的数据储存区域都需要 1024*1024*100 的空间,故需要在主机生成固定大小的文件来模拟磁盘。Linux 的位图法管理空闲的盘块,要求使用以下结构:超级块、inode 结点区、根目录区。同时, 对于一个磁盘,肯定需要有一个存储区域来保存其整体信息,以便统计以及错误 修正,而 这个区域保存在磁 盘起始位置为最佳。将这些结构存储于文件中,直接想到的方案是建立对应的类,并用二进制文件直接将整个类写进文件,通 过文件指针的移动,可以将所有结构直接进行保存和读取,相对于按变量保存和读取的出错率将大大
8、降低。如果将这些内容也保存到文件,则生成的模 拟磁盘文件实际大小必定大于 100MB。其文件设计如下:数据块组inode 结点位图inode 结点表数据块位图根目录数据(100MB )另外,根据题目要求,需要从整体来考虑设计一、二、三,故为了控制不同的用户访问,定义一个用 户类也是必须的。并且要根据不同的用户给予不同的访问权限。所以整个系统的访问流程如下图所示:2. 主要算法及数据结构说明一些简单的数据结构:超级块:记录系统的一些重要数据,每个数据块组都有超级块,系统启动时只将第 0 块的数据块组的超级块读入内存,每次修改 时 更新所有数据块组并写回硬盘,所以一般不会出错 。struct su
9、per_blockunsigned int s_inodes_count; /inode 的总数unsigned int s_blocks_count; /盘块的总数unsigned int s_log_block_size; /盘块的大小开始装载文件系统不存在 格式化化等待输入命令分析命令进行相应的操作,直到输入 exit退出格式化unsigned int s_free_blocks_count; /空闲块的总数unsigned int s_free_inodes_count; /空闲inode的总数unsigned int s_first_data_block; /第一个数据块unsign
10、ed int s_blocks_per_group; /每组的盘块数unsigned int s_inodes_per_group; /每组的inode数;组描述符:描述各个数据块组的信息,和超级块一起构成了数据块组struct group_descunsigned long bg_block_addr; /本组数据块在数据区的首地址unsigned int bg_block_bitmap; /本组数据块位图所在的块号unsigned int bg_inode_bitmap; /本组inode 位图所在的块号unsigned int bg_inode_table; /本组inode 表所在的块
11、号unsigned int bg_free_blocks_count; /组中空闲块的数目unsigned int bg_free_inodes_count; /组中空闲inode 的数目;inode节点:描述文件的属性,一个文件 对应一个 inode,inode 数目和数据块数目一样多,即表示如果每个文件都只有一个数据块这么大,则可以有和数据块一样多的文件存在;不过本系统的 inode 和 Linux 的有点不同,就是记录地址的是文件的首地址,因为本系 统的文件在数据区是连续存放的。struct inodeunsigned short i_mode; /模式unsigned int i_ui
12、d; /文件的用户IDunsigned int i_size; /文件的大小unsigned int i_blocks; /分配给该文件的磁盘块的数目long i_block; /指向磁盘块的起始地址bool i_change; /表示该文件是否修改过,true表示修改过,false表示没有;数据块组:由超级块和组描述符组成struct block_groupstruct super_block super_block; /超级块struct group_desc group_desc; /组描述符;文件:包括文件名(普通文件或者目录)和 inode 号struct file_entrycha
13、r nameNAME_LEN; /文件名int inode; /inode号,即在inode_table中的数组下标;目录:用于存储指定具体目录所包含文件(包括目录)的数目和具体的文件内容(即 dir_entry)struct dirchar dir_nameNAME_LEN; /目录名int inode; /inode号int size; /记录该目录下包含多少个文件(包括目录)struct file_entry file_entryFILE_NUM; /具体的文件内容;用户:包括用户权限、ID 、密 码,系统默认最大用户数目为 8 个struct userunsigned int mode
14、; /用户的模式(权限)int uid; /用户的IDchar password20; /密码;命令:用于存储系统命令,共 13 个命令struct commandchar com10;一些重要的函数说明:(具体的参见源程序)void format(); /用于格式化文件系统void display_sys_info(); /显示系统信息bool get_dirname(char*path,int len,int pos,char*name); /根据路径 path 分解出路径第pos 处的文件(或目录)名long block_alloc(int len,int *b_index); /分配数
15、据块,返回成功分配的首地址void block_free(int len,int pos); /释放数据块int i_alloc(); /分配 inodevoid i_free(int inode); /释放 inodebool change_dir(char *path_and_dirname,int len); /根据路径 path 改变到指定目录void display(char*path,int len); /显示 path 指定的目录内容void make_dir(char*path_and_dir_name,int path_len); /根据指定路径创建目录void remove
16、_dir(char*path_and_dir_name,int path_len); /根据指定路径 删除目录void delete_file(char*path_and_file_name,int path_len); /根据指定路径 删除文件void create_file(char *path_and_file_name,int path_len); /根据指定路径 创建文件void open_file(char*path_and_file_name,int path_len); /根据指定路径打开文件void copy_file(char*src_path,int src_len,ch
17、ar*des_path,int des_len); /根据指定源路径和目的路径拷贝文件void install(); /文件系统的装载,完成基本的初始化及读取操作主要函数的算法步骤及其实现:功能:改变目录算法步骤:判断路径是否为“”是则转换到上一级目录,否则判断从是否从根目录开始,是则从根目录开始查找路径,找到要打开的目录,找到 则打开,否则提示错误信息;否则是从当前目录开始查找路径,找到要打开的目录找到则打开,否则提示错误信息bool change_dir(char *path_and_dirname,int len)dir temp;if(get_dir_path_and_op(path_
18、and_dirname,len,temp)_current_dir = temp;elseprintf(“目录切换失败!n“);return false;return true;功能:显示目录,显示当前目录或指定目录(绝对路径或相 对路径)算法步骤:1.判断是否为显示当前目录,是则转 4,否则转 22.判断是否从根目录开始,是则从根目录开始查找到指定目录的 inode,转 4,否则转 33.判断是否为当前目录下的子目录,是则找到指定目录的 inode,转 4,否则表示无该目录, 返回出错信息4.循环显示文件和目录void display_dir(char*path,int len)dir te
19、mp;if(get_dir_path_and_op(path,len,temp)printf(“%8s 的目录nn“,path);display(temp);elseprintf(“目录显示失败!n“);功能:创建目录算法步骤:分析给的路径,分解出要 创建的目录的路径和要 创建的目录名;判断是否在当前目录下创建,如果是则判断是否存在同名目录,有 则提示信息,否 则直接分配空间创建目录;否则判断是绝对路径还是相对路径,找出创建的所在目录位置;然后判断该目录下是否有与要创建的目录的同名目录,有则给出提示信息,否则分配空间创建目录void make_dir(char*path_and_dir_nam
20、e,int path_len)dir temp_dir;char file_nameNAME_LEN;if(get_dir_and_name_and_op(path_and_dir_name,path_len,temp_dir,file_name)make_dir(temp_dir,file_name);elseprintf(“目录创建失败!n“);功能:删除目录算法步骤:先判断路径是否正确, 错误则提示信息,正确则找到要删除的目录,判断是否为空,是则删除,更改父目录信息,否 则提示信息,确定要删除时递归删除其文件即子目录void remove_dir(char*path_and_dir_na
21、me,int path_len)dir temp_dir;char file_nameNAME_LEN;if(get_dir_and_name_and_op(path_and_dir_name,path_len,temp_dir,file_name)remove_dir(temp_dir,file_name);elseprintf(“目录删除失败!n“);功能:建立文件算法步骤:检查路径,如果路径正确 则在正确的目录 下建立文件,包括分配数据块和 inode,最后修改超级块组描述符、数据 块位图、 inode 位图、文件所在的目 录、数据区等否则提示错误信息void create_file(c
22、har *path_and_file_name,int path_len)dir temp_dir;char file_nameNAME_LEN;if(get_dir_and_name_and_op(path_and_file_name,path_len,temp_dir,file_name)create_file(temp_dir,file_name);elseprintf(“文件创建失败!n“);功能:打开文件算法步骤:检查路径及文件是否正确,正确则取到文件的 inode,申请和文件一样大小的缓冲区,把文件内容读到缓冲区并输出即可; 否则提示错误信息。void open_file(char
23、*path_and_file_name,int path_len)dir temp_dir;char file_nameNAME_LEN;if(get_dir_and_name_and_op(path_and_file_name,path_len,temp_dir,file_name)open_file(temp_dir,file_name);elseprintf(“文件打开失败!n“);功能:删除文件算法步骤:检查给定的路径,找出要 删除的文件所在的目 录;如果路径正确,则调用 delete_file(dir temp_dir,char *file_name)进行删除否则提示错误void d
24、elete_file(char*path_and_file_name,int path_len)dir temp_dir;char file_nameNAME_LEN;if(get_dir_and_name_and_op(path_and_file_name,path_len,temp_dir,file_name)delete_file(temp_dir,file_name);elseprintf(“文件删除失败!n“);功能:拷贝文件(分为 Linux 文件系统内部、从 Linux 到 Windows、从 Windows到 Linux 的拷贝)算法步骤:首先检查给出的两个路径是否正确;如果正
25、确 则找到对应的文件,读出内容到内容缓冲区中,再将内容缓冲区的内容写到目的路径中否则提示错误信息。void copy_file(char*src_path,int src_len,char*des_path,int des_len)dir temp_dir; /保存目的目录char file_nameNAME_LEN; /文件名char *buf; /文件内容缓冲区char divide; /保存分隔符long len = 0; /文件长度if(host_sys(src_path) /从host文件系统拷贝到模拟Linux文件系统fd = fopen(src_path,“rb“);if(fd
26、= NULL)printf(“文件不存在,文件拷贝失败!n“);return;fseek(fd,0,SEEK_END);len = ftell(fd);buf = new charlen; /申请文件内容缓冲区buflen-1 = 0;fseek(fd,0,SEEK_SET);fread(buf,len-1,1,fd); /读取文件的内容fclose(fd);divide = ; /windows路径分隔符strcpy(file_name,strrchr(src_path,divide) +1); /获得文件名if(get_dir_path_and_op(des_path,des_len,te
27、mp_dir) /找到目的目录write_back(temp_dir,file_name,buf,len);return;elseprintf(“文件拷贝失败!n“);elseif(host_sys(des_path) /从模拟Linux文件系统拷贝到host文件系统if(get_dir_and_name_and_op(src_path,src_len,temp_dir,file_name)int inode;for(int i=2;itemp_dir.size;i+)if(strcmp(temp_dir.file_entryi.name,file_name)=0)inode = temp_d
28、ir.file_entryi.inode;buf = new charinode_tableinode.i_size-1; /分配缓冲区len = read_file(temp_dir,file_name,inode,buf);char *complete_path = new charsrc_len+des_len+1; /Windows中的完整路径sprintf(complete_path,“%s%s“,des_path,file_name);fd = fopen(complete_path,“wb+“);if(fd = NULL)printf(“文件拷贝失败!n“);delete(buf
29、);delete(complete_path);return;fwrite(buf,len-1,1,fd);fclose(fd);delete(complete_path);delete(buf);return;printf(“文件拷贝失败!n“);else /Linux文件系统内部拷贝if(get_dir_and_name_and_op(src_path,src_len,temp_dir,file_name)int f_inode;for(int i=2;itemp_dir.size;i+)if(strcmp(temp_dir.file_entryi.name,file_name)=0 br
30、eak;buf = new charinode_tablef_inode.i_size-1; /分配缓冲区len = read_file(temp_dir,file_name,f_inode,buf);char *complete_path = new charsrc_len+des_len+1; /Linux中的完整路径sprintf(complete_path,“%s/%s“,des_path,file_name);if(get_dir_and_name_and_op(complete_path,src_len+des_len+1,temp_dir,file_name)write_back(temp_dir,file_name,buf,len);elseprintf(“文件拷贝失败!n“);delete(complete_path);delete(buf);五、 调试过程