# Virtual File System

In early embedded systems, the data that needed to be stored was relatively small and the data type was relatively simple. The method of directly writing data to the specified address in the storage device was often used to store data. However, with the development of embedded device functions, the data that needs to be stored is increasing and becoming more and more complex. At this time, it becomes very cumbersome and difficult to use the old method to store and manage data. Therefore, we need a new data management method to simplify the organization of stored data. This method is the file system that we will introduce next.

The file system is an abstract data type that implements data storage, hierarchical organization, access, and retrieval. It is a mechanism for providing users with low-level data access. The basic unit of storage in a file system is usually a file, that is, data is organized in a file-by-file manner. When there are many files, there will be a large number of files that are difficult to classify and have duplicate names. A folder exists as a container for multiple files.

This chapter explains the RT-Thread file system and takes you to understand the architecture, functional features and usage of the RT-Thread virtual file system.

### [Introduction to DFS](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=dfs-%e7%ae%80%e4%bb%8b) <a href="#dfs-jian-jie" id="dfs-jian-jie"></a>

DFS is a virtual file system component provided by RT-Thread. Its full name is Device File System, which is a device virtual file system. The name of the file system uses a style similar to UNIX files and folders. The directory structure is shown in the following figure:

![Directory structure diagram](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-dir.png)

