FATFS文件系统剖析(全)
fatfs文件系统函数

fatfs文件系统函数FatFs 文件系统函数详解导语:FatFs 是一个跨平台、开源的文件系统实现,广泛应用于嵌入式设备。
本文将详细介绍 FatFs 文件系统函数的使用方法和实现原理。
第一节:FatFs 是什么?1.1 背景介绍嵌入式设备通常需要一个文件系统来管理储存和访问数据,而 FatFs 就是一个能够在 flash、SD 卡等储存介质上运行的文件系统实现。
1.2 FatFs 的功能FatFs 提供了一系列的文件系统函数,包括文件的创建、删除、读取、写入,目录的创建、删除、改名等。
同时,FatFs 还提供了簇管理、簇链、簇链索引的功能,以及对文件系统的格式化、检查、优化等操作。
第二节:FatFs 的使用方法2.1 环境配置在开始使用 FatFs 之前,首先要配置开发环境。
基本的配置包括硬件平台的选择和文件系统的选择。
FatFs 支持多种平台,如ARM、AVR、PIC、STM32等,并且支持多种文件系统类型,如FAT12、FAT16、FAT32等。
2.2 创建文件系统对象在使用 FatFs 的文件系统函数之前,需要先创建一个文件系统对象,并为其指定一个驱动器号。
驱动器号可以认为是一个逻辑卷,可以是实体存储介质上的一个分区或一个逻辑卷。
2.3 挂载文件系统在文件系统对象创建之后,需要通过调用 f_mount 函数来将文件系统对象挂载到系统中。
挂载文件系统的过程中,需要指定文件系统类型、逻辑卷号等参数。
2.4 文件的创建、打开和关闭通过使用文件系统函数可以创建、打开和关闭文件。
使用 f_open 函数可以创建一个新文件或打开一个已有的文件,指定打开的方式(读、写、追加等)和文件名。
使用 f_close 函数可以关闭一个已打开的文件。
2.5 文件的读取和写入文件系统函数提供了对文件的读取和写入操作。
通过 f_read 函数可以从文件中读取数据,指定读取的缓冲区和读取的大小。
通过 f_write 函数可以向文件中写入数据,指定写入的缓冲区和写入的大小。
FAT文件系统分析

FAT文件系统分析FAT文件系统的数据结构中有两个重要的结构:文件分配表和目录项:文件和文件夹内容储存在簇中,如果一个文件或文件夹需要多余1个簇的空间,则用FAT表来秒速如何找到另外的簇。
FAT结构用于指出文件的下一个簇,同时也说明了簇的分配状态。
FAT12、FAT16、FAT32这三种文件系统的主要区别在于FAT项的大小不同。
FAT文件系统的每一个文件和文件夹都被分配到一个目录项,目录项中记录着文件名、大小、文件内容起始地址以及其他一些元数据。
在FAT文件系统中,文件系统的数据记录在“引导扇区DBR”中。
引导扇区位于整个文件系统的0扇区,是文件系统隐藏区域的一部分,我们称其为DBR(DOS Boot Recorder ——DOS引导记录)扇区,DBR中记录着文件系统的起始位置、大小、FAT表个数及大小等相关信息。
在FAT文件系统中,同时使用“扇区地址”和“簇地址”两种地址管理方式。
这是因为只有存储用户数据的数据区使用簇进行管理(FAT12和FAT16的根目录除外),所有簇都位于数据区。
其他文件系统管理数据区域是不以簇进行管理的,这部分区域使用扇区地址进行管理。
文件系统的起始扇区为0号扇区。
FAT32的保留区FAT32文件系统的开始部分有一个由若干扇区组成的保留区,保留区的信息会记录在DBR扇区中,比较常见的为32、34或38个扇区。
引导扇区:引导扇区是FAT32文件系统的第一个扇区,也称DBR扇区。
包含以下基本信息:·每扇区字节数·每簇扇区数·保留扇区数·FAT表个数·文件系统大小(扇区数)·每个FAT表大小(扇区数)·根目录起始簇号·其他附加信息说明:我们可以通过每个FAT表的大小扇区数乘以FAT的个数得到FAT区域的大小;通过保留扇区数和FAT区域的大小就可以得知数据区的起始位置,也即文件系统第一簇的位置。
由根目录的簇号和第一簇的位置就可以得到根目录的位置。
stm32sdiofatfs文件系统源码分析

