Geekos操作系统全部实验实现报告.doc_第1页
Geekos操作系统全部实验实现报告.doc_第2页
Geekos操作系统全部实验实现报告.doc_第3页
Geekos操作系统全部实验实现报告.doc_第4页
Geekos操作系统全部实验实现报告.doc_第5页
免费预览已结束,剩余17页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算机系统实验软件报告题目:Geekos操作系统的研究与实现(全部项目)院 (系): 计算机科学与工程学院 专 业: XXXXX 学生姓名: 周长劭 学 号: XXXXXXX 指导教师: 黄廷辉 2012年04月23日目 录1 GeekOS简介311GeekOS系统源代码结构32 实验环境43 项目实现431 Project043.11项目设计目的43.12项目设计要求43.13项目设计原理43.13项目具体实现53.14调试运行结果532 Project163.21项目设计目的63.22项目设计要求63.23项目设计原理63.23项目具体实现73.24调试运行结果733 Project283.31项目设计目的83.32项目设计要求83.33项目设计原理93.33项目具体实现103.34调试运行结果1134 Project3113.41项目设计目的113.42项目设计要求113.43项目设计原理113.43项目具体实现133.44调试运行结果1435 Project4153.51项目设计目的153.52项目设计要求153.53项目设计原理153.53项目具体实现153.54调试运行结果1536 Project5153.61项目设计目的153.62项目设计要求153.63项目设计原理153.63项目具体实现153.64调试运行结果154 遇到问题及解决方法155 学习总结16参考文献161 GeekOS简介GeekOS是一个基于X86架构的PC上运行的微操作系统内核。由美国马理兰大学的教师开发,是一个用C语言开发的操作系统。主要用于操作系统课程设计,目的是使学生能够实际动手参与到一个操作系统的开发工作中。出于教学目的,这个系统内核设计简单,却又兼备实用性,它可以运行在真正的X86 PC硬件平台。作为一个课程设计平台,GeekOS由一个基本的操作系统内核作为基础,提供了操作系统与硬件之间的所有必备接口,实现了系统引导、实模式到保护模式的转换、中断调用及异常处理、基于段式的内存管理,FIFO进程调度算法以及内核进程、基本的输入输出(键盘作为输入设备、显示器作为输出设备),以及一个用于存放用户程序的只读文件系统PFAT。学生可以在Linux或Unix及Windows Cygwin环境下对其进行功能扩充,且其针对进程、文件系统、存储管理等操作系统核心内容分别设计了7个难度逐渐增加的项目供学生选择 11GeekOS系统源代码结构 GeekOS操作系统源文件geekos-0.3.0.zip可以从下载。解压后的GeekOS目录结构如图1-3所示:在doc目录下文件hacking.pdf和index.htm是GeekOS系统的参考文档。Scripts目录下有startProject和removeEmptyConflicts两个脚本文件。GeekOS系统的源文件在src目录下,分为7个项目:Project0, Project1, Project2, Project3, Project4, Project5, Project6。每个项目的文件结构都类似,以Project0为例,结构如图1-4所示:在build文件夹中,包含系统编译后的可执行文件的文件、软盘镜像或是硬盘镜像、makefile项目管理文件。在inculde文件夹中有geekOS和libc两个子目录,在geekOS子目录中有kthread.h,keyboard.h等头文件,在libc中包含有geekOS支持的C语言标准函数string.H头文件。在scripts文件夹是项目编译时要用到的一些脚本文件。Src文件夹中存放系统内核源代码,用户修改geekOS系统时要修改的源代码如main.c都位于这个目录中。在User子目录中一般是用来存放用户的测试文件,在tools子目录中的代码是用来建立PFAT测试文件系统的。2 实验环境1下载并完全安装Cygwin最新版2 Windows下配置Cygwin运行2Bochs最新版安装和使用3 项目实现31 Project03.11项目设计目的熟悉GeekOS的项目编译、调试和运行环境,掌握GeekOS运行工作过程。3.12项目设计要求(1)搭建GeekOS的编译和调试平台,掌握GeekOS的内核进程工作原理。(2)熟悉键盘操作函数,编程实现一个内核进程。该进程的功能是:接受键盘输入的字符并显示到屏幕上并计数,当输入Ctrl+D时,结束进程的运行。3.13项目设计原理项目要求从键盘输入,因此要用到键盘处理函数 。GeekOS的键盘处理函数定义在keyboard.h与keyboard.c 文件中。键盘的初始化是在Main函数中调用Init_Keyboard进行的,Init_Keyboard主要功能是设置初始状态下存放键盘扫描码的缓冲区,并为键盘中断设置处理函数。而键盘中断处理过程是:首先从相应的I/O端口读取键盘扫描码,根据是否按下Shift键,分别在键值表中寻找扫描码对应的按键值,经过处理后将键值放入键盘缓冲区,最后通知系统重新调度进程。若用户进程需要从键盘输入信息,可调用Wait_For_Key()函数,进程调用该函数后,会阻塞进入按键操作的等待队列,直到按键操作结束,进程才会被唤醒。Start_Kernel_Thread函数主要功能就是建立一个内核线程。本项目主要要求设计一个函数对键盘的中断进行响应。这主要通过使用Geekos提供的键盘响应函数Wait_For_Key()进行键盘中断的响应及返回键值。该函数首先检查键盘缓冲区是否有按键,如果有,就读取一个键码,如果此时键盘缓冲区中没有按键,就将线程放入键盘事件等待队列。于是可分两步完成:1 编写函数EchoCount,函数功能是:接受键盘输入的按键,并将键值显示到显示器,当输入Ctrl+D退出。2 在Main函数体内调用Start_Kernel_Thread函数,将编写的函数地址传递给startFunc,建立一个内核进程。3.13项目具体实现编写的函数svoid EchoCount() Keycode keycode; int count; count=0; while(1) if(Read_Key(&keycode) if(keycode & 0x4000) = 0x4000) if(Wait_For_Key() & 0x00ff) = d) Set_Current_Attr(ATTRIB(BLACK, RED); Print(Ctrl+d Is Entered! Program Ended!); Exit(1); else if(!(keycode & KEY_SPECIAL_FLAG) & !(keycode & KEY_RELEASE_FLAG) keycode &= 0xff; count=count+1; Set_Current_Attr(ATTRIB(BLACK,CYAN); Print(%c,(keycode = r)?n:keycode); if(keycode=r) count=count-1; Set_Current_Attr(ATTRIB(AMBER, BLUE); Print(The counnts is %d n ,count); count=0; 在mian函数中编写:Start_Kernel_Thread(keyin,0,PRIORITY_NORMAL,false);将编写的函数传入,生成内核进程。3.14调试运行结果1.Windows里开始-运行:CMD,进入project0/build目录。 2.执行 make depend。3.执行make,成功之后在build 目录下生成fd.img文件。4.在build目录中启动执行bochs 。6.成功后,运行结果:32 Project13.21项目设计目的熟悉ELF文件格式,了解GeekOS系统如何将ELF格式的用户可执行程序装入内存,建立内核进程并运行的实现技术。3.22项目设计要求(1)修改/geekos/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构的域值。(2)掌握GeekOS在核心态运行用户程序的原理,为项目2的实现做准备。3.23项目设计原理ELF是UNIX系统实验室作为应用程序二进制接口而开发和发布的。有两个平行视图。连接程序视图 执行程序视图 ELF 头部ELF 头部 程序头部表(可选) 程序头部表 节区1 段 1 . 节区 n 段 2 . . . 节区头部表 节区头部表(可选) GeekOS中的用户程序全部在系统的编译阶段完成编译和连接,形成可执行文件,用户可执行文件保存在PFAT文件系统中。本项目要完成的就是在系统启动后,从PFAT文件系统将可执行文件装入内存,建立进程并运行得到相应的输出。在磁盘中的ELF文件的映像和在内存中执行程序镜像间的对应关系如下图所示而此过程主要由Spawner函数实现,其主要经过简要概述为:先调用Read_Fully函数将文件读入内存,后调用Parse_ELF_Executable函数分析ELF文件,最后调用Spawn_Program函数将可执行程序的代码段和数据段等装入内存,此后便可以开始运行一个内核级进程了。如下图所示:在本项目中,我们要完成Parse_ELF_Executable函数,此函数的作用为根据ELF文件格式,从exeFileData指向的内容中得到ELF文件头,继续分析可得到程序头和程序代码段等信息。3.23项目具体实现int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat)elfHeader *eh = (elfHeader*)exeFileData; programHeader *ph=(programHeader *)(exeFileData+eh-phoff);int i;for(i=0;iphnum;i+)exeFormat-segmentList i.offsetInFile=ph-offset;exeFormat-segmentList i.lengthInFile=ph-fileSize;exeFormat-segmentList i.startAddress=ph-vaddr;exeFormat-segmentList i.sizeInMemory=ph-memSize;exeFormat-segmentList tFlags=ph-flags; ph+;exeFormat-numSegments=eh-phnum;exeFormat-entryAddr=eh-entry; return 0; 3.24调试运行结果1.进入/os/ project1/build目录。 2.同上项目,成功之后在build 目录下生成fd.img、diskc.img文件。3.启动bochs 成功后,运行结果:33 Project23.31项目设计目的扩充GeekOS操作系统内核,使得系统能够支持用户级进程的动态创建和执行。3.32项目设计要求开始本项目前需要阅读/src/geekos目录中的entry.c、lowlevel.asm、kthread.c、userseg.c,其中在userseg.c中主要关注Destroy_User_Context()和Load_User_Program()两个函数。本项目要求用户对以下几个文件进行修改:1)“src/GeekOS/user.c”文件中的函数Spawn(),其功能是生成一个新的用户级进程;2)“src/GeekOS/user.c”文件中的函数Switch_To_User_Context(),调度程序在执行一个新的进程前调用该函数以切换用户地址空间;3)“src/GeekOS/elf.c”文件中的函数Parse_ELF_Executable()。该函数的实现要求和项目1相同。4)“src/GeekOS/userseg.c”文件中主要是实现一些为实现对“src/GeekOS/user.c”中高层操作支持的函数。 Destroy_User_Context()函数的功能是释放用户态进程占用的内存资源。 Load_User_Program()函数的功能通过加载可执行文件镜像创建新进程的User_Context结构。 Copy_From_User()和Copy_To_User()函数的功能是在用户地址空间和内核地址空间之间复制数据,在分段存储器管理模式下,只要段有效,调用memcpy函数就可以实现这两个函数的功能。 Switch_To_Address_Space()函数的功能是通过将进程的LDT装入到LDT寄存器来激活用户的地址空间;5)“src/GeekOS/kthread.c”文件中的Start_User_Thread函数和Setup_User_Thread函数。 Setup_User_Thread()函数的功能是为进程初始化内核堆栈,堆栈中是为进程首次进入用户态运行时设置处理器状态要使用的数据。 Start_User_Thread()是一个高层操作,该函数使用User_Context对象开始一个新进程。6)“src/GeekOS/kthread.c”文件中主要是实现用户程序要求内核进行服务的一些系统调用函数定义。要求用户实现的有Sys_Exit()函数、Sys_PrintString()函数、Sys_GetKey()、Sys_SetAttr()、Sys_GetCursor()、Sys_PutCursor()、Sys_Spawn()函数、Sys_Wait()函数和Sys_GetPID( )函数。7)在main.c文件中改写生成第一个用户态进程的函数调用:Spawn_Init_Process(void) 。3.33项目设计原理Geekos的初始系统不支持用户态进程,但提供了用户态进程上下文接口和实现用户态进程需要用到的数据结构。所以,用户态进程及相关函数都要开发者实现。在Geekos中为了区分用户态进程和内核进程,在Kernel_Thread结构体中设置了一个字段userContext,指向用户态进程上下文。对于内核进程来说,这个指针为空,而用户态进程都拥有自己的用户上下文。因此在Geekos中要判断一个进程是内核进程还是用户态进程,只要通过userContext字段是否为空来判断就可以了。GeekOS的进程结构图如10-1所示:图10.1 用户态进程结构每个用户态进程都拥有属于自己的内存段空间,如:代码段、数据段、堆栈段等,每个段有一个段描述符(segment descriptor),并且每个进程有一个段描述符表(Local Descriptor Table),用于保存该进程的所有段描述符。操作系统中还设置一个全局描述符表(GDT,Global Descriptor Table),用于记录了系统中所有进程的ldt描述符。GDT、LDT和User_Context的关系如图10-2所示图10-2 GDT、LDT和User_Context的关系程序流程图:GeekOS的用户级进程创建过程可以描述如下:(1)Spawn函数导入用户程序并初始化:调用Load_User_Program进行User_Context的初始化及用户级进程空间的分配及用户程序各段的装入;(2)Spawn函数调用Start_User_Thread(),初始化一个用户态进程,包括初始化进程Kernel_Thread结构以及调用Setup_User_Thread初始化用户级进程内核堆栈;(3)最后Spawn函数退出,这时用户级进程已被添加至系统运行进程队列,可以被调度了。3.33项目具体实现修改及增加的代码及函数如下(由于篇幅限制具体代码见附件):User.c中int Spawn(const char *program, const char *command, struct Kernel_Thread *pThread)void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state)Elf.c中int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat)Userseg.cvoid Destroy_User_Context(struct User_Context* userContext)int Load_User_Program(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat, const char *command,struct User_Context *pUserContext)bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize)bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t bufSize)void Switch_To_Address_Space(struct User_Context *userContext)Kthresd.c中Start_User_Thread(struct User_Context* userContext, bool detached)void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context* userContext)Syscall.c中static int Sys_Exit(struct Interrupt_State* state)static int Sys_PrintString(struct Interrupt_State* state)static int Sys_GetKey(struct Interrupt_State* state)static int Sys_SetAttr(struct Interrupt_State* state)static int Sys_GetCursor(struct Interrupt_State* state)static int Sys_PutCursor(struct Interrupt_State* state)static int Sys_Spawn(struct Interrupt_State* state)static int Sys_Wait(struct Interrupt_State* state)static int Sys_GetPID(struct Interrupt_State* state)3.34调试运行结果进入/os/ pp/project2/build目录,操作同上成功后,运行结果:34 Project33.41项目设计目的改进GeekOS的调度程序,实现基于4级反馈队列的调度算法(初始GeekOS系统仅提供了FIFO进程调度算法),并实现信号量,支持进程间通信。3.42项目设计要求 (1)实现src/geekos/syscall.c文件中的Sys_SetSchedulingPolicy系统调用,它的功能是设置系统采用的何种进程调度策略; (2)实现src/geekos/syscall.c文件中的Sys_GetTimeOfDay系统调用,它的功能是获取全局变量g_numTicks的值; (3)实现函数Change_Scheduling_Policy(),具体实现不同调度算法的转换。 (4)实现syscall.c中信号量有关的四个系统调用:sys_createsemaphore( )、sys_P( )、sys_V( )和sys_destroysemaphore( )。3.43项目设计原理1)Set_Scheduling_Policy(policy,quantum),policy是设置的调度策略,quantum是设置的时间片。例如policy为1说明设置的是多级反馈队列调度算法,g_schedulingPolicy设置为1(g_schedulingPolicy为系统添加的标识算法的变量,初始化为0)。如果policy为0,则说明设置的是轮转调度, g_schedulingPolicy设置为0,把4个队列变成一个队列,即所有的线程都在队列0上了。2)在系统调用Sys_GetTimeOfDay()中,只需要返回g_numTicks就可以了。在Sys_SetSchedulingPolicy()中,如果state-ebx是1,则设置的是MLF算法,为0则是RR算法。如果state-ebx为其他值,则返回-1。 3)在Init_Thread()中都是把队列放在0队列上的,并且blocked变量为false。 4)在Get_Next_Runnable()中,从最高级的队列开始,调用Find_Best()来找线程优先级最大的线程,直到在某级队列中找到符合条件可以运行的线程。 5)在Wait()函数中,线程被阻塞,所以blocked变量被设置为true,并且如果是MLF算法,则该进程的currentReadyQueue加一,下次运行的时候进入高一级的线程队列。6)信号量定义 GveekOS定义了信号量的结构体:Struct Semaphore7)信号量PV操作 信号量操作:Semaphore_Create()Semaphore_Acquire(P操作)Semaphore_Release(V操作)Semaphore_Destroy()Semaphore_Create()函数首先检查请求创建的这个信号量的名字是否存在,如果存在,那么就把这个线程加入到这个信号量所注册的线程链表上;如果不存在,则分配内存给新的信号量,清空它的线程队列,把当前的这个线程加入到它的线程队列中,设置注册线程数量为1,初始化信号量的名字,值和信号量的ID,并把这个信号量添加到信号量链表上,最后返回信号量的ID。 P操作Semaphore_Acquire()中,首先检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号量,如果这两项检查任意一项失败了,那么就返回-1。如果成功了,就把信号量的值减去1,如果减去1后信号量的值小于0,那么就把当前线程放入这个信号量的等待队列上。 V操作Semaphore_Release()中,首先也是检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号量,如果这两项检查任意一项失败了,那么就返回-1。如果成功了,那就把信号量的值加上1,如果加上1后信号量的值小于或等于0,则要把该信号量里等待队列上的一个线程唤醒。 Semaphore_Destroy()中,首先也是检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号量,如果这两项检查任意一项失败了,那么就返回-1。如果成功了,就把该线程从这个信号量的注册的线程数组中删除,并把注册的线程数量减去1。如果这个信号量的注册线程为0了,则把这个信号量从信号量链表中删除,并释放它的内存。8)多级反馈队列调度队列模型 9)多级反馈队列与分时调度进程队列的转换3.43项目具体实现struct Semaphore;DEFINE_LIST(Semaphore_List,Semaphore); struct Semaphore intsemaphoreID; char*semaphoreName; intvalue; intregisteredThreadCount; #defineMAX_REGISTERED_THREADS 60 structKernel_Thread *registeredThreadsMAX_REGISTERED_THREADS; structThread_Queue waitingThreads; DEFINE_LINK(Semaphore_List,Semaphore); ;IMPLEMENT_LIST(Semaphore_List,Semaphore);syscall.c文件中添加:并完成如下函数(篇幅有限,详细代码见项目程序):static int Sys_CreateSemaphore(struct Interrupt_State*state)static int Sys_P(struct Interrupt_State* state)static int Sys_V(struct Interrupt_State* state)static int Sys_DestroySemaphore(structInterrupt_State* state)static int Sys_SetSchedulingPolicy(struct Interrupt_State* state)在kthread.c中完成如下函数:struct Kernel_Thread* Get_Next_Runnable(void)在此函数中实现Round-Robin和Multi-Level-Feedback 两个进程调度核心算法。注:系统要求idle放入多队列的最后一列,在此没做处理,因为标准时钟中断函数已经进行自动降级处理所有进程达到同样的效果,节省代码。3.44调试运行结果操作同上,Round-Robin和Multi-Level-Feedback 调度结果如下图所示:信号量测试结果如下图所示:35 Project43.51项目设计目的要求实现分页虚拟存储管理,以替代在项目1和项目2中采用的分段存储管理。实现分页虚存管理后。系统在内存不够的情况下可以将部分页调到硬盘,以释放内存实现虚拟存储技术。3.52项目设计要求1) 段式先将逻辑地址映射成线性地址2) 页式将线性地址映射成物理地址3) 请求分页机制的实现4)创建页目录PGD和页表PT数据结构5) 系统全局页链表g_pageList, s_freeList6) 初始化虚拟内存7) 初始化页面文件数据结构8) 为页面文件分配与释放磁盘块9) 读写页数据函数的实现10) 内核缓冲区与用户缓冲区之间的数据交换11) 用户级进程在分页系统中的创建,执行与销毁3.53项目设计原理系统增加了一个新的寄存器CR3作为指向当前页目录的指针。这样,从线性地址到物理地址的映射过程为:(1)从CR3取得页目录的基地址;(2)以线性地址中的页目录位段为下标,在目录中取得相应页表的基地址;(3)以线性地址中的页表位段为下标,在所得到的页表中取得相应的页面描述项;(4)将页面描述项中给出的页面基地址与线性地址中的页内偏移位段相加得到物理地址。上述映射过程可用图直观地表示,具体如下图所示。线性地址到物理地址的映射在GeekOS中,所有内核级进程共享一个页表,而每个用户级进程都有各自的页表。此外,用户模式进程的页表也包含访问内核模式内存的入口。GeekOS的内存布局如图下所示。GeekOS的内存布局通过编写一个初始化页表和允许在处理器中使用分页模式的函数来为内核级进程创建一个页目录和页表入口,这个函数就是中的Init_VM函数。在的Init_VM的Hints(提示)中,用户可以看到此函数的功能主要有以下三个:(1)建立内核页目录表和页表;(2)调用Enable_Paging函数使分页机制有效;(3)加入一个缺页中断处理程序,并注册其中断号为14。用户设计的缺页中断处理程序应该能够认识到此页在page file中是存在的,并将其从磁盘读进内存。而当用户将一页从磁盘调入内存时,需要释放这一页占用的空间。缺页中断处理程序应做的工作如下表所示。缺页处理表缺页情况标识相应处理堆栈生长到新页超出原来分配一页的限制分配一个新页进程继续此页保存在磁盘上数据标识这一页在page file中存在从page file读入需要的页继续因为无效地址缺页非法地址访问终止用户进程3.53项目具体实现int Load_User_Program(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat, const char *command, struct User_Context *pUserContext)void Destroy_User_Context(struct User_Context* userContext)bool Free_Pages_User_Process(pde_t * page_dir)bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t numBytes)bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t numBytes)void Write_To_Paging_File(void *paddr, ulong_t vaddr, int pagefileIndex)void Read_From_Paging_File(void *paddr, ulong_t vaddr, int pagefileIndex,pte_t * entry)void Free_Space_On_Paging_File(int pagefileIndex)int Find_Space_On_Paging_File(void)void Init_Paging(void)Init_VM(bootInfo);/调用Init_VM为使用分页系统作准备Install_Interrupt_Handle(14,Page_Fault_Handler); /加入缺页中断处理程序void Switch_To_Address_Space(struct User_Context *userContext)void Update_Clock()/*static*/ void Page_Fault_Handler(struct Interrupt_State* state)由于篇幅有限具体代码请见项目程序。3.54调试运行结果36 Project53.61项目设计目的要求实现GOSFS文件系统。由于GeekOS使用了虚拟文件系统,可以加载不同的文件系统,而系统默认加载的是PFAT只读文件系统。在这个项目中,需要实现一个多级目录,可读写的文件系统。3.62项目设计要求目标实现项目5GOSFS文件系统,因为项目之间依赖关系,还必须完成项目0、1、2。因此此次课题最后要实现的功能如下:(1)能够读入ELF格式的可执行程序文件,对其进行解析,并利用解析出的信息生成用户态进程。即是能够运行GOSFS提供的shell、b(功能为输出执行时的参数)、c(触发一个非法的系统调用)等用户程序。(2)能够格式化并加载GOSFS文件系统。(3)能在GOSFS文件系统中建立文件,建立文件夹,支持长文件名与长文件夹名。(4)能够向文件中写入内容,能够从文件中读出内容并在屏幕上显示。(5)支持文件的复制。(6)支持多级目录,即能在目录下建立目录或文件。(7)支持文件与文件夹的的删除。3.63项目设计原理文件系统的框架GeekOS的文件系统的层次如图GeekOS整体文件系统图函数调用步骤如下:(1)用户进程首先调用系统C库函数中的文件访问操作。(2)库文件中的相应函数调用相应的系统调用。(3)系统调用调用虚拟文件系统(VFS)中相应的操作函数。(4)虚拟文件系统的操作函数根据情况决定调用哪个实体操作函数。(5)实体操作函数调用底层的块设备请求函数,完成操作;虚拟文件系统VFS GeekOS的虚拟文件系统(Virtual File System)是源自Linux VFS的一种抽象机制,它将各种文件系统的基本操作抽象了出来,并组织在一起形成一个系统调用与实体文件系统间的中间层。VFS的实现使得一个操作系统使用多个文件系统成为可能,并且可以方便的实现实体文件系统向操作系统的并入。高速缓冲区 GeekOS系统为文件系统提供了高速缓冲区,以加快磁盘操作的运行效率。高速缓冲区的代码在bufcache.h,bufcache.c中实现。高速缓冲区层次位于实体文件系统与块设备服务模块之间,如图高速缓冲区层次图GOSFS磁盘格式GOSFS文件系统是项目5要求完成的文件系统,它支持多级文件目录结构和长文件名,提供文件与目录的创建、删除等基本操作。在Bochs模拟器中,该文件系统驻留在二级存储设备ide1硬盘上,IDE硬盘镜像名为diskd.img,默认大小为10MB。GOSFS按磁盘块为单位对磁盘进行划分,每个磁盘块大小为4KB(IDE硬盘扇区大小为512字节,所以一个磁盘块有8个扇区),GOSFS磁盘布局如图,超级块格式如图GOSFS磁盘格式图超级块格式图GOSFS文件系统的格式化disckd.img是GOSFS文件系统所驻留的硬盘镜像,它在编译GeekOS操作系统时自动产生并初始化为全0。此时的磁盘镜像并不能直接使用,必须先格式化成GOSFS文件系统。此部分是由GOSFS_Format实现的。其步骤如下:(1)设置文件系统魔数。(2)设置根目录所在磁盘块的块号,默认GOSFS文件系统的根目录放置在1号磁盘块。(3)获取磁盘容量,调用函数Get_Num_Block转换成磁盘块数(此函数得到的是扇区数,需要除以8才是磁盘块数),设置超级块的size项。(4)建立磁盘使用情况位图。(5)把磁盘上的1号磁盘块清空,因为刚格式化的情况下根目录应该是空的。(6)在磁盘使用情况位图上把0、1号磁盘对应的标志设为已使用。这样就可以加载和使用GOSFS格式的磁盘了。GOSFS文件系统的加载GOSFS文件系统的加载过程就可以概括为建立Mount_Poin,并对其结构体进行初始化。其主要流程如下:(1)程序通过系统调用调用VFS层的mount函数。(2)VFS层的mount根据文件系统名,从文件系统节点链表s_filesystemList中取出对应的文件系统节点,同时根据设备名取对应的设备结构指针。(3)申请一个Mount_Point结构,设置其设备结构指针,路径前缀。(4)从文件系统节点可以得到GOSFS文件系统的Mount函数(GOSFS_Mount),将新申请的Mount_Point作为参数传递给GOSFS文件系统的GOSFS_Mount函数。(5)在GOSFS层的GOSFS_Mount中,通过高速缓存区,取出磁盘中超级块的内容,保存到fsData中,设置fsData中相关数据。(6)把GOSFS文件系统支持的文件系统操作函数地址赋给Mount_Point中的Mount_Point_Ops结构体中对应的函数指针。(7)返回VFS层,将新建并已设置好的Mount_Point加入加载点链表s_mountPointList中去。至此,就完成了GOSFS文件系统挂载部分。文件夹与文件操作函数要实现的函数如下:l GOSFS_Openl GOSFS_Create_Directoryl GOSFS_Open_Directoryl GOSFS_Statl GOSFS_Syncl GOSFS_Delete3.63项目具体实现3.64调试运行结

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论