In RT-Thread DFS, the file system has a unified root directory, which `/`is represented by . The f1.bin file in the root directory is `/f1.bin`represented by , and the files in the 2018 directory `f1.bin`are `/data/2018/f1.bin`represented by . That is, the directory separator is `/`, which is exactly the same as UNIX/Linux, but different from Windows (Windows operating system uses `\`as the directory separator).

#### [DFS Architecture](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=dfs-%e6%9e%b6%e6%9e%84) <a href="#dfs-jia-gou" id="dfs-jia-gou"></a>

The main features of the RT-Thread DFS component are:

* Provides a unified POSIX file and directory operation interface for applications: read, write, poll/select, etc.
* It supports multiple types of file systems, such as FatFS, RomFS, DevFS, etc., and provides management of common files, device files, and network file descriptors.
* Supports various types of storage devices, such as SD Card, SPI Flash, Nand Flash, etc.

The hierarchical architecture of DFS is shown in the figure below, which is mainly divided into POSIX interface layer, virtual file system layer and device abstraction layer.

![DFS hierarchical architecture diagram](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-layer.png)

#### [POSIX interface layer](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=posix-%e6%8e%a5%e5%8f%a3%e5%b1%82) <a href="#posix-jie-kou-ceng" id="posix-jie-kou-ceng"></a>

POSIX stands for Portable Operating System Interface of UNIX (POSIX for short). The POSIX standard defines the interface standards that the operating system should provide to applications. It is the general name for a series of API standards defined by IEEE for software to run on various UNIX operating systems.

The POSIX standard is intended to achieve software portability at the source code level. In other words, a program written for a POSIX-compatible operating system should be compilable and executable on any other POSIX operating system (even if it comes from another manufacturer). RT-Thread supports the POSIX standard interface, so it is easy to port Linux/Unix programs to the RT-Thread operating system.

In Unix-like systems, ordinary files, device files, and network file descriptors are the same file descriptors. In the RT-Thread operating system, DFS is used to achieve this unification. With this unification of file descriptors, we can use the poll/select interface to uniformly poll these descriptors, which brings convenience to the implementation of program functions.

The poll/select interface can be used to block and simultaneously detect whether a group of I/O devices that support non-blocking have events (such as readable, writable, high-priority error output, error, etc.) until a device triggers an event or exceeds the specified waiting time. This mechanism can help the caller find the currently ready device and reduce the complexity of programming.

#### [Virtual file system layer](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%99%9a%e6%8b%9f%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e5%b1%82) <a href="#xu-ni-wen-jian-xi-tong-ceng" id="xu-ni-wen-jian-xi-tong-ceng"></a>

Users can register specific file systems to DFS, such as FatFS, RomFS, DevFS, etc. The following are some common file system types:

* FatFS is a file system compatible with Microsoft FAT format developed specifically for small embedded devices. It is written in ANSI C and has good hardware independence and portability. It is the most commonly used file system type in RT-Thread.
* The traditional RomFS file system is a simple, compact, read-only file system that does not support dynamic erasure and storage and stores data in sequence. It supports applications running in XIP (execute in place) mode, saving RAM space when the system is running.
* Jffs2 file system is a log flash file system. It is mainly used for NOR flash memory, based on MTD driver layer, and has the following features: readable and writable, supports data compression, is a log file system based on hash table, provides crash/power-off safety protection, provides write balancing support, etc.
* DevFS is the device file system. After enabling this function in the RT-Thread operating system, the devices in the system can be virtualized into files in the /dev folder, so that the devices can be operated using read, write and other interfaces in the same way as files.
* NFS Network File System (NFS) is a technology for sharing files between different machines and different operating systems over the network. During the development and debugging phase of the operating system, this technology can be used to create an NFS-based root file system on the host and mount it on an embedded device, so that the content of the root file system can be easily modified.
* UFFS is the abbreviation of Ultra-low-cost Flash File System. It is an open source file system developed by Chinese people and is specially designed for using Nand Flash in small memory environments such as embedded devices. Compared with the Yaffs file system commonly used in embedded systems, it has the advantages of less resource usage, fast startup speed, and free of charge.

#### [Device Abstraction Layer](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%ae%be%e5%a4%87%e6%8a%bd%e8%b1%a1%e5%b1%82) <a href="#she-bei-chou-xiang-ceng" id="she-bei-chou-xiang-ceng"></a>

The device abstraction layer abstracts physical devices such as SD Card, SPI Flash, and Nand Flash into devices that can be accessed by the file system. For example, the FAT file system requires that storage devices must be block device types.

Different file system types are implemented independently of storage device drivers. Therefore, the file system function can only be used correctly after the driver interface of the underlying storage device is connected with the file system.

### [Mount Management](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%8c%82%e8%bd%bd%e7%ae%a1%e7%90%86) <a href="#gua-zai-guan-li" id="gua-zai-guan-li"></a>

The initialization process of the file system is generally divided into the following steps:

1. Initializes the DFS components.
2. Initialize a file system of a specific type.
3. Create a block device on the storage.
4. Format a block device.
5. Mount the block device to the DFS directory.
6. When a file system is no longer in use, it can be unmounted.

#### [Initialize DFS components](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%88%9d%e5%a7%8b%e5%8c%96-dfs-%e7%bb%84%e4%bb%b6) <a href="#chu-shi-hua-dfs-zu-jian" id="chu-shi-hua-dfs-zu-jian"></a>

The initialization of the DFS component is completed by the dfs\_init() function. The dfs\_init() function will initialize the relevant resources required by DFS and create some key data structures. With these data structures, DFS can find a specific file system in the system and obtain the operation method for files in a specific storage device. If automatic initialization is enabled (enabled by default), this function will be called automatically.

#### [Registering a file system](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%b3%a8%e5%86%8c%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f) <a href="#zhu-ce-wen-jian-xi-tong" id="zhu-ce-wen-jian-xi-tong"></a>

After the DFS component is initialized, the specific type of file system to be used needs to be initialized, that is, the specific type of file system needs to be registered in DFS. The interface for registering a file system is as follows:

```c
int dfs_register(const struct dfs_filesystem_ops *ops);copymistakeCopy Success
```

| **parameter** | **describe**                                    |
| ------------- | ----------------------------------------------- |
| ops           | A collection of file system operation functions |
| **return**    | **——**                                          |
| 0             | File registration successful                    |
| -1            | File registration failed                        |

This function does not need to be called by the user, it will be called by the initialization function of different file systems, such as the initialization function of the elm-FAT file system `elm_init()`. After the corresponding file system is enabled, if automatic initialization is enabled (enabled by default), the file system initialization function will also be automatically called.

`elm_init()`The function will initialize the elm-FAT file system. This function will call `dfs_register(`the function to register the elm-FAT file system to DFS. The file system registration process is shown in the figure below:

![Registering a file system](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-reg.png)

#### [Registering a storage device as a block device](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%b0%86%e5%ad%98%e5%82%a8%e8%ae%be%e5%a4%87%e6%b3%a8%e5%86%8c%e4%b8%ba%e5%9d%97%e8%ae%be%e5%a4%87) <a href="#jiang-cun-chu-she-bei-zhu-ce-wei-kuai-she-bei" id="jiang-cun-chu-she-bei-zhu-ce-wei-kuai-she-bei"></a>

Because only block devices can be mounted on the file system, it is necessary to create the required block devices on the storage device. If the storage device is SPI Flash, you can use the "Serial Flash Universal Driver Library SFUD" component, which provides various SPI Flash drivers and abstracts SPI Flash into block devices for mounting. The process of registering a block device is shown in the following figure:

![Register block device timing diagram](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-reg-block.png)

#### [Format the file system](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%a0%bc%e5%bc%8f%e5%8c%96%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f) <a href="#ge-shi-hua-wen-jian-xi-tong" id="ge-shi-hua-wen-jian-xi-tong"></a>

After registering the block device, you need to create a file system of the specified type on the block device, that is, format the file system. You can use `dfs_mkfs()`the function to format the specified storage device and create a file system. The interface for formatting the file system is as follows:

```c
int dfs_mkfs(const char * fs_name, const char * device_name);copymistakeCopy Success
```

| **parameter** | **describe**                               |
| ------------- | ------------------------------------------ |
| fs\_name      | File system type                           |
| device\_name  | Block device name                          |
| **return**    | **——**                                     |
| 0             | The file system was formatted successfully |
| -1            | File system formatting failed              |

The possible values ​​of the file system type (fs\_name) and the corresponding file systems are shown in the following table:

| **Value** | **File system type**               |
| --------- | ---------------------------------- |
| elm       | elm-FAT file system                |
| jffs2     | jffs2 Journaling Flash File System |
| nfs       | NFS Network File System            |
| ram       | RamFS File System                  |
| rom       | RomFS read-only file system        |
| uffs      | uffs file system                   |
| lfs       | littlefs file system               |

Taking the elm-FAT file system to format a block device as an example, the formatting process is shown in the following figure:

![Format the file system](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/elm-fat-mkfs.png)

You can also use `mkfs`the command to format the file system. The result of formatting the block device sd0 is as follows:

```c
msh />mkfs sd0                    # sd0 为块设备名称，该命令会默认格式化 sd0 为 elm-FAT 文件系统
msh />
msh />mkfs -t elm sd0             # 使用 -t 参数指定文件系统类型为 elm-FAT 文件系统copymistakeCopy Success
```

#### [Mounting the file system](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%8c%82%e8%bd%bd%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f) <a href="#gua-zai-wen-jian-xi-tong" id="gua-zai-wen-jian-xi-tong"></a>

In RT-Thread, mounting means attaching a storage device to an existing path. To access files in a storage device, we must mount the partition where the file is located to an existing path, and then access the storage device through this path. The interface for mounting a file system is as follows:

```c
int dfs_mount(const char   *device_name,
              const char   *path,
              const char   *filesystemtype,
              unsigned long rwflag,
              const void   *data);copymistakeCopy Success
```

| **parameter**  | **describe**                                                                                          |
| -------------- | ----------------------------------------------------------------------------------------------------- |
| device\_name   | The name of the formatted block device                                                                |
| path           | Mount path, that is, mount point                                                                      |
| filesystemtype | The type of file system to be mounted. For possible values, see the dfs\_mkfs() function description. |
| rwflag         | Read and write flag                                                                                   |
| data           | Private data for a specific file system                                                               |
| **return**     | **——**                                                                                                |
| 0              | The file system is mounted successfully                                                               |
| -1             | File system mount failed                                                                              |

If there is only one storage device, you can mount it directly to the root directory `/`.

#### [Unmounting the file system](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%8d%b8%e8%bd%bd%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f) <a href="#xie-zai-wen-jian-xi-tong" id="xie-zai-wen-jian-xi-tong"></a>

When a file system is no longer needed, it can be uninstalled. The interface for uninstalling a file system is as follows:

```c
int dfs_unmount(const char *specialfile);copymistakeCopy Success
```

| **parameter** | **describe**                            |
| ------------- | --------------------------------------- |
| specialfile   | Mount path                              |
| **return**    | **——**                                  |
| 0             | Unmounting the file system successfully |
| -1            | Failed to unmount the file system       |

### [File Management](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%96%87%e4%bb%b6%e7%ae%a1%e7%90%86) <a href="#wen-jian-guan-li" id="wen-jian-guan-li"></a>

This section introduces the functions related to file operations. File operations are generally based on the file descriptor fd, as shown in the following figure:

![Common functions for file management](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-mg.png)

#### [Opening and Closing Files](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%89%93%e5%bc%80%e5%92%8c%e5%85%b3%e9%97%ad%e6%96%87%e4%bb%b6) <a href="#da-kai-he-guan-bi-wen-jian" id="da-kai-he-guan-bi-wen-jian"></a>

To open or create a file, you can call the following open() function:

```c
int open(const char *file, int flags, ...);copymistakeCopy Success
```

| **parameter**    | **describe**                                                                           |
| ---------------- | -------------------------------------------------------------------------------------- |
| file             | The name of the file to open or create                                                 |
| flags            | Specify the method to open the file. The values ​​can be found in the following table. |
| **return**       | **——**                                                                                 |
| File Descriptors | File opened successfully                                                               |
| -1               | File open failed                                                                       |

A file can be opened in multiple ways, and multiple opening modes can be specified at the same time. For example, if a file is opened in O\_RDONLY and O\_CREAT modes, then if the specified file does not exist, the file will be created first and then opened in read-only mode. The file opening modes are shown in the following table:

| **parameter** | **describe**                                                                                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| O\_RDONLY     | Open the file in read-only mode                                                                                                                              |
| O\_WRONLY     | Open the file for writing only                                                                                                                               |
| O\_RDWR       | Open the file for reading and writing                                                                                                                        |
| O\_CREAT      | If the file to be opened does not exist, it is created.                                                                                                      |
| O\_APPEND     | When reading and writing files, they start moving from the end of the file, that is, the written data is added to the end of the file in an appended manner. |
| O\_TRUNC      | If the file already exists, clear the contents of the file                                                                                                   |

When you have finished using a file and no longer need to use it, you can use `close()`the function to close the file, which `close()`will write the data back to the disk and release the resources occupied by the file.

```
int close(int fd);copymistakeCopy Success
```

| **parameter** | **describe**             |
| ------------- | ------------------------ |
| fd            | File Descriptors         |
| **return**    | **——**                   |
| 0             | File closed successfully |
| -1            | File close failed        |

#### [Reading and Writing Data](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%af%bb%e5%86%99%e6%95%b0%e6%8d%ae) <a href="#du-xie-shu-ju" id="du-xie-shu-ju"></a>

To read the file contents, use `read()`the function:

```
int read(int fd, void *buf, size_t len);copymistakeCopy Success
```

| **parameter** | **describe**                                                                   |
| ------------- | ------------------------------------------------------------------------------ |
| fd            | File Descriptors                                                               |
| buf           | Buffer pointer                                                                 |
| len           | The number of bytes read from the file                                         |
| **return**    | **——**                                                                         |
| int           | The actual number of bytes read                                                |
| 0             | The read data has reached the end of the file or there is no more data to read |
| -1            | Read error, error code see errno of the current thread                         |

This function will read len bytes of the file pointed to by the parameter fd into the memory pointed to by the buf pointer. In addition, the file's read and write position pointer will move with the bytes read.

To write data to a file, use `write()`the function:

```
int write(int fd, const void *buf, size_t len);copymistakeCopy Success
```

| **parameter** | **describe**                                              |
| ------------- | --------------------------------------------------------- |
| F             | File Descriptors                                          |
| buf           | Buffer pointer                                            |
| len           | The number of bytes written to the file                   |
| **return**    | **——**                                                    |
| int           | The actual number of bytes written                        |
| -1            | Writing error, error code see errno of the current thread |

This function will write len bytes in the memory pointed to by the buf pointer to the file pointed to by the parameter fd. In addition, the file's read and write position pointers will move with the bytes written.

#### [Rename](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e9%87%8d%e5%91%bd%e5%90%8d) <a href="#zhong-ming-ming" id="zhong-ming-ming"></a>

To rename a file, use `rename()`the function:

```
int rename(const char *old, const char *new);copymistakeCopy Success
```

| **parameter** | **describe**              |
| ------------- | ------------------------- |
| old           | Old file name             |
| new           | New File Name             |
| **return**    | **——**                    |
| 0             | Name changed successfully |
| -1            | Change name failed        |

This function will change the file name specified by the parameter old to the file name specified by the parameter new. If the file specified by new already exists, it will be overwritten.

#### [Get Status](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%8f%96%e5%be%97%e7%8a%b6%e6%80%81) <a href="#qu-de-zhuang-tai" id="qu-de-zhuang-tai"></a>

To get the file status, use the following `stat()`function:

```
int stat(const char *file, struct stat *buf);copymistakeCopy Success
```

| **parameter** | **describe**                                                                   |
| ------------- | ------------------------------------------------------------------------------ |
| file          | file name                                                                      |
| buf           | Structure pointer, pointing to a structure that stores file status information |
| **return**    | **——**                                                                         |
| 0             | Get status successfully                                                        |
| -1            | Failed to get status                                                           |

#### [Deleting Files](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%88%a0%e9%99%a4%e6%96%87%e4%bb%b6) <a href="#shan-chu-wen-jian" id="shan-chu-wen-jian"></a>

To delete files in a specified directory, you can use `unlink()`the function:

```
int unlink(const char *pathname);copymistakeCopy Success
```

| **parameter** | **describe**                                        |
| ------------- | --------------------------------------------------- |
| pathname      | Specify the absolute path of the file to be deleted |
| **return**    | **——**                                              |
| 0             | Delete file successfully                            |
| -1            | Failed to delete file                               |

#### [Synchronize file data to storage devices](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%90%8c%e6%ad%a5%e6%96%87%e4%bb%b6%e6%95%b0%e6%8d%ae%e5%88%b0%e5%ad%98%e5%82%a8%e8%ae%be%e5%a4%87) <a href="#tong-bu-wen-jian-shu-ju-dao-cun-chu-she-bei" id="tong-bu-wen-jian-shu-ju-dao-cun-chu-she-bei"></a>

To synchronize all modified file data in memory to the storage device, you can use `fsync()`the function:

```c
int fsync(int fildes);copymistakeCopy Success
```

| **parameter** | **describe**                   |
| ------------- | ------------------------------ |
| Fildes        | File Descriptors               |
| **return**    | **——**                         |
| 0             | Synchronize files successfully |
| -1            | Failed to sync files           |

#### [Query file system related information](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%9f%a5%e8%af%a2%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e7%9b%b8%e5%85%b3%e4%bf%a1%e6%81%af) <a href="#cha-xun-wen-jian-xi-tong-xiang-guan-xin-xi" id="cha-xun-wen-jian-xi-tong-xiang-guan-xin-xi"></a>

To query the file system related information, you can use `statfs()`the function:

```c
int statfs(const char *path, struct statfs *buf);copymistakeCopy Success
```

| **parameter** | **describe**                                                 |
| ------------- | ------------------------------------------------------------ |
| path          | The mount path of the file system                            |
| buf           | Pointer to a structure used to store file system information |
| **return**    | **——**                                                       |
| 0             | Query file system information successfully                   |
| -1            | Failed to query file system information                      |

#### [Monitor I/O device status](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e7%9b%91%e8%a7%86-io-%e8%ae%be%e5%a4%87%e7%8a%b6%e6%80%81) <a href="#jian-shi-io-she-bei-zhuang-tai" id="jian-shi-io-she-bei-zhuang-tai"></a>

To monitor whether an I/O device has an event, you can use `select()`the function:

```c
int select( int nfds,
            fd_set *readfds,
            fd_set *writefds,
            fd_set *exceptfds,
            struct timeval *timeout);copymistakeCopy Success
```

| **parameter**   | **describe**                                                                                            |
| --------------- | ------------------------------------------------------------------------------------------------------- |
| nfds            | The range of all file descriptors in the set, that is, the maximum value of all file descriptors plus 1 |
| readfds         | The set of file descriptors that need to be monitored for read changes                                  |
| writefds        | The set of file descriptors that need to be monitored for write changes                                 |
| exceptfds       | Need to monitor the set of file descriptors that have abnormalities                                     |
| timeout         | select timeout                                                                                          |
| **return**      | **——**                                                                                                  |
| Positive        | The monitored file collection has a read/write event or an error                                        |
| 0               | Waiting timed out, no files to read or write or error                                                   |
| Negative Values | Error                                                                                                   |

The interface can be used to `select()`block and simultaneously detect whether a group of I/O devices that support non-blocking have events (such as readable, writable, high-priority error output, error, etc.) until a device triggers an event or exceeds the specified waiting time.

### [Catalog Management](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e7%9b%ae%e5%bd%95%e7%ae%a1%e7%90%86) <a href="#mu-lu-guan-li" id="mu-lu-guan-li"></a>

This section introduces the functions commonly used in directory management. The operations on directories are generally based on the directory address, as shown in the following figure:

![Common functions for directory management](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-dir-mg.png)

#### [Creating and Deleting Directories](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%88%9b%e5%bb%ba%e5%92%8c%e5%88%a0%e9%99%a4%e7%9b%ae%e5%bd%95) <a href="#chuang-jian-he-shan-chu-mu-lu" id="chuang-jian-he-shan-chu-mu-lu"></a>

To create a directory, use `mkdir()`the function:

```c
int mkdir(const char *path, mode_t mode);copymistakeCopy Success
```

| **parameter** | **describe**                          |
| ------------- | ------------------------------------- |
| path          | The absolute address of the directory |
| mode          | Create a schema                       |
| **return**    | **——**                                |
| 0             | Directory created successfully        |
| -1            | Failed to create directory            |

This function is used to create a directory or folder. The parameter path is the absolute path of the directory. The parameter mode is not enabled in the current version, so fill in the default parameter 0x777.

To delete a directory, use `rmdir()`the function:

```c
int rmdir(const char *pathname);copymistakeCopy Success
```

| **parameter** | **describe**                                     |
| ------------- | ------------------------------------------------ |
| pathname      | The absolute path of the directory to be deleted |
| **return**    | **——**                                           |
| 0             | Directory deleted successfully                   |
| -1            | Directory deletion error                         |

#### [Opening and Closing Directories](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%89%93%e5%bc%80%e5%92%8c%e5%85%b3%e9%97%ad%e7%9b%ae%e5%bd%95) <a href="#da-kai-he-guan-bi-mu-lu" id="da-kai-he-guan-bi-mu-lu"></a>

To open a directory, use `opendir()`the function:

```c
DIR* opendir(const char* name);copymistakeCopy Success
```

| **parameter** | **describe**                                                                 |
| ------------- | ---------------------------------------------------------------------------- |
| name          | The absolute address of the directory                                        |
| **return**    | **——**                                                                       |
| DIR           | Open the directory successfully and return a pointer to the directory stream |
| NULL          | Open Failed                                                                  |

To close a directory, you can use `closedir()`the function:

```c
int closedir(DIR* d);copymistakeCopy Success
```

| **parameter** | **describe**                  |
| ------------- | ----------------------------- |
| d             | Directory stream pointer      |
| **return**    | **——**                        |
| 0             | Directory closed successfully |
| -1            | Directory Close Error         |

This function is used to close a directory and must `opendir()`be used in conjunction with the function.

#### [Reading a Directory](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%af%bb%e5%8f%96%e7%9b%ae%e5%bd%95) <a href="#du-qu-mu-lu" id="du-qu-mu-lu"></a>

To read the directory, use `readdir()`the function:

```c
struct dirent* readdir(DIR *d);copymistakeCopy Success
```

| **parameter** | **describe**                                                         |
| ------------- | -------------------------------------------------------------------- |
| d             | Directory stream pointer                                             |
| **return**    | **——**                                                               |
| dirent        | A successful read returns a structure pointer to the directory entry |
| NULL          | End of directory read                                                |

This function is used to read a directory. The parameter d is the directory stream pointer. In addition, each time a directory is read, the pointer position of the directory stream will automatically move back by 1 position.

#### [Get the read position of the directory stream](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%8f%96%e5%be%97%e7%9b%ae%e5%bd%95%e6%b5%81%e7%9a%84%e8%af%bb%e5%8f%96%e4%bd%8d%e7%bd%ae) <a href="#qu-de-mu-lu-liu-de-du-qu-wei-zhi" id="qu-de-mu-lu-liu-de-du-qu-wei-zhi"></a>

To get the read position of the directory stream, use `telldir()`the function:

```
long telldir(DIR *d);copymistakeCopy Success
```

| **parameter** | **describe**                    |
| ------------- | ------------------------------- |
| d             | Directory stream pointer        |
| **return**    | **——**                          |
| long          | Read the offset of the position |

The return value of this function records the current position of a directory stream. This return value represents [the offset](https://baike.baidu.com/item/%E5%81%8F%E7%A7%BB%E9%87%8F) from the beginning of the directory file . You can use this value in subsequent `seekdir()`[function calls](https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8) to reset the directory to the current position. In other words, `telldir()`the function can `seekdir()`be used in conjunction with the function to reset the reading position of the directory stream to the specified offset.

#### [Set the location of the directory to be read next time](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%ae%be%e7%bd%ae%e4%b8%8b%e6%ac%a1%e8%af%bb%e5%8f%96%e7%9b%ae%e5%bd%95%e7%9a%84%e4%bd%8d%e7%bd%ae) <a href="#she-zhi-xia-ci-du-qu-mu-lu-de-wei-zhi" id="she-zhi-xia-ci-du-qu-mu-lu-de-wei-zhi"></a>

To set the location of the directory to be read next time, you can use `seekdir()`the function:

```
void seekdir(DIR *d, off_t offset);copymistakeCopy Success
```

| **parameter** | **describe**                                       |
| ------------- | -------------------------------------------------- |
| d             | Directory stream pointer                           |
| offset        | Offset value, the displacement from this directory |

This is used to set the reading position of the directory stream parameter d. When calling readdir(), reading starts from this new position.

#### [Reset the directory read position to the beginning](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e9%87%8d%e8%ae%be%e8%af%bb%e5%8f%96%e7%9b%ae%e5%bd%95%e7%9a%84%e4%bd%8d%e7%bd%ae%e4%b8%ba%e5%bc%80%e5%a4%b4%e4%bd%8d%e7%bd%ae) <a href="#zhong-she-du-qu-mu-lu-de-wei-zhi-wei-kai-tou-wei-zhi" id="zhong-she-du-qu-mu-lu-de-wei-zhi-wei-kai-tou-wei-zhi"></a>

To reset the directory stream's reading position to the beginning, use `rewinddir()`the function:

```
void rewinddir(DIR *d);copymistakeCopy Success
```

| **parameter** | **describe**             |
| ------------- | ------------------------ |
| d             | Directory stream pointer |

This function can be used to set the current reading position of the directory stream d to the initial position of the directory stream.

### [DFS Configuration Options](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=dfs-%e9%85%8d%e7%bd%ae%e9%80%89%e9%a1%b9) <a href="#dfs-pei-zhi-xuan-xiang" id="dfs-pei-zhi-xuan-xiang"></a>

The specific configuration path of the file system in menuconfig is as follows:

```c
RT-Thread Components  --->
    Device virtual file system  --->copymistakeCopy Success
```

The configuration menu description and corresponding macro definition are shown in the following table:

| **Configuration options**                                      | **Corresponding macro definition** | **describe**                             |
| -------------------------------------------------------------- | ---------------------------------- | ---------------------------------------- |
| \[\*] Using device virtual file system                         | RT\_USING\_DFS                     | Enable DFS virtual file system           |
| \[\*] Using working directory                                  | DFS\_USING\_WORKDIR                | Enable relative paths                    |
| (2) The maximum number of mounted file system                  | DFS\_FILESYSTEMS\_MAX              | Maximum number of mounted file systems   |
| (2) The maximum number of file system type                     | DFS\_FILESYSTEM\_TYPES\_MAX        | Maximum number of supported file systems |
| (4) The maximum number of opened files                         | DFS\_FD\_MAX                       | Maximum number of open files             |
| \[ ] Using mount table for file system                         | RT\_USING\_DFS\_MNTTABLE           | Enable automatic mount table             |
| \[\*] Enable elm-chan fatfs                                    | RT\_USING\_DFS\_ELMFAT             | Enable elm-FatFs file system             |
| \[\*] Using devfs for device objects                           | RT\_USING\_DFS\_DEVFS              | Enable DevFS device file system          |
| \[ ] Enable ReadOnly file system on flash                      | RT\_USING\_DFS\_ROMFS              | Enable RomFS file system                 |
| \[ ] Enable RAM file system                                    | RT\_USING\_DFS\_RAMFS              | Enable RamFS file system                 |
| \[ ] Enable UFFS file system: Ultra-low-cost Flash File System | RT\_USING\_DFS\_UFFS               | Enable UFFS file system                  |
| \[ ] Enable JFFS2 file system                                  | RT\_USING\_DFS\_JFFS2              | Enable JFFS2 file system                 |
| \[ ] Using NFS v3 client file system                           | RT\_USING\_DFS\_NFS                | Enable NFS file system                   |

By default, the RT-Thread operating system does not enable the relative path function in order to obtain a smaller memory footprint. When the relative path support option is not enabled, you should use absolute directories when using file and directory interfaces for operations (because the current working directory does not exist in the system at this time). If you need to use the current working directory and relative directories, you can enable the relative path function in the file system configuration item.

After the option `[*] Using mount table for file system`is selected, the corresponding macro will be enabled `RT_USING_DFS_MNTTABLE`to turn on the automatic mount table function. The automatic mount table `mount_table[]`is provided by the user in the application code. The user needs to specify the device name, mount path, file system type, read-write flags and private data in the table. After that, the system will traverse the mount table to perform the mount. It should be noted that the mount table must end with {0} to determine the end of the table.

An example of the automatic mount table `mount_table[]`is shown below, where `mount_table[0]`the five members are `dfs_mount()`the five parameters of the function, which means mounting the elm file system to the / path of the flash0 device, with rwflag being 0 and data being 0; `mount_table[1]`and ending with {0} to determine the end of the table.

```c
const struct dfs_mount_tbl mount_table[] =
{
    {"flash0", "/", "elm", 0, 0},
    {0}
};copymistakeCopy Success
```

#### [elm-FatFs file system configuration options](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=elm-fatfs-%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e9%85%8d%e7%bd%ae%e9%80%89%e9%a1%b9) <a href="#elmfatfs-wen-jian-xi-tong-pei-zhi-xuan-xiang" id="elmfatfs-wen-jian-xi-tong-pei-zhi-xuan-xiang"></a>

After enabling the elm-FatFs file system in menuconfig, you can further configure elm-FatFs. The configuration menu description and corresponding macro definitions are shown in the following table:

| **Configuration options**                                     | **Corresponding macro definition** | **describe**                         |
| ------------------------------------------------------------- | ---------------------------------- | ------------------------------------ |
| (437) OEM code page                                           | RT\_DFS\_ELM\_CODE\_PAGE           | Encoding                             |
| \[\*] Using RT\_DFS\_ELM\_WORD\_ACCESS                        | RT\_DFS\_ELM\_WORD\_ACCESS         |                                      |
| Support long file name (0: LFN disable) --->                  | RT\_DFS\_ELM\_USE\_LFN             | Open the long file name submenu      |
| (255) Maximal size of file name length                        | RT\_DFS\_ELM\_MAX\_LFN             | Maximum file name length             |
| (2) Number of volumes (logical drives) to be used.            | RT\_DFS\_ELM\_DRIVES               | Number of devices mounted with FatFs |
| (4096) Maximum sector size to be handled.                     | RT\_DFS\_ELM\_MAX\_SECTOR\_SIZE    | File system sector size              |
| \[ ] Enable sector erase feature                              | RT\_DFS\_ELM\_USE\_ERASE           |                                      |
| \[\*] Enable the reentrancy (thread safe) of the FatFs module | RT\_DFS\_ELM\_REENTRANT            | Enable reentrancy                    |

[**Long file names**](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e9%95%bf%e6%96%87%e4%bb%b6%e5%90%8d)

By default, FatFs file naming has the following disadvantages:

* The file name (excluding the suffix) cannot be longer than 8 characters, and the suffix cannot be longer than 3 characters. The file name and suffix will be truncated if they exceed the limit.
* File names are not case sensitive (displayed as uppercase letters)

If you need to support long file names, you need to turn on the long file name support option. The long file name submenu description is as follows:

| **Configuration options**                               | **Corresponding macro definition** | **describe**                                                                                                                |
| ------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| ( ) 0: LFN disable                                      | RT\_DFS\_ELM\_USE\_LFN\_0          | Turn off long file names                                                                                                    |
| ( ) 1: LFN with static LFN working buffer               | RT\_DFS\_ELM\_USE\_LFN\_1          | Use static buffer to support long file names, which will cause reentrancy problems when multi-threaded file name operations |
| ( ) 2: LFN with dynamic LFN working buffer on the stack | RT\_DFS\_ELM\_USE\_LFN\_2          | Uses a temporary buffer in the stack to support long file names. Large stack space requirements                             |
| (X) 3: LFN with dynamic LFN working buffer on the heap  | RT\_DFS\_ELM\_USE\_LFN\_3          | Use heap (malloc) buffer to store long file names, which is the safest (default mode)                                       |

[**Encoding**](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e7%bc%96%e7%a0%81%e6%96%b9%e5%bc%8f)

When long file name support is enabled, you can set the file name encoding. RT-Thread/FatFs uses 437 encoding (American English) by default. If you need to store Chinese file names, you can use 936 encoding (GBK encoding). 936 encoding requires a font library of about 180KB. If you only use English characters as files, it is recommended to use 437 encoding (American English), which can save 180KB of Flash space.

The file encodings supported by FatFs are as follows:

```c
/* This option specifies the OEM code page to be used on the target system.
/  Incorrect setting of the code page can cause a file open failure.
/
/   1   - ASCII (No extended character. Non-LFN cfg. only)
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
*/copymistakeCopy Success
```

[**File system sector size**](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e6%89%87%e5%8c%ba%e5%a4%a7%e5%b0%8f)

Specify the internal sector size of FatFs, which needs to be greater than or equal to the sector size of the actual hardware driver. For example, if the sector size of a spi flash chip is 4096 bytes, the above macro needs to be modified to 4096, otherwise the array will be out of bounds when FatFs reads data from the driver, causing the system to crash (the new version will give a warning message when the system is executed).

Generally, the sector size of Flash devices can be set to 4096, and the sector size of common TF cards and SD cards is set to 512.

[**Reentrancy**](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%8f%af%e9%87%8d%e5%85%a5%e6%80%a7)

FatFs takes into full consideration the safety of multi-threaded reading and writing. When reading and writing FatFs in multiple threads, in order to avoid the problem of reentry, the above macro needs to be turned on. If the system has only one thread operating the file system and there will be no reentry problem, this function can be turned off to save resources.

[**More Configuration**](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%9b%b4%e5%a4%9a%e9%85%8d%e7%bd%ae)

FatFs itself supports a lot of configuration options and is very flexible. The following file is the configuration file of FatFs, which can be modified to customize FatFs.

```c
components/dfs/filesystems/elmfat/ffconf.hcopymistakeCopy Success
```

### [DFS Application Examples](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=dfs-%e5%ba%94%e7%94%a8%e7%a4%ba%e4%be%8b) <a href="#dfs-ying-yong-shi-li" id="dfs-ying-yong-shi-li"></a>

#### [FinSH Commands](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=finsh-%e5%91%bd%e4%bb%a4) <a href="#finsh-ming-ling" id="finsh-ming-ling"></a>

After the file system is mounted successfully, you can operate files and directories. The commonly used FinSH commands for file system operations are shown in the following table:

| **FinSH Commands** | **describe**                                                                                                                                                   |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ls                 | Display information about files and directories                                                                                                                |
| cd                 | Enter the specified directory                                                                                                                                  |
| cp                 | Copying Files                                                                                                                                                  |
| rm                 | Deleting a file or directory                                                                                                                                   |
| mv                 | Move or rename the file                                                                                                                                        |
| echo               | Write the specified content to the specified file. If the file exists, write it to the file. If the file does not exist, create a new file and write it to it. |
| cat                | Display the contents of a file                                                                                                                                 |
| pwd                | Print out the current directory address                                                                                                                        |
| mkdir              | Create a folder                                                                                                                                                |
| mkfs               | Format the file system                                                                                                                                         |

Use `ls`the command to view the current directory information. The running results are as follows:

```c
msh />ls                          # 使用 ls 命令查看文件系统目录信息
Directory /:                      # 可以看到已经存在根目录 /copymistakeCopy Success
```

Use `mkdir`the command to create a folder. The running result is as follows:

```c
msh />mkdir rt-thread             # 创建 rt-thread 文件夹
msh />ls                          # 查看目录信息如下
Directory /:
rt-thread           <DIR>copymistakeCopy Success
```

Use `echo`the command to output the input string to the specified output location. The running result is as follows:

```c
msh />echo "hello rt-thread!!!"                 # 将字符串输出到标准输出
hello rt-thread!!!
msh />echo "hello rt-thread!!!" hello.txt      # 将字符串出输出到 hello.txt 文件
msh />ls
Directory /:
rt-thread           <DIR>
hello.txt           18
msh />copymistakeCopy Success
```

Use `cat`the command to view the file contents. The running results are as follows:

```c
msh />cat hello.txt                     # 查看 hello.txt 文件的内容并输出
hello rt-thread!!!copymistakeCopy Success
```

Use `rm`the command to delete folders or files. The running results are as follows:

```c
msh />ls                                # 查看当前目录信息
Directory /:
rt-thread           <DIR>
hello.txt           18
msh />rm rt-thread                      # 删除 rt-thread 文件夹
msh />ls
Directory /:
hello.txt           18
msh />rm hello.txt                      # 删除 hello.txt 文件
msh />ls
Directory /:
msh />copymistakeCopy Success
```

#### [Read and write file examples](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%af%bb%e5%86%99%e6%96%87%e4%bb%b6%e7%a4%ba%e4%be%8b) <a href="#du-xie-wen-jian-shi-li" id="du-xie-wen-jian-shi-li"></a>

After the file system works properly, you can run the application example. In this sample code, you will first use `open()`the function to create a file text.txt, use the write() function to write a string to the file `“RT-Thread Programmer!\n”`, and then close the file. Use the function again `open()`to open the text.txt file, read out the content and print it out, and finally close the file.

The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

static void readwrite_sample(void)
{
    int fd, size;
    char s[] = "RT-Thread Programmer!", buffer[80];

    rt_kprintf("Write string %s to test.txt.\n", s);

    /* 以创建和读写模式打开 /text.txt 文件，如果该文件不存在则创建该文件 */
    fd = open("/text.txt", O_WRONLY | O_CREAT);
    if (fd>= 0)
    {
        write(fd, s, sizeof(s));
        close(fd);
        rt_kprintf("Write done.\n");
    }

      /* 以只读模式打开 /text.txt 文件 */
    fd = open("/text.txt", O_RDONLY);
    if (fd>= 0)
    {
        size = read(fd, buffer, sizeof(buffer));
        close(fd);
        rt_kprintf("Read from file test.txt : %s \n", buffer);
        if (size < 0)
            return ;
    }
  }
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(readwrite_sample, readwrite sample);
copymistakeCopy Success
```

#### [Example of changing file name](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e6%9b%b4%e6%94%b9%e6%96%87%e4%bb%b6%e5%90%8d%e7%a7%b0%e7%a4%ba%e4%be%8b) <a href="#geng-gai-wen-jian-ming-cheng-shi-li" id="geng-gai-wen-jian-ming-cheng-shi-li"></a>

The sample code in this section shows how to modify the file name. The program will create a function to operate the file `rename_sample()`and export it to the msh command list. This function will call `rename()`the function to rename the file named text.txt to text1.txt. The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

static void rename_sample(void)
{
    rt_kprintf("%s => %s", "/text.txt", "/text1.txt");

    if (rename("/text.txt", "/text1.txt") < 0)
        rt_kprintf("[error!]\n");
    else
        rt_kprintf("[ok!]\n");
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(rename_sample, rename sample);copymistakeCopy Success
```

Run this example in the FinSH console, and the results are as follows:

```c
msh />echo "hello" text.txt
msh />ls
Directory /:
text.txt           5
msh />rename_sample
/text.txt => /text1.txt [ok!]
msh />ls
Directory /:
text1.txt           5copymistakeCopy Success
```

In the example display process, we first use the echo command to create a file named text.txt, and then run the sample code to change the file name of the text.txt file to text1.txt.

#### [Get file status example](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%8e%b7%e5%8f%96%e6%96%87%e4%bb%b6%e7%8a%b6%e6%80%81%e7%a4%ba%e4%be%8b) <a href="#huo-qu-wen-jian-zhuang-tai-shi-li" id="huo-qu-wen-jian-zhuang-tai-shi-li"></a>

The sample code in this section shows how to get the file status. The program will create a function to operate the file `stat_sample()`and export it to the msh command list. This function will call `stat()`the function to get the file size information of the text.txt file. The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

static void stat_sample(void)
{
    int ret;
     struct stat buf;
     ret = stat("/text.txt", &buf);
    if(ret == 0)
    rt_kprintf("text.txt file size = %d\n", buf.st_size);
    else
    rt_kprintf("text.txt file not fonud\n");
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(stat_sample, show text.txt stat sample);copymistakeCopy Success
```

Run this example in the FinSH console, and the results are as follows:

```c
msh />echo "hello" text.txt
msh />stat_sample
text.txt file size = 5copymistakeCopy Success
```

When the example is running, `echo`the command is used to create the file text.txt first, and then the example code is run to print out the file size information of the file text.txt.

#### [Create a directory example](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%88%9b%e5%bb%ba%e7%9b%ae%e5%bd%95%e7%a4%ba%e4%be%8b) <a href="#chuang-jian-mu-lu-shi-li" id="chuang-jian-mu-lu-shi-li"></a>

The sample code in this section shows how to create a directory. The program will create a function to operate files `mkdir_sample()`and export it to the msh command list. This function will call `mkdir()`the function to create a folder named dir\_test. The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

static void mkdir_sample(void)
{
    int ret;

    /* 创建目录 */
    ret = mkdir("/dir_test", 0x777);
    if (ret < 0)
    {
        /* 创建目录失败 */
        rt_kprintf("dir error!\n");
    }
    else
    {
        /* 创建目录成功 */
        rt_kprintf("mkdir ok!\n");
    }
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(mkdir_sample, mkdir sample);copymistakeCopy Success
```

Run this example in the FinSH console, and the results are as follows:

```c
msh />mkdir_sample
mkdir ok!
msh />ls
Directory /:
dir_test                 <DIR>    # <DIR> 表示该目录的类型是文件夹copymistakeCopy Success
```

This example demonstrates creating a folder named dir\_test in the root directory.

#### [Read directory example](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%af%bb%e5%8f%96%e7%9b%ae%e5%bd%95%e7%a4%ba%e4%be%8b) <a href="#du-qu-mu-lu-shi-li" id="du-qu-mu-lu-shi-li"></a>

The sample code in this section shows how to read a directory. The program will create a function to operate files `readdir_sample()`and export it to the msh command list. The function will call `readdir()`the function to obtain the content information of the dir\_test folder and print it out. The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

static void readdir_sample(void)
{
    DIR *dirp;
    struct dirent *d;

    /* 打开 / dir_test 目录 */
    dirp = opendir("/dir_test");
    if (dirp == RT_NULL)
    {
        rt_kprintf("open directory error!\n");
    }
    else
    {
        /* 读取目录 */
        while ((d = readdir(dirp)) != RT_NULL)
        {
            rt_kprintf("found %s\n", d->d_name);
        }

        /* 关闭目录 */
        closedir(dirp);
    }
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(readdir_sample, readdir sample);copymistakeCopy Success
```

Run this example in the FinSH console, and the results are as follows:

```c
msh />ls
Directory /:
dir_test                 <DIR>
msh />cd dir_test
msh /dir_test>echo "hello" hello.txt       # 创建一个 hello.txt 文件
msh /dir_test>cd ..                        # 切换到上级文件夹
msh />readdir_sample
found hello.txtcopymistakeCopy Success
```

In this example, we first enter the dir\_test folder to create the hello.txt file, and then exit the dir\_test folder. Now run the sample program to print out the contents of the dir\_test folder.

#### [Example of setting the read directory location](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e8%ae%be%e7%bd%ae%e8%af%bb%e5%8f%96%e7%9b%ae%e5%bd%95%e4%bd%8d%e7%bd%ae%e7%a4%ba%e4%be%8b) <a href="#she-zhi-du-qu-mu-lu-wei-zhi-shi-li" id="she-zhi-du-qu-mu-lu-wei-zhi-shi-li"></a>

The sample code in this section shows how to set the location of the next directory read. The program will create a function to operate the file `telldir_sample()`and export it to the msh command list. The function will first open the root directory, then read all the directory information under the root directory and print out the directory information. At the same time, `telldir()`the function is used to record the location information of the third directory item. Before reading the directory information under the root directory for the second time, `seekdir()`the function is used to set the reading position to the address of the third directory item previously recorded. At this time, the information under the root directory is read again and the directory information is printed out. The sample code is as follows:

```c
#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时，需要包含这个头文件 */

/* 假设文件操作是在一个线程中完成 */
static void telldir_sample(void)
{
    DIR *dirp;
    int save3 = 0;
    int cur;
    int i = 0;
    struct dirent *dp;

    /* 打开根目录 */
    rt_kprintf("the directory is:\n");
    dirp = opendir("/");

    for (dp = readdir(dirp); dp != RT_NULL; dp = readdir(dirp))
    {
        /* 保存第三个目录项的目录指针 */
        i++;
        if (i == 3)
            save3 = telldir(dirp);

        rt_kprintf("%s\n", dp->d_name);
    }

    /* 回到刚才保存的第三个目录项的目录指针 */
    seekdir(dirp, save3);

    /* 检查当前目录指针是否等于保存过的第三个目录项的指针. */
    cur = telldir(dirp);
    if (cur != save3)
    {
        rt_kprintf("seekdir (d, %ld); telldir (d) == %ld\n", save3, cur);
    }

    /* 从第三个目录项开始打印 */
    rt_kprintf("the result of tell_seek_dir is:\n");
    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
    {
         rt_kprintf("%s\n", dp->d_name);
    }

    /* 关闭目录 */
    closedir(dirp);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(telldir_sample, telldir sample);copymistakeCopy Success
```

In this demonstration, you need to manually `mkdir`create five folders from hello\_1 to hello\_5 in the root directory using the command to ensure that the root directory contains the folders required to run the example.

Run this example in the FinSH console, and the results are as follows:

```c
msh />ls
Directory /:
hello_1             <DIR>
hello_2             <DIR>
hello_3             <DIR>
hello_4             <DIR>
hello_5             <DIR>
msh />telldir_sample
the directory is:
hello_1
hello_2
hello_3
hello_4
hello_5
the result of tell_seek_dir is:
hello_3
hello_4
hello_5copymistakeCopy Success
```

After running the sample program, you can see that the first time the root directory information is read, it starts from the first folder and prints out all the directory information under the root directory. When the directory information is printed for the second time, the `seekdir()`function is used to set the starting position of the read to the position of the third folder. Therefore, when the root directory is read for the second time, it starts from the third folder to the last folder and only prints out the directory information from hello\_3 to hello\_5.

### [Frequently asked questions](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98) <a href="#chang-jian-wen-ti" id="chang-jian-wen-ti"></a>

#### [Q: What should I do if I find that the file name or folder name is displayed abnormally?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e5%8f%91%e7%8e%b0%e6%96%87%e4%bb%b6%e5%90%8d%e6%88%96%e8%80%85%e6%96%87%e4%bb%b6%e5%a4%b9%e5%90%8d%e7%a7%b0%e6%98%be%e7%a4%ba%e4%b8%8d%e6%ad%a3%e5%b8%b8%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#q-fa-xian-wen-jian-ming-huo-zhe-wen-jian-jia-ming-cheng-xian-shi-bu-zheng-chang-zen-me-ban" id="q-fa-xian-wen-jian-ming-huo-zhe-wen-jian-jia-ming-cheng-xian-shi-bu-zheng-chang-zen-me-ban"></a>

**A:** Check whether long file name support is enabled in the DFS function configuration section.

#### [Q: What should I do if the file system initialization fails?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e5%88%9d%e5%a7%8b%e5%8c%96%e5%a4%b1%e8%b4%a5%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#q-wen-jian-xi-tong-chu-shi-hua-shi-bai-zen-me-ban" id="q-wen-jian-xi-tong-chu-shi-hua-shi-bai-zen-me-ban"></a>

**A:** Check whether the types and number of file systems allowed to be mounted in the file system configuration items are sufficient.

#### [Q: What should I do if the mkfs command fails to create the file system?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e5%88%9b%e5%bb%ba%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f-mkfs-%e5%91%bd%e4%bb%a4%e5%a4%b1%e8%b4%a5%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#q-chuang-jian-wen-jian-xi-tong-mkfs-ming-ling-shi-bai-zen-me-ban" id="q-chuang-jian-wen-jian-xi-tong-mkfs-ming-ling-shi-bai-zen-me-ban"></a>

**A:** Check whether the storage device exists. If it exists, check whether the device driver can pass the functional test. If not, check the driver error. Check whether the libc function is enabled.

#### [Q: What should I do if the file system fails to mount?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e6%8c%82%e8%bd%bd%e5%a4%b1%e8%b4%a5%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#q-wen-jian-xi-tong-gua-zai-shi-bai-zen-me-ban" id="q-wen-jian-xi-tong-gua-zai-shi-bai-zen-me-ban"></a>

**A:**

* Check whether the specified mount path exists. The file system can be mounted directly to the root directory ("/"), but if you want to mount it to another path, such as ("/sdcard"), you need to ensure that the ("/sdcard") path exists, otherwise you need to create `sdcard`a folder in the root directory before mounting successfully.
* Check whether a file system has been created on the storage device. If no file system has been created on the storage device, you need to use `mkfs`the command to create a file system on the storage device.

#### [Q: What should I do if SFUD cannot detect the specific model of Flash used?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-sfud-%e6%8e%a2%e6%b5%8b%e4%b8%8d%e5%88%b0-flash-%e6%89%80%e4%bd%bf%e7%94%a8%e7%9a%84%e5%85%b7%e4%bd%93%e5%9e%8b%e5%8f%b7%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#qsfud-tan-ce-bu-dao-flash-suo-shi-yong-de-ju-ti-xing-hao-zen-me-ban" id="qsfud-tan-ce-bu-dao-flash-suo-shi-yong-de-ju-ti-xing-hao-zen-me-ban"></a>

**A:**

* Check whether the hardware pin settings are correct.
* Whether the SPI device has been registered.
* Whether the SPI device has been mounted on the bus.
* Check whether the and configuration items `RT-Thread Components → Device Drivers -> Using SPI Bus/Device device drivers -> Using Serial Flash Universal Driver`under the menu are selected. If not, you need to enable these two options.`Using auto probe flash JEDEC SFDP parameterUsing defined supported flash chip information table`
* If the storage device is still not recognized after enabling the above options, you can file an issue in the [SFUD](https://github.com/armink/SFUD) project.

#### [Q: Why does the benchmark test of storage devices take too long?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e5%ad%98%e5%82%a8%e8%ae%be%e5%a4%87%e7%9a%84-benchmark-%e6%b5%8b%e8%af%95%e8%80%97%e6%97%b6%e8%bf%87%e9%95%bf%e6%98%af%e6%80%8e%e4%b9%88%e5%9b%9e%e4%ba%8b%ef%bc%9f) <a href="#q-cun-chu-she-bei-de-benchmark-ce-shi-hao-shi-guo-chang-shi-zen-me-hui-shi" id="q-cun-chu-she-bei-de-benchmark-ce-shi-hao-shi-guo-chang-shi-zen-me-hui-shi"></a>

**A:**

* You can compare [the benchmark test data](https://github.com/armink/SFUD/blob/master/docs/zh/benchmark.txt)`system tick` when is 1000 and the time required for this test. If the time difference is too large, it can be considered that the test work is not running normally.
* Check the system tick settings, because some delay operations are determined by the tick time, so you need to set a suitable `system tick`value according to the system situation. If the system `system tick`value is not less than 1000, you need to use a logic analyzer to check the waveform to confirm that the communication rate is normal.

#### [Q: When implementing the elmfat file system in SPI Flash, how can we reserve some sectors that are not used by the file system?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-spi-flash-%e5%ae%9e%e7%8e%b0-elmfat-%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%ef%bc%8c%e5%a6%82%e4%bd%95%e4%bf%9d%e7%95%99%e9%83%a8%e5%88%86%e6%89%87%e5%8c%ba%e4%b8%8d%e8%a2%ab%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e4%bd%bf%e7%94%a8%ef%bc%9f) <a href="#qspiflash-shi-xian-elmfat-wen-jian-xi-tong-ru-he-bao-liu-bu-fen-shan-qu-bu-bei-wen-jian-xi-tong-shi" id="qspiflash-shi-xian-elmfat-wen-jian-xi-tong-ru-he-bao-liu-bu-fen-shan-qu-bu-bei-wen-jian-xi-tong-shi"></a>

**A: You can use the** [partition](https://github.com/RT-Thread-packages/partition) tool package provided by RT-Thread to create multiple block devices for the entire storage device, and assign different functions to the created multiple block devices.

#### [Q: What should I do if the program gets stuck while testing the file system?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e8%bf%87%e7%a8%8b%e4%b8%ad%e7%a8%8b%e5%ba%8f%e5%8d%a1%e4%bd%8f%e4%ba%86%e6%80%8e%e4%b9%88%e5%8a%9e%ef%bc%9f) <a href="#q-ce-shi-wen-jian-xi-tong-guo-cheng-zhong-cheng-xu-ka-zhu-le-zen-me-ban" id="q-ce-shi-wen-jian-xi-tong-guo-cheng-zhong-cheng-xu-ka-zhu-le-zen-me-ban"></a>

**A:** Try to use a debugger or print some necessary debugging information to determine where the program is stuck before asking the question.

#### [Q: How to check file system problems step by step?](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/filesystem/filesystem?id=q-%e5%a6%82%e4%bd%95%e4%b8%80%e6%ad%a5%e6%ad%a5%e6%a3%80%e6%9f%a5%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e5%87%ba%e7%8e%b0%e7%9a%84%e9%97%ae%e9%a2%98%ef%bc%9f) <a href="#q-ru-he-yi-bu-bu-jian-cha-wen-jian-xi-tong-chu-xian-de-wen-ti" id="q-ru-he-yi-bu-bu-jian-cha-wen-jian-xi-tong-chu-xian-de-wen-ti"></a>

**A:**

* You can use a bottom-up approach to gradually troubleshoot the problem.
* First, check whether the storage device is successfully registered and functions normally.
* Check whether a file system has been created on the storage device.
* Checks whether the specified file system type is registered with the DFS framework, and always checks whether the allowed file system types and number are sufficient.
* Check whether DFS is initialized successfully. This step of initialization is purely software-based, so the possibility of error is low. It should be noted that if automatic component initialization is enabled, there is no need to manually initialize it again.