、概述1、目的在移植之前,先将源代码大概的阅读一遍,主要是了解文件系统的结构、各个函数的功能和接口、与移植相关的代码等等。
2、准备工作在官方网站下载了0.07c 版本的源代码,利用记事本进行阅读。
二、源代码的结构1、源代码组成源代码压缩包解压后,共两个文件夹,doc是说明,src里就是代码。
src文件夹里共五个文件和一个文件夹。
文件夹是option,还有OOreadme.txt、diskio.c、diskio.h、ff.c、ff.h、integer.h。
对比网上的文章,版本已经不同了,已经没有所谓的tff.c 和tff.h 了,估计现在都采用条件编译解决这个问题了,当然文件更少,可能编译选项可能越复杂。
2、00readme.txt 的说明Low level disk I/O module is not included in this archive because the FatFsmodule is only a generic file system layer and not depend on any specificstorage device. You have to provide a low level disk I/O module that writtento control your storage device .主要是说不包含底层10代码,这是个通用文件系统可以在各种介质上使用。
我们移植时针对具体存储设备提供底层代码。
接下来做了版权声明-可以自由使用和传播。
然后对版本的变迁做了说明。
3、源代码阅读次序先读integer.h,了解所用的数据类型,然后是ff.h, 了解文件系统所用的数据结构和各种函数声明,然后是diskio.h,了解与介质相关的数据结构和操作函数。
再把ff.c和diskio.c两个文件所实现的函数大致扫描一遍。
最后根据用户应用层程序调用函数的次序仔细阅读相关代码。
fatfs 详解

fatfs 详解摘要:I.什么是FATFS?A.FATFS 的定义B.FATFS 的作用II.FATFS 的历史A.FATFS 的起源B.FATFS 的发展历程III.FATFS 的文件系统结构A.FATFS 的目录结构B.FATFS 的文件分配表IV.FATFS 的操作A.FATFS 的文件操作1.打开文件2.读取文件3.写入文件4.关闭文件B.FATFS 的目录操作1.打开目录2.读取目录3.创建目录4.删除目录5.改变目录C.FATFS 的磁盘操作1.格式化磁盘2.挂载磁盘3.卸载磁盘V.FATFS 的应用A.FATFS 在嵌入式系统中的应用B.FATFS 在移动设备中的应用C.FATFS 在其他领域的应用正文:FATFS(File Allocation Table File System,文件分配表文件系统) 是一种通用的文件系统,被广泛应用于嵌入式系统、移动设备等领域。
FATFS 具有良好的可移植性和兼容性,支持大容量存储设备,并且具有高效的数据管理能力。
本文将对FATFS 进行详细的介绍和解析。
FATFS 最早由Microsoft 公司于1977 年开发,用于MS-DOS 操作系统中。
随着技术的发展,FATFS 不断地得到改进和完善,现在已经成为了一个功能强大、稳定性高、可移植性好的文件系统。
FATFS 的作用是将磁盘分成多个逻辑块,并为每个逻辑块分配唯一的标识符,以便对磁盘中的数据进行高效的管理和访问。
FATFS 的文件系统结构包括目录结构、文件分配表等。
其中,目录结构用于存储文件的元数据,如文件名、大小、创建时间等;文件分配表则用于记录磁盘中的空闲块和已分配块的位置,以便进行磁盘空间的分配和管理。
FATFS 支持多种操作,包括文件操作、目录操作和磁盘操作。
文件操作包括打开文件、读取文件、写入文件和关闭文件等;目录操作包括打开目录、读取目录、创建目录、删除目录和改变目录等;磁盘操作包括格式化磁盘、挂载磁盘和卸载磁盘等。
fatfs详解

