资源描述
《操作系统课程设计》汇报
专业班级: 计科1106班
姓 名: 李育洪、胡 壮
刘春林、邓程峰
指导老师: 李 玺
设计时间: 6月
目录
第一章 概论·······································3
第二章 设计基础概念和原理·······················4
第三章 总体设计···································6
第四章 具体设计···································8
第五章 系统测试和运行···························18
第六章 系统使用说明·····························20
第七章 课程设计总结·······························21
第八章 参考资料···································22
第一章 概论
1.1 课程设计内容
此次课程设计我们是四个人小组,我们选择是第三个题目,题目标描述以下:
在uC/OS操作系统中增加一个简单文件系统, 要求以下:
(1) 熟悉并分析uc/os操作系统
(2) 设计并实现一个简单文件系统
(3) 能够是存放在内存虚拟文件系统,也能够是存放在磁盘实际文件系统
(4) 编写测试代码,测试对文件相关操作:建立,读写等
1.2 课程设计目标
操作系统课程关键讲述内容是多道操作系统原理和技术,和其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分亲密。本课程设计目标综合应用学生所学知识,建立系统和完整计算机系统概念,了解和巩固操作系统基础理论、原理和方法,掌握操作系统开发基础技能。
1.3 要处理关键问题
经过对题目标分析,和对相关资料查阅,我们决定为μC/OS-II写一个FAT32文件系统。
那么,我们要处理关键问题就有:
1) 掌握μC/OS-II基础原理,并能在μC/OS-II上用C语言进行程序设计;
2) μC/OS-II开发环境建立。因为我们没有嵌入式硬件设备,所以在PC上进行开发。于是就需要把μC/OS-II一直到windows下,用VC++作为开发环境;
3) 了解FAT32文件系统底层细节。必需要有FAT32这种文件系统具体说明。
4) 手动实现FAT32文件系统。
5) 测试。必需确保文件系统能在μC/OS-II下运行。
第二章 设计基础概念和原理
2.1 μC/OS-II介绍
μC/OS-II由Micrium企业提供,是一个可移植、可固化、可裁剪、占先式多任务实时内核,它适适用于多个微处理器,微控制器和数字处理芯片(已经移植到超出100种以上微处理器应用中)。同时,该系统源代码开放、整齐、一致,注释详尽,适合系统开发。 μC/OS-II已经经过联邦航空局(FAA)商用航行器认证,符合航空无线电技术委员会(RTCA)DO-178B标准。
μC/OS-II能够大致分成关键、任务处理、时间处理、任务同时和通信,CPU移植等5个部分。
1) 关键部分
是操作系统处理关键,包含操作系统初始化、操作系统运行、中止进出前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基础工作部分全部在这里。
2) 任务处理部分
任务处理部分中内容全部是和任务操作亲密相关。包含任务建立、删除、挂起、恢复等等。因为μC/OS-II是以任务为基础单位调度,所以这部分内容也相当关键。
3) 时钟部分
μC/OS-II中最小时钟单位是timetick(时钟节拍)。任务延时等操作是在这里完成。
4) 任务同时和通信部分
为事件处理部分,包含信号量、邮箱、邮箱队列、事件标志等部分;关键用于任务间相互联络和对临界资源访问。
5) 和CPU接口部分
是指μC/OS-II针对所使用CPU移植部分。因为μC/OS-II是一个通用性操作系统,所以对于关键问题上实现,还是需要依据具体CPU具体内容和要求作对应移植。这部分内容因为牵涉到SP等系统指针,所以通常见汇编语言编写。关键包含中止级任务切换底层实现、任务级任务切换底层实现、时钟节拍产生和处理、中止相关处理部分等内容。
2.2 μC/OS-II在VC++下移植
为了开发环境方便,需要将μC/OS-II移植到VC++上。移植关键有三步,下面作简明说明。具体方法能够参考《嵌入式实时操作系统μC/OS原理和实践》一书。
1) VC下时钟取得
能够使用采取软件定时器来模拟时钟中止。这里我们采取是timeSetEvent()函数。这个函数很简单,不需要消息循环,定时精度为ms级,关键应用在多媒体定时方面,能够在很正确时间间隔内完成一个事件、函数或过程调用。能够经过调用timeSetEvent()函数,将需要周期性实施任务定义在LpTimeProc回调函数中,从而完成所需处理事件。调用这个函数后会增加一个线程,时间一到则在这个线程中调用回调函数,对于根本程来说,很类似外部中止调用,我们需要正是这么效果。
2) 模拟时钟中止产生
中止指是中止目前事务,处理别更要紧事情。我们经过软件定时器来模拟产生uC/OS-II时钟中止,但timeSetEvent()函数调用定时回调函数是和根本程同时被windows操作系统调度,并没有起到中止作用。所以在调用定时回调函数时候必需停止根本程运行,退出回调函数则恢复根本程运行,自然这些事情能够全部放在定时回调函数,也就是uC/OS-II时钟中止处理函数中完成。Windows下要挂起一个线程运行,首先要得到这个线程句柄,然后调用SuspendThread(hangdler)和ResumeThread(handler)就能够挂起和继续实施线程。
3) 任务切换
任务切换,其实做是任务上下文切换,在其它CPU上很轻易分辨出任务上下文,通常就是CPU上对应寄存器,那么在VC下呢?从简单考虑,我们选择了不带浮点运算上下文环境,所以任务上下文和uC/OS-II在80x86上移植上下文很相近,不一样点只是段寄存器不用保留,因为在VC下任务其实只是在同一个线程中切换,而且在保护模式下段寄存器概念已变,其值在同一个线程中是不会变。
2.3 FAT32文件系统格式
FAT32是Windows系统硬盘分区格式一个。这种格式采取32位文件分配表,使其对磁盘管理能力大大增强,突破了FAT16对每一个分区容量只有2 GB限制。因为现在硬盘生产成本下降,其容量越来越大,利用FAT32分区格式后,我们能够将一个大硬盘定义成一个分区而无须分为多个分区使用,大大方便了对磁盘管理。现在已被性能更优异NTFS分区格式所替换。
一个FAT文件系统包含四个不一样部分:保留扇区、FAT区域、根目录区域、数据区域。
对于FAT32具体说明能够参考微软官网上相关FAT32白皮书,网址:。
第三章 总体设计
嵌入式文件系统因为功效和作用和一般桌面操作系统文件系统不一样,造成了二者在体系结构上含有很大差异性。在一般桌面操作系统中,文件系统不仅要管理文件,提供文件系统调用API,还要管理多种设备,支持对设备和文件操作一致性(即要像操作文件一样来操作多种I/O设备)。在嵌入式文件系统中,这种规则发生了很大改变。在一些情况下,嵌入式系统能够针对特殊目标来进行定制,尤其是伴随ASOS(为应用定制嵌入式操作系统)发展,对嵌入式操作系统系统功效规整性、可伸缩性及其灵活性提出了更高要求。
基于以上考虑,我们采取了下图所表示嵌入式文件系统体系结构,该结构定义文件系统从上到下有三个层次:第一层为API层、第二层为中间转换层、下层为介质驱动层。
第一层:API层。API层是文件系统和用户应用程序之间接口,它有一个标准C函数库,其中包含有诸如打开文件(f_open)、写文件(f_write)等函数。本层功效是将用户调用传送给中间转换层。这是整个系统设计关键,也是嵌入式文件系统中用户唯一可见部分。
第二层:中间转换层。中间转换层要为文件系统实现提供和硬件无关统一接口,是文件系统结构规整性基础。中间转换层包含有文件系统子层及逻辑块子层,其汉字件系统子层将文件操作解释到逻辑块子层,然后文件系统调用逻辑块子层并依据不一样设备定义出对应设备驱动程序;逻辑块子层关键是同时对设备驱动程序访问,向上提供友好界面。
第三层:介质驱动层。介质驱动层是访问硬件最低端程序,该程序结构要能够便于实现对硬件访问。本层功效关键是完成对介质访问。本层关键任务就是提供统一设备驱动程序接口。
依据文件系统层次结构,能够将该文件系统分成三大功效块:API接口模块、中间转换模块、设备驱动模块。其中API接口模块关键完成文件基础操作,包含有文件生成、删除、打开、关闭、文件读、文件写等。中间转换模块关键完成对存取权限检验、介质选择、逻辑到物理转换。设备驱动模块完成存放介质驱动程序,包含有一个驱动程序函数表和介质读、介质写、检验状态、实施特定命令等驱动程序。
第四章 具体设计
总体设计完成以后,就能够多个精力进行具体设计。依据总体设计划分模块,一个模块一个模块进行具体设计。
4.1 文件系统对外提供关键接口
1、FRESULT f_open (FIL*, const char*, BYTE);
函数功效:打开或创建一个文件
2、FRESULT f_read (FIL*, BYTE*, WORD, WORD*);
函数功效:读一个文件
3、FRESULT f_close (FIL*);
函数功效:关闭一个文件
4、FRESULT f_opendir (DIR*, const char*);
函数功效:读一个目录中目录项
5、FRESULT f_readdir (DIR*, FILINFO*);
函数功效:读取目录内容
6、FRESULT f_stat (const char*, FILINFO*);
函数功效:获取文件状态
7、FRESULT f_mountdrv ();
函数功效:初始化文件系统
8、FRESULT f_write (FIL*, const BYTE*, WORD, WORD*);
函数功效:写文件
9、FRESULT f_sync (FIL*);
函数功效:同时文件缓冲区内容到磁盘中
10、FRESULT f_delete(const char*);
函数功效:删除一个文件或目录
11、FRESULT f_mkdir (const char*);
函数功效:创建一个目录
这就是文件系统提供全部功效,灵活地利用上述函数,就能够编写出复杂应用程序。
4.2 文件系统关键数据结构
1)UCFS结构体
/* 文件系统结构体,保留文件系统相关信息 */
typedef struct {
BYTE fs_type; // 文件系统类型
BYTE files; // 目前已打开文件数目
BYTE sects_clust; // 每个簇扇区数
BYTE n_fats; // FAT表数目
WORD n_rootdir; // 根目录数(在FAT32中为0)
BYTE winflag; // 标识文件是否被改动过,为1时要回写
BYTE pad1; // 站位,字节对齐
DWORD sects_fat; // 每个FAT表所占扇区数
DWORD max_clust; // 总簇数
DWORD fatbase; // FAT区起始扇区
DWORD dirbase; // 根目录区起始扇区
DWORD database; // 数据区起始扇区
DWORD winsect; // 目前缓冲区中存放扇区号
BYTE win[512]; // 单个扇区缓存
} UCFS;
UCFS结构体统计了文件系统全部信息,有了这个结构体,就能够方便地访问文件系统每一部分。
2)DIR结构体
//目录结构体,表示一个目录
typedef struct {
DWORD sclust; // 起始簇
DWORD clust; // 目前簇
DWORD sect; // 目前扇区
WORD index; // 目前索引
} DIR;
作为目录项指针,既能够用于统计一个特定文件在目录中位置,又能够用于统计在目录中目前目录项指针位置(类似于文件指针)。
3) FIL结构体
//文件结构体,表示一个文件
typedef struct {
DWORD fptr; // 文件读写指针
DWORD fsize; // 文件大小
DWORD org_clust; // 文件起始簇
DWORD curr_clust; // 目前簇(fsize=0时为0)
DWORD curr_sect; // 目前扇区
DWORD dir_sect; // 此文件目录项所在扇区
BYTE* dir_ptr; // 指向文件目录项指针
BYTE* buffer; // 文件读写缓冲区
BYTE flag; // 文件状态标识
BYTE sect_clust; // 目前簇中剩下扇区数
} FIL;
统计一般文件(不是目录文件)具体信息,比如文件对应目录项位置,文件起始簇号,文件指针,文件大小等。
4) FILINFO结构体
//文件信息结构体,也能够表示目录,用fattrib区分
typedef struct _FILINFO {
DWORD fsize; // 文件大小
WORD fdate; // 文件修改日期
WORD ftime; // 文件修改时间
BYTE fattrib; // 文件属性
char fname[13]; // 文件名 (8.3 格式)
} FILINFO;
5) win[512]数组
在 FATFS 结构体中,作为目录项或 FAT 分配表读写缓冲区。它不是某一个文件专有缓冲区,而是整个文件系统公共读写缓冲区。
6) buffer指针
buffer 是一个指向 512 字节缓冲区指针,在 FIL 结构体中,也就相当于是 FIL 中有一个 512 字节缓冲区组员。此 512 字节缓冲区,是一个文件专有缓冲区。用于当文件读写没有根据 512 字节对齐时候,作为磁盘和用户读写缓冲区之间临时缓冲区。
4.3 各个函数具体实现
1)move_window
函数原型:BOOL move_window ( DWORD sector )
函数功效:win[]操作函数(DBR、FAT 表、目录项)
<1>读取新扇区内容到临时缓冲区 win[]
<2>同时 win[]中内容到磁盘
注意:
<1> 假如读取新扇区号就是现在存放在 win[]中扇区号,就什么也不操作
<2> 假如不一样,则依据情况同时 win[]到磁盘中,而且将新扇区中内容读取到 win[]中
<3> 假如 sector 为 0,则函数功效变为同时 win[]到磁盘中,不会读取 0 扇区内容到 win[]
输入参数:sector 要读取扇区扇区号
和其它函数关系:此函数被下列函数直接或间接调用
第一类:操作 FAT 表
① get_cluster
② put_cluster
③ remove_chain
④ create_chain
第二类:操作 MBR、DBR
⑤ check_fs
第三类:操作目录项所在扇区(目录数据空间)
⑥ trace_path
程序实现方法:首先判定要读取扇区号是否和目前缓存在 win[]中扇区号一致。倘若一致,则无需实施任何操作。倘若不一致,再判定缓存在 win[]中内容是否被修改过,假如修改过,就需要更新到磁盘,最终还要把新扇区中内容加载到 win[]中。当传入参数0时,0 和目前缓存在 win[]扇区号肯定不一样,所以一定会同时 win[]内容到磁盘中。
2)f_mountdrv
函数原型:FRESULT f_mountdrv()
函数功效:初始化磁盘;初始化UcFs对象,统计物理磁盘相关参数。
函数实现方法:首先调用磁盘初始化函数,对磁盘进行初始化。然后读取物理磁盘 0 号扇区内容,判定是否是 DBR 扇区。假如不是 DBR 扇区,那么肯定就是 MBR 扇区,再从 MBR 扇区中获取 DBR 扇区地址,将 DBR 扇区内容调取到 win[]中。接下来从 win[]中,填充 UCFS 类型系统对象,这么物理磁盘和文件系统参数就被保留到了这个对象中。以后,程序就能够从全局变量--UcFs 类型变量,访问文件系统每一个区域。
3)f_open
函数原型:FRESULT f_open (FIL *fp, const char *path, BYTE mode)
函数功效:以指定方法打开或新建一个文件。假如打开或创建成功,会填充 fp 指向文件信息变量(包含文件目录项确切位置和文件信息)。
函数参数:fp 指向文件信息变量指针
path 指向文件路径
mode 打开方法
输出参数:FR_OK 打开或创建成功
其它值 打开或创建失败
函数实现方法:
① 以只读方法打开一个已经存在文件
首先调用函数 trace_path 搜索文件系统中是否存在目标文件,假如不存在就返回失败;假如存在就返回文件目录项位置(dirscan、dir),而且将目录项所在扇区内容加载到 win[]中。接下来就是从 win[]中,将文件目录项参数稍作转化后传入 FIL 类型变量中。到此,一个文件就算完整打开了。注意打开文件并不是打开文件内容,而是文件目录项,知道了文件目录项就知道了怎样去查看文件内容。
以后,经过 FIL 类型变量就能够操作对应文件。
② 新建一个文件
首先调用函数 trace_path 搜索文件系统中是否存在目标文件,因为是新建文件肯定不存在。那么不存在文件就返回新建文件目前文件夹目录指针位置(dirscan、dir)--第一个空目录项所在位置,而且将目前目录指针所在扇区内容加载到 win[]中。首先给新建文件在目前文件夹中预定一个目录项位置,然后填入新建文件目录项初始值(文件名、扩展名、属性、创建时间、更新时间)到 win[]中。注意这里并不会将新建文件目录项所在扇区同时到磁盘中,只有当调用 f_sync 函数时才会将文件目录项所在扇区同时到磁盘。创建一个新文件,只会在其上一层目录中添加对应目录项并初始化,并不会给文件分配数据空间,当然文件大小肯定是 0。
③ 重建一个文件
首先调用函数 trace_path 搜索文件系统中是否存在目标文件,因为是重建文件肯定存在。那么就返回文件目录项位置(dirscan、dir),而且将目录项所在扇区内容加载到 win[]中。重建首先将文件簇链删除,然后设置文件起始位置和文件大小为空,还需要初始化文件属性、创建时间和修改时间。这里修改全部只是在 win[]中进行,并没有同时到磁盘。只有当调用 f_sync 函数时才会将文件目录项所在扇区同时到磁盘。重建文件更改了原来文件在目录中目录项信息,重建文件并没有分配簇,也就是没有分配数据空间。
4)f_read
函数原型:FRESULT f_read (FIL *fp, BYTE *buff, WORD btr, WORD *br)
函数功效:文件读操作
输入参数:fp 文件信息指针
buff 指向用户缓冲区
btr 准备读取字节数
br 指向实际读取字节数变量
输出参数:FRESULT 成功是否
备注:函数在读取文件内容后,还会移动文件指针到下一此读写操作起点。
函数实现方法:
读文件情况有些复杂,不一样情况有不一样处理方法。开始读时候,文件指针并没有在扇区边界上(512 字节对齐),读取跨度为 3 个簇。
首先读没有对齐扇区剩下内容,其实这个内容在以前函数(以前函数移动了文件指针)已经将这个扇区内容加载到了 buffer 中。所以,直接从缓冲区 buffer 中读取此扇区文件指针以后剩下内容到用户缓冲区。
接下来,读取第一个簇剩下一个扇区内容到用户缓冲区。经过 get_cluster 函数从 FAT 表中,获取第二个簇链位置。然后一次性将一个簇链全部扇区内容读取到用户缓冲区中。再经过 get_cluster 函数从 FAT 表中,获取第三个簇链位置。然后将第三个簇链第一个扇区内容读取到用户缓冲区中。
最终,将最终所需要读取剩下内容所在扇区(剩下部分不够一个扇区)读取到 buffer 中,然后再从 buffer 中读取所需要剩下内容到用户缓冲区中。到这里为止,整个读取操作已经完成。因为 buffer 中还有一部分内容没读,假设继续调用函数 f_read 函数读取数据,那么肯定先从这个 buffer 缓冲区中将文件指针以后扇区剩下内容读取到用户缓冲区。
5)f_write
函数原型:FRESULT f_write(FIL *fp,const BYTE *buff,WORD btw, WORD *bw)
函数功效 :文件写操作,只对文件数据区进行写入,并没有更新对应目录项。
输入参数:fp 文件信息指针
buff 指向读取用户缓冲区
btw 准备写入字节数
bw 返回实际写入字节数
输出参数:FRESULT 成功是否
备注:函数在写完文件内容后,还会移动文件指针到下一此读写操作起点。
函数实现方法:
写文件情况和读取文件内容类似。开始写时候,文件指针并没有在扇区边界上(512 字节对齐),写入数据跨度为 3 个簇。
首先写入没有对齐扇区剩下内容,其实这个内容在以前函数(以前函数移动了文件指针)已经将这个扇区内容加载到了 buffer 中。所以,将用户缓冲区中对应内容写入到 buffer 中(从文件指针开始到 buffer 结束这部分空间)。然后再将 buffer 中内容写入到磁盘对应扇区。
接下来,将用户缓冲区写入到第一个簇剩下一个扇区中。经过 creat_chain 函数从 FAT 表中,获取第二个簇链位置(假如是文件有剩下簇链则使用文件剩下簇链,假如已经用完则重新从 FAT 表中搜索一个空簇链连接到此文件中,也就是更改了文件大小)。然后一次性将用户缓冲区写入到第二个簇链全部扇区中。再经过get_cluster 函数从 FAT 表中,获取第三个簇链位置。然后将用户缓冲区写入到第三个簇链第一个扇区中。
最终,将最终所需要写入剩下内容所在扇区(剩下部分不够一个扇区)读取到 buffer 中,然后再将用户缓冲区中剩下内容写入到 buffer 中。到这里为止,整个读取操作已经完成。注意这里并没有将 buffer 内容写入到磁盘中。当调用 f_sync 函数时候才会将 buffer 内容同时到磁盘。
在函数返回之前,还需要判定文件大小是否更改了,假如大小更改了则要更新文件大小,并将 FA__WRITTEN统计到文件 flag 中。这么做目标是为了当实施 f_sync 时,能够依据 FA__WRITTEN 判定出文件修改过,从而更新文件目录项。
6)f_sync
函数原型:FRESULT f_sync (FIL *fp)
函数功效:在关闭文件之前,同时文件缓冲区中内容到磁盘,同时文件目录项信息到磁盘。
输入参数:fp 文件信息指针
输出参数:FRESULT 成功是否
函数实现方法:判定文件是否修改过,假如修改过再判定文件 buffer 缓冲区是否修改过,假如修改过则同时到磁盘汉字件对应数据空间中。假如文件修改过,还要更新文件目录项,这时修改也是在 win[]中。 最终经过调用 move_window(0),将文件目录项信息同时到磁盘中。
7)f_opendir
函数原型:FRESULT f_opendir (DIR *scan, const char *path)
函数功效:打开一个目录
输入参数:scan 指向返回找到目录项结构体
path 指向路径
输出参数:FRESULT 成功是否
函数实现方法:
首先调用函数 trace_path 搜索文件系统中是否存在所要打开目录,假如不存在就返回失败;假如存在就返回目录对应目录项位置(dirscan、dir),而且将目录对应目录项所在扇区内容加载到 win[]中。
接下来判定找到是不是一个目录。假如就是一个目录话,就从 win[]中将目录对应目录项参数稍作转化后传入 DIR 类型变量中。到此,一个目录就算完整打开了。注意打开目录并不是打开目录内容,而是目录对应目录项,知道了目录对应目录项就知道了怎样去查看目录内容。
以后,经过 DIR 类型变量就能够操作对应目录。
8)f_mkdir
函数原型:FRESULT f_mkdir (const char *path)
函数功效:创建一个目录
新建一个目录,它即使是一个空目录(有效存放内容为 0),不过系统已经为它分配了一个簇数据空间,用于保留它目录项。这是和新建一个 一般文件区分很大地方。
另外,新建一个目录时,对新建目录在上一层目录目录项和新建目录中目录项初始化,全部全部在 win[]中进行操作。
输入参数:path 指向路径指针
输出参数:FRESULT 成功是否
函数实现方法:
首先调用函数 trace_path 搜索文件系统中是否存在目标目录,因为是新建目录肯定不存在。那么不存在目录时就返回新建目录所在目前文件夹目录指针(dirscan、dir)--第一个空目录项位置,而且将目前目录指针所在扇区内容加载到 win[]中。
接下来给新建目录在目前文件夹中预定一个目录项位置。然后调用 creat_chain 函数在 FAT 表中为新建目录找到一个可用数据簇,再调用 move_window(0)同时 FAT 表到磁盘中。为新建目录数据簇初始化,而且初始化第一个目录项。
最终,填入新建目录目录项初始值(目录名、属性、创建时间 、数据簇起始位置)到 win[]中。然后同时到磁盘中,完成整个新建目录工作。
9)f_delete
函数原型:FRESULT f_delete (const char *path)
函数功效:删除一个文件或目录
1、删除目录或文件簇链(回收数据空间)。
2、文件或目录目录项被设置成为删除(0xE5),注意目录项并没有回收,只是标识为删除。
输入参数:path 指向路径指针
输出参数:FRESULT 成功是否
函数实现方法:
首先调用函数 trace_path 搜索文件系统中是否存在所要删除目录或文件,假如不存在就返回失败;假如存在就返回对应目录项位置(dirscan、dir),而且将对应目录项所在扇区内容加载到 win[]中。判定要删除是不是目录,假如是目录还要判定是不是非空目录,假如是非空目录则不许可删除。假如是空目录,那么就能够删除。
删除文件或目录时,首先删除簇链(数据空间),然后修改目录项为删除状态(0xE5),最终同时目录项所在扇区 win[]缓冲区到磁盘中,完成删除。
10)f_readdir
函数原型:FRESULT f_readdir (DIR *scan, FILINFO *finfo)
函数功效:从目前目录项指针处读取一个目录项,而且移动目录指针到下一个索引
输入参数:scan 要读取目录
finfo 目录信息,finfo->fname[0] = 0,这是一个空目录项 finfo->fname[0] = others,这是一个非空目录项 。
输出参数:FRESULT 成功是否
函数实现方法:首先将目录指针目前所在物理扇区读取到 win[]中,然后调用 get_fileinifo 函数从目前目录指针处读取目前目录项并处理后存入 finfo 中。最终,还要移动目录项指针到下一个索引位置。
11)f_close
函数原型:FRESULT f_close (FIL *fp)
函数功效:关闭文件
函数参数:fp 指向文件指针
函数返回值:FRESULT 操作是否成功
函数实现方法:首先调用f_sync(),假如成功,则把UcFs->files减一。
第五章 系统测试和运行
文件系统关键是对外提供接口,所以需要编写驱动程序开测试文件函数是否正常工作。
5.1 测试程序编写
测试程序必需运行在μC/OS-II上,因为我们是为μC/OS-II编写文件系统。而且测试程序必需覆盖全部公共接口。下面是测试程序关键代码:
void test_fs(void* p_arg)
{
char cmd[256];
char param[20];
char* p;
CMDTYPE type;
for (;;)
{
printf("ucosii/fs>");
fgets(cmd, 255, stdin);
//删除行尾换行符
p = strrchr(cmd, '\n');
if(p != NULL)
*p = '\0';
rm_blank(cmd);
if(*cmd == '\0')
{
puts("");
continue;
}
type = parse(cmd, param);
switch (type)
{
case READ:
read_test(param);
puts("");
break;
case WRITE:
write_test(param);
puts("");
break;
case LS:
ls_test(param);
puts("");
break;
case RM:
rm_test(param);
puts("");
break;
case NEWFILE:
newfile_test(param);
puts("");
break;
case MKDIR:
mkdir_test(param);
puts("");
break;
case HELP:
show_help();
puts("");
break;
case QUIT:
exit(0);
break;
case INVALID:
printf("输入命令有误,请重新输入");
puts("");
break;
}
}
}
5.2 程序运行结果
程序运行截图以下:
经过反复测试,发觉程序是正确。
第六章 系统使用说明
在使用此文件系统时候,有下面几点需要注意:
1、不使用一个文件时候,要调用 f_close 或 f_sync 函数将文件同时到磁盘中。
2、f_read、f_write、f_lseek、f_sync、f_close 在使用前要先打开文件,也即是调用 f_open 函数。
3、f_stat 无需事先打开文件,能够直接使用
4、f_readdir 使用前要先打开目录,也就是调用函数 f_opendir
第七章 课程设计总结
经过此次课程设计,使我对uC/OS操作系统有了更深入了解。操作系统是一门实践性较强课程,为了学好这门课程,必需在掌握理论知识同时,加强上机实践。一个人力量是有限,要想把课程设计做愈加好,就要学会参考一定资料,吸收她人经验,让自己和她人思想有机结合起来,得出属于你自己灵感。
程序编写需要有耐心,有些事情看起来很复杂,但问题需要一点一点去处理,分析问题,把问题一个一个划分,划分成小块以后就逐一去处理。再总体处理大问题。这么做起来不仅有条理也使问题得到了轻松处理。
在这个过程中,我也曾经因为实践经验缺乏失落过,也曾经仿真成功而热情高涨。生活就是这么,汗水预示着结果也见证着收获。劳动是人类生存生活永恒不变话题。即使这只是一次极简单课程制作,可是平心而论,也花费了我不少心血,这就让我不得不佩服开发技术前辈,才意识到老一辈对我们社会付出,为了大家生活更美好,她们为我们社会所付出多少心血啊!
对我而言,知识上收获关键,精神上丰收愈加可喜。让我知道了学无止境道理。我们每一个人永远不能满足于现有成就,人生就像在爬山,一座山峰后面还有更高山峰在等着你。挫折是一份财富,经历是一份拥有。这次课程设计必将成为我人生旅途上一个很美好回想!
经过这次课程设计我对于专业课学习有了愈加深刻认识,认为现在学知识用不上就加以怠慢,等到想用时候却发觉自己学习原来是那么不扎实。以后努力学好每门专业课,让自己拥有更多知识,才能处理更多问题!
每个学期课程设计这段时间全部是我收获最多一段时间,我享受这段时间,也感激这段时间。
最终,感谢试验老师这两个星期陪同和指导。
第八章 参考资料
1、JEAN J.LABROSSE著 邵贝贝译 µC/OS-II----源码公开实时嵌入式操作系统 中国电力出版社 .08
2、王田苗著 嵌入式系统设计和和实例开发 清华大学出版社 .09
3、孟庆昌著 操作系统教程——UNIX实例分析 西安电子科技大学出版社 1989.12
展开阅读全文