File System Basic Concepts#
This section introduces important architectural aspects of Micrium OS File System and defines the terminology that will be used throughout the rest of the documentation. Although most of the terms and concepts presented here are widely used in the literature in general, their exact meaning and usage are specific to Micrium OS File System. So even if you are familiar with file systems, we suggest you at least skim through the following content before you jump to the programming guide and start actual coding.
Figure - File System Top-Level Architecture in the File System Basic Concepts page shows a schematic view of the file system's main sub-modules and objects, as well as their relation to the application. Micrium OS File System consists of two main sub-modules: core and storage.
The core sub-module has two parts: The first is a virtual file system (VFS), which is responsible for providing the application with a uniform (i.e., file system driver-agnostic) interface to file, directory, volume and working directory manipulation. The second is a set of file system drivers which are responsible for maintaining consistent on-disk metadata according to specific (and most often standardized) layouts (e.g., FAT32).
The storage sub-module is also divided into two parts: The first is a generic storage layer, which is responsible for providing the application (and the core) with a uniform (i.e., media-agnostic) interface to block device and media manipulation. The second is a set of storage drivers, which are responsible for emulating the behavior of a block device when needed (this is the case of the NOR and NAND flash memories), and implementing the specifics of performing media I/O.
Figure - File System Top-Level Architecture#
The application can interact with specific file system objects (files, directories, block devices, etc) through the use of object handles. Object handles are obtained through dedicated open() functions and released through corresponding close() functions. A file handle, for instance, is obtained through a call to FSFile_Open() and is released through a call to FSFile_Close(). Similarly, a block device handle is obtained through a call to FSBlkDev_Open() and is released through a call to FSBlkDev_Close(). The media object is slightly different in that it is instantiated internally by the storage sub-module itself. A media handle can be retrieved in a few different ways, as explained in Media .
After an object is closed, the corresponding handle cannot be reused. An error is returned whenever the application attempts to reuse an old handle, which effectively prevents any unwanted access to a stale object.
File System Objects#
Although it is not necessary to understand the details of Micrium OS FS internal implementation to use it, it is nonetheless useful to have at least a schematic mental representation of how common file system concepts such as files, directories, volumes are represented internally. This section describes the main Micrium OS FS objects and their relation to the on-disk file system concepts.
File and Directory Nodes#
File and directory nodes are the in-RAM representation of on-disk files and directories. They basically serve as small distributed caches for on-disk metadata such as content start position, file size and other file and directory attributes. A single instance of a node exists for each opened file or directory (no matter how many times the file or directory is opened). A node is created when a file or directory is opened for the first time and destroyed when the last associated descriptor is destroyed.
File and Directory Descriptors#
Unlike file and directory nodes, file and directory descriptors do not have corresponding on-disk data structures. This is because nodes represent the state of actual on-disk entries, whereas descriptors represent the state of read and write operations on those entries. Each time a file or directory is opened, a new descriptor is created, and a handle to this descriptor is returned. This handle can then be used to perform various read and write operations. The same file or directory can be opened many times, returning as many handles to the application. Since each descriptor carries its own internal operation state, many "threads" of read and write operations may be performed concurrently without interfering with each other.
Working directory objects are lightweight objects containing an on-disk directory position. They can be used as the first argument of many file-level APIs to specify the base location from where a new file or directory can be referenced.
Volume objects are the in-RAM representation of on-disk partitions. In contrast to files and directories, a volume can be opened only once (using FSVol_Open()). Upon opening, the newly created volume is given a name, which can be later used as part of an entry path.
Relation Between Core Object Hierarchy and On-disk Layout#
Consider the file system on-disk layout shown in Figure - Example of a File System On-Disk Layout in the File System Basic Concepts page. There are two partitions (possibly formatted using a different file system), each containing its own file and directory tree. Now consider the object hierarchy shown in Figure - Example of a File System Core Object Hierarchy in the File System Basic Concepts page, which is created after performing the following operations:
Open (mount) partition 1 as "vol1"
Open (mount) partition 2 as "vol2"
Open "data" directory
Open "archive" as a working directory
Open "sys.log" file
Open "sys_00.log" file
Open "sys.log" file again
You can see that the directory "log", the file "user.db" and the file "sys_01.log", which are present on-disk, do not have corresponding in-RAM file or directory nodes. They have not been opened. All other files and directories have nodes in-RAM. Also, you can notice that the "sys.log" file has been opened twice resulting in two different file descriptors being created and two distinct file handles being returned to the application.
Figure - Example of a File System On-Disk Layout#
Figure - Example of a File System Core Object Hierarchy#
Block device objects represent storage devices whose smallest addressable unit is a block of a fixed and uniform size (typically 512, 1024, 2048 or 4096 bytes). Physical media may or may not exhibit such a property. For instance, NAND flash memories are not typically made of continuous blocks of uniform size that can be addressed individually: a special translation layer (called flash translation layer (FTL)) must be used in order to make the NAND flash appear like a block device to the upper layer (either the file system core or the application).
A block device is opened on top of an existing media and can be opened only once. A block device cannot exist without its underlying media, but a media may be used on its own, without a corresponding block device being opened on it.
Media objects represent physical media. A media can be categorized according to two distinct criteria: its persistence and its ability to be disconnected and reconnected. Following these criteria a media can be:
Persistent and fixed (or non-removable): the media's existence begins as soon as the storage initialization ends, and it cannot be disconnected.
Persistent and removable: the media's existence begins as soon as the storage initialization ends, and it can be disconnected and reconnected anytime.
Non-persistent (and thus removable): the media can appear and vanish anytime.
Table - Possible media states per media type#
persistent / fixed
persistent / fixed
persistent / fixed
persistent / fixed
persistent / removable
SCSI logical unit (USB MSC device)
non-persistent / removable
Unlike other file system objects, media are not opened explicitly, but rather instantiated internally by the storage sub-module. Since there are no such functions as FSMedia_Open() and FSMedia_Close(), media handles cannot be retrieved in the same way as the other file system object handles. Instead, media handles are retrieved using FSMedia_Get(), which takes the media name as its unique parameter and returns the corresponding media handle. The media name is statically assigned to a given media in the BSP_OS_Init() for NAND, NOR and SD when using the memory controller register macros (refer to Table - Memory Controller Register Macros in the File System Memory Controller Registration to the Platform Manager page for more details about the macros). For RAM disks, the media name is assigned by the application when calling FS_RAM_Disk_Add(). For SCSI, a name is internally assigned to each newly connected SCSI device (refer to section Automatic Media Naming for more details).