UC/FS也是在网上搜了个代码,看了下,很标准的几个层,什么硬件层,文件系统层,API层,等等(具体参见UC/FS的文档),跟UCOSII一个公司的,稳定性应该不错,需要提供的函数也是读扇区,写扇区等等几个。但是底层的读写扇区的函数不需要提供扇区计数器count这个参数,也就是说,这个文件系统不能在只写一个读或者写命令的情况下,读或者写多个扇区,本来效感觉不错的一个文件系统,效率就大大的降低了。
FatFs文件系统的结构也很清晰,也是看图:
补充一点,FatFs的作者写了两个,一个是正宗的FatFs,比较适合大的RAM的设备,另一个是FatFs/Tiny,比较适合小RAM的系统,比如单片机,FatFs/Tiny占用较小的RAM,代价是更慢的读写速度和更少的API函数。不过两个都支持FAT12,FAT16,FAT32文件系统。
get_fattime - Get current time
所有的函数都牵涉到了选择第几个磁盘的问题,如果仅仅用一个,可以不必理会这个drv 参数。
disk_initialize ,如果不需要的话,直接返回0就行
disk_status ,这个嘛,先不管了,直接返回0就OK
disk_read - Read sector(s)
LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) 就产生数据终止异常( DATA ABORT exception),但是网上的一个兄弟的(ouravr上的一个兄弟,用的SD卡,IAR编译器,平台是STM32,已经成功了,还公布了源码的,这里没有问题啊),没问题。分析下这个几个宏的意思:
下载下来的FatFs的FatFs有两个文件夹,一个是 doc ,FatFs的说明,包括特性,系统函数,以及可能的一些问题,另一个就是源代码文件夹src了,总共8个文件,diskio.c和diskio.h是硬件层,ff.c和ff.h是FatFs的文件系统层和文件系统的API层,integer.h是文件系统所用到的数据类型的定义,tff.c和tff.h是Tiny的文件系统层和文件系统的API层,还有一个00readme.txt简要的介绍了FatFSHE FatFs/Tiny,包括他们所支持的API,怎么配置等等。
fatfs 详解

fatfs 详解(实用版)目录1.FATFS 简介2.FATFS 的特点3.FATFS 的文件系统4.FATFS 的应用领域5.FATFS 的未来发展正文【1.FATFS 简介】FATFS,全称 File Allocation Table File System,是一种基于文件分配表的文件系统,主要用于管理闪存设备上的文件和数据。
FATFS 起源于 DOS 时代,由微软公司开发,后来逐渐被广泛应用于各种嵌入式系统和物联网设备中。
【2.FATFS 的特点】FATFS 具有以下特点:1) 文件分配表:FATFS 通过文件分配表来管理文件的分配和释放,使得文件管理更加灵活和高效。
2) 适用于闪存设备:FATFS 主要针对闪存设备进行优化,具有较好的性能和稳定性。
3) 支持多种存储介质:FATFS 支持多种存储介质,如闪存、硬盘、软盘等。
4) 兼容性:FATFS 具有良好的兼容性,可兼容多种操作系统和设备。
【3.FATFS 的文件系统】FATFS 的文件系统主要包括以下几个部分:1) 文件分配表:用于记录文件的分配情况,包括文件的起始簇号、文件长度等信息。
2) 簇:FATFS 将闪存设备划分为多个簇,每个簇可容纳多个文件。
3) 根目录:FATFS 的根目录包含所有文件和子目录的入口。
4) 短文件名:FATFS 支持短文件名,使得文件查找更加方便。
【4.FATFS 的应用领域】FATFS 广泛应用于各种嵌入式系统和物联网设备中,如:1) 智能家居:FATFS 可用于管理智能家居设备中的文件和数据。
2) 工业控制:FATFS 可用于工业控制设备中的数据存储和管理。
3) 消费电子:FATFS 可用于各种消费电子产品中的文件管理。
【5.FATFS 的未来发展】随着物联网和嵌入式系统的快速发展,FATFS 将继续保持其在闪存设备文件管理领域的优势。
同时,FATFS 也在不断进行技术创新和升级,以适应新时期的市场需求。
fatfs 读写模式解析

