• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# FAT<a name="ZH-CN_TOPIC_0000001153180399"></a>
2
3-   [基本概念](#section1772629121418)
4-   [开发指导](#section1149072811148)
5    -   [驱动适配](#section19174939191414)
6    -   [开发流程](#section131211626151513)
7
8-   [编程实例](#section1133718619459)
9    -   [实例描述](#section45337345313)
10    -   [示例代码](#section119813171539)
11    -   [结果验证](#section7987101232311)
12
13
14## 基本概念<a name="section1772629121418"></a>
15
16FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。
17
18OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。
19
20## 开发指导<a name="section1149072811148"></a>
21
22### 驱动适配<a name="section19174939191414"></a>
23
24FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要:
25
261、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口;
27
282、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如:
29
30```
31#define FF_VOLUME_STRS     "system", "inner", "update", "user"
32#define FS_MAX_SS          512
33#define FAT_MAX_OPEN_FILES 50
34```
35
36### 开发流程<a name="section131211626151513"></a>
37
38>![](../public_sys-resources/icon-note.gif) **说明:**
39>-   FATFS文件与目录操作:
40>    -   单个文件大小不超过4G。
41>    -   支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。
42>    -   暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。
43>    -   若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。
44>    -   读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。
45>    -   暂不支持文件与目录的权限管理。
46>    -   stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。
47>-   FATFS分区挂载与卸载:
48>    -   支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。
49>    -   mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。
50>    -   在umount操作前,需确保所有目录及文件全部关闭。
51>    -   umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。
52>-   FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format:
53>    -   在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。
54>    -   在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。
55>    -   fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。
56
57## 编程实例<a name="section1133718619459"></a>
58
59### 实例描述<a name="section45337345313"></a>
60
61本实例实现以下功能:
62
631.  创建目录“user/test642.  在“user/test”目录下创建文件“file.txt653.  在文件起始位置写入“Hello OpenHarmony!”
664.  将文件内容刷入设备中
675.  设置偏移到文件起始位置
686.  读取文件内容
697.  关闭文件
708.  删除文件
719.  删除目录
72
73### 示例代码<a name="section119813171539"></a>
74
75前提条件:
76
77-   系统已将MMC设备分区挂载到user目录
78
79代码实现如下:
80
81```
82#include <stdio.h>
83#include <string.h>
84#include "sys/stat.h"
85#include "fcntl.h"
86#include "unistd.h"
87
88#define LOS_OK 0
89#define LOS_NOK -1
90
91int FatfsTest(void)
92{
93    int ret;
94    int fd = -1;
95    ssize_t len;
96    off_t off;
97    char dirName[20] = "user/test";
98    char fileName[20] = "user/test/file.txt";
99    char writeBuf[20] = "Hello OpenHarmony!";
100    char readBuf[20] = {0};
101
102    /* 创建目录“user/test” */
103    ret = mkdir(dirName, 0777);
104    if (ret != LOS_OK) {
105        printf("mkdir failed.\n");
106        return LOS_NOK;
107    }
108
109    /* 创建可读写文件"user/test/file.txt" */
110    fd = open(fileName, O_RDWR | O_CREAT, 0777);
111    if (fd < 0) {
112        printf("open file failed.\n");
113        return LOS_NOK;
114    }
115
116    /* 将writeBuf中的内容写入文件 */
117    len = write(fd, writeBuf, strlen(writeBuf));
118    if (len != strlen(writeBuf)) {
119        printf("write file failed.\n");
120        return LOS_NOK;
121    }
122
123    /* 将文件内容刷入存储设备中 */
124    ret = fsync(fd);
125    if (ret != LOS_OK) {
126        printf("fsync failed.\n");
127        return LOS_NOK;
128    }
129
130    /* 将读写指针偏移至文件头 */
131    off = lseek(fd, 0, SEEK_SET);
132    if (off != 0) {
133        printf("lseek failed.\n");
134        return LOS_NOK;
135    }
136
137    /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */
138    len = read(fd, readBuf, sizeof(readBuf));
139    if (len != strlen(writeBuf)) {
140        printf("read file failed.\n");
141        return LOS_NOK;
142    }
143    printf("%s\n", readBuf);
144
145    /* 关闭文件 */
146    ret = close(fd);
147    if (ret != LOS_OK) {
148        printf("close failed.\n");
149        return LOS_NOK;
150    }
151
152    /* 删除文件"user/test/file.txt" */
153    ret = unlink(fileName);
154    if (ret != LOS_OK) {
155        printf("unlink failed.\n");
156        return LOS_NOK;
157    }
158
159    /* 删除目录“user/test” */
160    ret = rmdir(dirName);
161    if (ret != LOS_OK) {
162        printf("rmdir failed.\n");
163        return LOS_NOK;
164    }
165
166    return LOS_OK;
167}
168```
169
170### 结果验证<a name="section7987101232311"></a>
171
172编译运行得到的结果为:
173
174```
175Hello OpenHarmony!
176```
177
178