FileSystem
文件系统 API 提供用于在基于块的存储设备上实现文件系统的公共接口。文件系统 API 是基于类的接口,但实现文件系统 API 提供了 C 用户熟悉的标准 POSIX 文件 API。
FileSystem 的主要目的是实例化。FileSystem 的构造函数可以接受指定为字符串的 BlockDevice 和挂载点,以及其他特定于实现的配置选项。然后,当与 POSIX API 一起使用时,挂载点可以充当 Mbed OS 中任何路径中的第一个目录。这使您可以访问文件系统内的文件。如果您只需要将 FileSystem 用作 C++ 对象,则挂载点可以为 NULL。
FileSystem 的 file
和 dir
函数受到保护,因为您不应直接使用 FileSystem file
和 dir
函数。它们只是实现者的便利。相反,File 和 Dir 类提供对 C++ 类中的文件和目录操作的访问,这些操作遵循 RAII 和其他 C++ 约定。
文件系统类参考
公共成员函数 | |
FileSystem (const char *name=NULL) | |
virtual int | mount (BlockDevice *bd)=0 |
virtual int | unmount ()=0 |
virtual int | reformat (BlockDevice *bd=NULL) |
virtual int | remove (const char *path) |
virtual int | rename (const char *path, const char *newpath) |
virtual int | stat (const char *path, struct stat *st) |
virtual int | mkdir (const char *path, mode_t mode) |
virtual int | statvfs (const char *path, struct statvfs *buf) |
公共成员函数继承自 mbed::FileSystemLike | |
FileSystemLike (const char *name=NULL) | |
FileHandle * | open (const char *path, int flags) |
DirHandle * | opendir (const char *path) |
公共成员函数继承自 mbed::FileSystemHandle | |
virtual | ~FileSystemHandle () |
公共成员函数继承自 mbed::FileBase | |
FileBase (const char *name, PathType t) | |
const char * | getName (void) |
PathType | getPathType (void) |
受保护的成员函数 | |
virtual int | file_open (fs_file_t *file, const char *path, int flags)=0 |
virtual int | file_close (fs_file_t file)=0 |
virtual ssize_t | file_read (fs_file_t file, void *buffer, size_t size)=0 |
virtual ssize_t | file_write (fs_file_t file, const void *buffer, size_t size)=0 |
virtual int | file_sync (fs_file_t file) |
virtual int | file_isatty (fs_file_t file) |
virtual off_t | file_seek (fs_file_t file, off_t offset, int whence)=0 |
virtual off_t | file_tell (fs_file_t file) |
virtual void | file_rewind (fs_file_t file) |
virtual off_t | file_size (fs_file_t file) |
virtual int | dir_open (fs_dir_t *dir, const char *path) |
virtual int | dir_close (fs_dir_t dir) |
virtual ssize_t | dir_read (fs_dir_t dir, struct dirent *ent) |
virtual void | dir_seek (fs_dir_t dir, off_t offset) |
virtual off_t | dir_tell (fs_dir_t dir) |
virtual void | dir_rewind (fs_dir_t dir) |
virtual size_t | dir_size (fs_dir_t dir) |
virtual int | open (FileHandle **file, const char *path, int flags) |
virtual int | open (DirHandle **dir, const char *path) |
友元 | |
class | File |
class | Dir |
其他继承成员 | |
静态公共成员函数继承自 mbed::FileBase | |
static FileBase * | lookup (const char *name, unsigned int len) |
static FileBase * | get (int n) |
文件系统示例
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include <stdio.h>
#include <errno.h>
// Block devices
#include "SPIFBlockDevice.h"
#include "DataFlashBlockDevice.h"
#include "SDBlockDevice.h"
#include "HeapBlockDevice.h"
// File systems
#include "LittleFileSystem.h"
#include "FATFileSystem.h"
// Physical block device, can be any device that supports the BlockDevice API
SPIFBlockDevice bd(
MBED_CONF_SPIF_DRIVER_SPI_MOSI,
MBED_CONF_SPIF_DRIVER_SPI_MISO,
MBED_CONF_SPIF_DRIVER_SPI_CLK,
MBED_CONF_SPIF_DRIVER_SPI_CS);
// File system declaration
LittleFileSystem fs("fs");
// Set up the button to trigger an erase
InterruptIn irq(BUTTON1);
void erase() {
printf("Initializing the block device... ");
fflush(stdout);
int err = bd.init();
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Erasing the block device... ");
fflush(stdout);
err = bd.erase(0, bd.size());
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Deinitializing the block device... ");
fflush(stdout);
err = bd.deinit();
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
}
// Entry point for the example
int main() {
printf("--- Mbed OS filesystem example ---\n");
// Setup the erase event on button press, use the event queue
// to avoid running in interrupt context
irq.fall(mbed_event_queue()->event(erase));
// Try to mount the filesystem
printf("Mounting the filesystem... ");
fflush(stdout);
int err = fs.mount(&bd);
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
// Reformat if we can't mount the filesystem
// this should only happen on the first boot
printf("No filesystem found, formatting... ");
fflush(stdout);
err = fs.reformat(&bd);
printf("%s\n", (err ? "Fail :(" : "OK"));
if (err) {
error("error: %s (%d)\n", strerror(-err), err);
}
}
// Open the numbers file
printf("Opening \"/fs/numbers.txt\"... ");
fflush(stdout);
FILE *f = fopen("/fs/numbers.txt", "r+");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
// Create the numbers file if it doesn't exist
printf("No file found, creating a new file... ");
fflush(stdout);
f = fopen("/fs/numbers.txt", "w+");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
for (int i = 0; i < 10; i++) {
printf("\rWriting numbers (%d/%d)... ", i, 10);
fflush(stdout);
err = fprintf(f, " %d\n", i);
if (err < 0) {
printf("Fail :(\n");
error("error: %s (%d)\n", strerror(errno), -errno);
}
}
printf("\rWriting numbers (%d/%d)... OK\n", 10, 10);
printf("Seeking file... ");
fflush(stdout);
err = fseek(f, 0, SEEK_SET);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
}
// Go through and increment the numbers
for (int i = 0; i < 10; i++) {
printf("\rIncrementing numbers (%d/%d)... ", i, 10);
fflush(stdout);
// Get current stream position
long pos = ftell(f);
// Parse out the number and increment
int32_t number;
fscanf(f, "%d", &number);
number += 1;
// Seek to beginning of number
fseek(f, pos, SEEK_SET);
// Store number
fprintf(f, " %d\n", number);
// Flush between write and read on same file
fflush(f);
}
printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10);
// Close the file which also flushes any cached writes
printf("Closing \"/fs/numbers.txt\"... ");
fflush(stdout);
err = fclose(f);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Display the root directory
printf("Opening the root directory... ");
fflush(stdout);
DIR *d = opendir("/fs/");
printf("%s\n", (!d ? "Fail :(" : "OK"));
if (!d) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
printf("root directory:\n");
while (true) {
struct dirent *e = readdir(d);
if (!e) {
break;
}
printf(" %s\n", e->d_name);
}
printf("Closing the root directory... ");
fflush(stdout);
err = closedir(d);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Display the numbers file
printf("Opening \"/fs/numbers.txt\"... ");
fflush(stdout);
f = fopen("/fs/numbers.txt", "r");
printf("%s\n", (!f ? "Fail :(" : "OK"));
if (!f) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
printf("numbers:\n");
while (!feof(f)) {
int c = fgetc(f);
printf("%c", c);
}
printf("\rClosing \"/fs/numbers.txt\"... ");
fflush(stdout);
err = fclose(f);
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(errno), -errno);
}
// Tidy up
printf("Unmounting... ");
fflush(stdout);
err = fs.unmount();
printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
if (err < 0) {
error("error: %s (%d)\n", strerror(-err), err);
}
printf("Mbed OS filesystem example done!\n");
}
扇区要求
LittleFS 要求:
- 4 blocks root dir。
- 2 blocks per dir。
- 1 block per file。
FATFS 要求:
- Hard minimum: 256 blocks。
- 128 blocks for FAT table。
- 1 block per dir。
- 1 block per file。