fatfs 读写模式解析摘要:1.FATFS 文件系统概述2.FATFS 文件系统的读写模式3.FATFS 文件系统的优缺点正文:【FATFS 文件系统概述】FATFS(File Allocation Table File System) 是一种常见的文件系统,常用于存储设备中,例如硬盘、U 盘、SD 卡等。
FATFS 文件系统采用表格方式来存储文件的分配表,从而实现对文件的读写管理。
FATFS 文件系统支持多种设备,并且具有较好的兼容性,因此被广泛使用。
【FATFS 文件系统的读写模式】FATFS 文件系统的读写模式分为三种:只读模式、读写模式和写保护模式。
1.只读模式:在只读模式下,用户只能读取文件,不能修改文件。
该模式通常用于只读设备,例如CD-ROM、DVD-ROM 等。
2.读写模式:在读写模式下,用户既可以读取文件,也可以修改文件。
该模式通常用于可读写设备,例如硬盘、U 盘、SD 卡等。
3.写保护模式:在写保护模式下,用户只能读取文件,不能修改文件。
该模式通常用于防止数据被误删除或修改的场景,例如某些设备的启动盘等。
【FATFS 文件系统的优缺点】FATFS 文件系统的优点包括:1.兼容性好:FATFS 文件系统可以支持多种设备,并且具有较好的兼容性,可以实现不同设备之间的数据共享。
2.稳定性好:FATFS 文件系统采用表格方式来存储文件的分配表,从而实现对文件的读写管理,具有较好的稳定性。
3.支持大容量存储:FATFS 文件系统支持大容量存储,可以满足不同设备的存储需求。
FATFS 文件系统的缺点包括:1.存储效率低:FATFS 文件系统采用表格方式来存储文件的分配表,导致存储效率较低。
2.安全性差:FATFS 文件系统采用明文方式来存储文件名和数据,容易导致数据泄露和安全问题。
3.不支持高级功能:FATFS 文件系统不支持高级功能,例如文件加密、压缩等。
【结论】FATFS 文件系统是一种常见的文件系统,采用表格方式来存储文件的分配表,实现对文件的读写管理。
[STM32]stm32sdiofatfs文件系统源码剖析[精品]
![[STM32]stm32sdiofatfs文件系统源码剖析[精品]](https://img.taocdn.com/s3/m/d05cd03ae3bd960590c69ec3d5bbfd0a7956d599.png)
[STM32]stm32+sdio+fatfs文件系统源码分析一、概述1、目的在移植之前,先将源代码大概的阅读一遍,主要是了解文件系统的结构、各个函数的功能和接口、与移植相关的代码等等。
2、准备工作在官方网站下载了0.07c版本的源代码,利用记事本进行阅读。
二、源代码的结构1、源代码组成源代码压缩包解压后,共两个文件夹,doc是说明,src里就是代码。
src文件夹里共五个文件和一个文件夹。
文件夹是option,还有00readme.txt、diskio.c、diskio.h、ff.c、ff.h、integer.h。
对比网上的文章,版本已经不同了,已经没有所谓的tff.c和tff.h了,估计现在都采用条件编译解决这个问题了,当然文件更少,可能编译选项可能越复杂。
2、00readme.txt的说明Low level disk I/O module is not included in this archive because the FatFsmodule is only a generic file system layer and not depend on any specificstorage device. Y ou have to provide a low level disk I/O module that writtento control your storage device.主要是说不包含底层IO代码,这是个通用文件系统可以在各种介质上使用。
我们移植时针对具体存储设备提供底层代码。
接下来做了版权声明-可以自由使用和传播。
然后对版本的变迁做了说明。
3、源代码阅读次序先读integer.h,了解所用的数据类型,然后是ff.h,了解文件系统所用的数据结构和各种函数声明,然后是diskio.h,了解与介质相关的数据结构和操作函数。
再把ff.c和diskio.c两个文件所实现的函数大致扫描一遍。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
FATFS文件系统剖析1:FAT16:数据按照其不同的特点和作用大致可分为5部分:MBR区、DBR区、FAT区、DIR区和DATA区,相比fat12多了DBR区Main boot record: MBR(0--1bdh)磁盘参数存放DPT(1beh--1fdh)磁盘分区表55,aa 分区结束标志DBR(Dos Boot Record)是操作系统引导记录区的意思FAT区(有两个,一个备份):对于fat16,每一个fat项16位,所以可寻址的簇项数为65535(2的16次方)。
而其每簇大小不超过32k,所以其每个分区最大容量为2G。
fat32,每一个fat项32位,可寻址簇数目为2的32次方。
DIR区(根目录区):紧接着第二FAT表(即备份的FAT表)之后,记录着根目录下每个文件(目录)的起始单元,文件的属性等。
定位文件位置时,操作系统根据DIR中的起始单元,结合FAT表就可以知道文件在硬盘中的具体位置和大小了。
DATA区:实际文件内容存放区。
FAT32:暂时放在这里,不讨论!Fatfs:嵌入式fat文件系统,支持fat16,fat32。
包含有ff.h,diskio.h,integer.h,ffconf.h 四个头文件以及ff.c 文件系统实现。
当然要实现具体的应用移植,自己要根据diskio.h实现其diskio。
c 底层驱动。
diskio.h : 底层驱动头文件ff.h : 文件系统实现头文件,定义有文件系统所需的数据结构ff.c : 文件系统的具体实现如下开始逐个文件加以分析:integer.h :仅实现数据类型重定义,增加系统的可移植性。
ffconf.h : 文件系统配置---逐个配置,先配置实现一个最小的fat文件系统,下面来分析各配置选项:#define _FFCONF 8255 //版本号#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ //在这里与先前版本有些许变化,是通过配置头配置两种不同大小的文件系统,这里配置为0。
#define _FS_READONLY 1//定义文件系统只读,也就不能写修改,在此定义为1,这样文件系统会大大缩小,简化学习理解过程。
#define _FS_MINIMIZE 3 /* 0 to 3 */ 这个选项是用于过滤掉一些文件系统功能,为0时是全功能,3是功能实现最小#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ 是否使用字符串文件接口,为0,不使用#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ 制作文件系统,这个功能实现是还要_FS_READONLY=0#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ f_forward function 实现还需_FS_TINY =1#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ 快速查找功能#define _CODE_PAGE 936 // 936 - Simplified Chinese GBK (DBCS, OEM, Windows)#define _USE_LFN 0/* 0 to 3 */ 0:不使用长文件名#define _MAX_LFN 255/* Maximum LFN length to handle (12 to 255) */#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */#define _FS_RPATH 0 /* 0 to 2 */ 不使用相对路径/*---------------------------------------------------------------------------// Physical Drive Configurations/----------------------------------------------------------------------------*/#define _VOLUMES 1/* Number of volumes (logical drives) to be used. */#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ 512字节每扇区#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ 只有一个分区#define _USE_ERASE 0 /* 0:Disable or 1:Enable *//* To enable sector erase feature, set _USE_ERASE to 1. *//*---------------------------------------------------------------------------// System Configurations/----------------------------------------------------------------------------*/#define _WORD_ACCESS 0 /* 0 or 1 */ 0: Byte-by-byte access./* Include a header file here to define sync object types on the O/S *//* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or ohters. */#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ 同步选项#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ 共享选项如上已经配置成了一个最小的fat文件系统。
Diskio.h:底层驱动头文件,就一些状态宏的定义和底层驱动函数的申明,看源码一目了然。
实现相应的diskio.c 。
根据我的配置:只需要根据不同的存储介质实现相应的disk_initialize ,disk_status,disk_read三个函数就够了,我在这里实现上s3c2440上的SD卡驱动:DSTATUS disk_initialize (BYTE nDisk){return 1;}DSTATUS disk_status (BYTE nDisk){return 1;}DRESULT disk_read (BYTE nDisk, BYTE* b, DWORD c, BYTE d){return 0;}编译报错get_fattime 没实现:DWORD get_fattime (void){return 0;}转自博客,供大家相互交流!FATFS文件系统剖析2:分析下ff.h和ff.c两个文件。
先来分析ff.h中定义的几个结构体:typedef struct {BYTE fs_type; // 系统类型,为0时系统没有被挂载BYTE drv; // 物理磁盘驱动号BYTE csize; // 每簇的扇区数目,簇是文件数据分配的基本单位BYTE n_fats; // 文件分配表的数目,一般为两个(一个备份fat表) //Fatfs文件系统应该是:引导扇区,文件分配表2个,根目录区,和数据区 BYTE wflag; // 文件活动窗体是否改动标志,为1要回写BYTE fsi_flag; // 文件信息回写标志WORD id; // 文件系统加载id号WORD n_rootdir; // 根目录区目录项数目(针对FAT12/16,FAT32不使用)#if _MAX_SS != 512WORD ssize; // 每扇区多少字节#endif#if _FS_REENTRANT_SYNC_t sobj; // 允许重入,则定义同步对象#endif#if !_FS_READONLYDWORD last_clust; // 最新分配的簇DWORD free_clust; // 空闲簇DWORD fsi_sector; // 文件信息扇区(仅用于FAT32)#endif#if _FS_RPATHDWORD cdir; //使用相对路径,文件系统的当前起始路径0(root 路径)#endifDWORD n_fatent; //文件分配表占用的扇区 n_fatent=数据簇数目+2DWORD fsize; //每FAT表有多少个扇区DWORD fatbase; //文件分配表开始扇区DWORD dirbase; // 如果是FAT32,根目录开始扇区需要首先得到 DWORD database; // 数据起始扇区DWORD winsect; // win中当前指定的扇区BYTE win[_MAX_SS]; //扇区操作缓存} FATFS;typedef struct {FATFS* fs; // 指向的文件系统WORD id; // 自身文件系统挂载id号即fs->idBYTE flag; // 文件状态BYTE pad1; //文件在簇里面扇区偏移(0--fs->csize)DWORD fptr; //文件当前读写指针位置,当文件打开时为0DWORD fsize; //文件大小(按字节计算)DWORD org_clust; // 文件起始簇(0 when fsize==0)DWORD curr_clust; // 文件当前操作簇DWORD dsect; // 文件当前操作扇区#if !_FS_READONLYDWORD dir_sect; // 包含路径入口的扇区号BYTE* dir_ptr; // 目录入口指针#endif#if _USE_FASTSEEKDWORD* cltbl; //指向查找映射表的簇(null on file open)#endif#if _FS_SHAREUINT lockid; // 文件锁ID号(index of file semaphore table) #endif#if !_FS_TINYBYTE buf[_MAX_SS]; // 文件读写缓存#endif} FIL;typedef struct {FATFS* fs; // 对应的文件系统WORD id; // 自身文件系统挂载id号即fs->idWORD index; // 目前读写索引号 /* Current read/write index number */DWORD sclust; // 目录表起始簇(0:Root dir)DWORD clust; // 目前处理的簇DWORD sect; // 目前簇里对应的扇区BYTE* dir; //指向当前在win[]中的短文件名入口项/* Pointer to the current SFN entry in the win[]BYTE* fn; //指向短文件名 (in/out) {file[8],ext[3],status[1]}#if _USE_LFNWCHAR* lfn; //指向长文件名缓冲 /* Pointer to the LFN working buffer */WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */#endif} DIR;typedef struct { //文件目录表项大小=4+2+2+1+13DWORD fsize; /* File size */WORD fdate; /* Last modified date */WORD ftime; /* Last modified time */BYTE fattrib; /* Attribute */ // 文件属性TCHAR fname[13]; /* Short file name (8.3 format) */#if _USE_LFN //长文件名支持TCHAR* lfname; /* Pointer to the LFN buffer */UINT lfsize; /* Size of LFN buffer in TCHAR */#endif} FILINFO;结构是搞清楚了,但其里面的具体联系怎么也还收理不清楚。