Embedded Systems Panorama 5: Practical File System and Storage Management

In embedded Linux systems, storage and file systems are the core links for data interaction between the kernel and user space. Whether it is an SD card, NAND/NOR Flash, or eMMC, understanding the Linux storage subsystem, driver mechanisms, and file system management not only helps ensure stable system operation but also enhances performance and reduces boot latency. This article will comprehensively analyze embedded Linux storage management practices from Overview of Embedded Storage, Block Devices and Driver Mechanisms, File System Types and Selection, Mounting and Rootfs Construction, Performance Tuning Practices to Debugging Techniques.

1. Overview of Embedded Storage Systems

The storage architecture of embedded devices typically includes:

  1. On-chip Memory: such as SRAM and ROM, which have small capacity and fast speed

  2. External Flash: such as NAND/NOR, used for storing code and data

  3. Block Storage Devices: SD cards, eMMC, SSDs, etc.

  4. Memory File System (tmpfs): RAM disk for temporary data

The Linux kernel abstracts storage devices through the block device layer and provides a unified access interface through the file system, enabling data management from hardware to user space.

1. Differences Between Block Devices and Character Devices

Feature Character Device Block Device
Access Method Byte Stream Blocks (sector)
Typical Devices UART, GPIO SD card, eMMC, NAND
Data Caching Minimal Kernel Page Cache
File System Dependency None Must mount a file system

Storage access in embedded systems is almost entirely through the block device interface, so understanding the block device layer is a prerequisite for file system management.

2. Block Device Driver Mechanisms

Block device drivers are the core of interaction between the kernel and storage hardware. Common driver types used in embedded platforms include:

1. Structure of Block Device Drivers

Each block device driver mainly includes:

  • Request Queue: The kernel manages I/O requests through the queue

  • Low-level Operation Functions (block_device_operations): Implementing read/write/ioctl interfaces

  • Device Registration: Calling <span>register_blkdev()</span> to register the device number

Example:

static struct block_device_operations mybdev_fops = {
    .owner = THIS_MODULE,
    .open = mybdev_open,
    .release = mybdev_release,
    .ioctl = mybdev_ioctl,
};

static int __init mybdev_init(void) {
    major = register_blkdev(0, "myblock");
    mybdev_queue = blk_init_queue(mybdev_request, &mybdev_lock);
    return 0;
}

2. Request Handling

The driver receives kernel I/O requests through the request queue:

static void mybdev_request(struct request_queue *q) {
    struct request *req;
    while ((req = blk_fetch_request(q)) != NULL) {
        // Perform read/write operations
        blk_end_request_all(req, 0);
    }
}

In embedded systems, properly configuring queue length and I/O scheduling strategies can significantly enhance storage performance.

3. Embedded Flash Drivers

1. NAND Flash Driver

NAND Flash requires the use of the MTD (Memory Technology Device) Subsystem. Key steps include:

  • Registering the MTD device

  • Providing read/write/erase operations

  • Configuring ECC (Error Correction Code) mechanisms

Example:

static struct mtd_info my_nand = {
    .name = "my_nand",
    .size = 128 * 1024 * 1024,
    .erasesize = 128 * 1024,
    .writesize = 2048,
    .read = my_nand_read,
    .write = my_nand_write,
    .erase = my_nand_erase,
};

2. NOR Flash Driver

  • Mapping register space through <span>map_flash</span>

  • Typically used for storing code, supporting XIP (execute-in-place)

  • Can be used with MTD or directly mount a file system

4. File System Types and Selection

Common file systems used in embedded systems include:

File System Features Applicable Scenarios
ext4 Journaled file system, mature and stable SD cards, eMMC
UBIFS Designed for NAND, supports wear-leveling NAND Flash
JFFS2 Older NAND, average performance Small capacity NAND
tmpfs RAM disk, fast Temporary data, cache
VFAT Cross-platform compatibility External SD cards

1. File System Mounting Methods

mount -t ext4 /dev/mmcblk0p2 /mnt/rootfs
  • <span>-t</span> specifies the file system type

  • <span>root=</span> kernel parameter specifies the rootfs device

2. Rootfs Construction

Common methods include:

  1. Buildroot / Yocto Build: Automatically generates rootfs

  2. Manual Creation: Copying BusyBox tools and necessary directories

  3. Compressed Images: Using initramfs or squashfs to reduce storage usage

5. Storage Performance Tuning

Embedded systems are sensitive to storage performance, and tuning strategies include:

  1. Block Device Layer Optimization

  • Adjusting I/O scheduling strategies: <span>noop</span>, <span>deadline</span>, <span>cfq</span>

  • Adjusting request queue length

  • File System Layer Optimization

    • Disabling unnecessary logging (ext4 mount parameter <span>data=writeback</span>)

    • Using appropriate mount options: <span>noatime</span>, <span>nodiratime</span>

    • Using UBIFS instead of JFFS2 for NAND to improve write performance

  • Boot Acceleration

    • Using initramfs to cache the root file system

    • Delaying the loading of non-critical services

    • Simplifying file system content to reduce mount time

    Example mount parameters:

    mount -t ext4 -o noatime,nodiratime,data=writeback /dev/mmcblk0p2 /mnt/rootfs
    

    6. Debugging and Practical Techniques

    1. Driver Debugging

    • Using <span>dmesg</span> to view MTD or block device initialization logs

    • Early printk outputs NAND/SD initialization status

    • Using <span>cat /proc/mounts</span> and <span>df -h</span> to check mount status

    2. Storage Performance Analysis

    • <span>iostat</span> and <span>blktrace</span> to analyze I/O performance

    • <span>ftrace</span> to trace kernel block layer scheduling

    • NAND Flash can be tested for erase/write speed and ECC status using <span>nandtest</span>

    3. Rootfs Construction and Compression

    • Using <span>initramfs</span> or <span>squashfs</span> to compress the file system and improve loading speed

    • Using BusyBox to build a minimal command set to save storage space

    • Using partition alignment on SD cards or eMMC to improve access efficiency

    7. Embedded Storage Case Studies

    1. SD Card Boot

    • Bootloader initializes the SD card controller

    • The kernel mounts ext4 Rootfs

    • Optimized mount parameters: <span>noatime,data=writeback</span>

    • Testing boot speed and I/O performance to ensure stability

    2. NAND Flash System

    • Using UBIFS file system

    • Hardware or software ECC verification

    • Using compressed images for root file system mounting

    • Regular garbage collection to extend NAND lifespan

    3. eMMC High-Performance Applications

    • Using ext4 or f2fs file systems

    • Aligning partitions to erase block sizes to improve performance

    • Using DMA to enhance I/O bandwidth

    • Adjusting I/O scheduling strategies to ensure responsiveness under multitasking

    8. Conclusion

    This article systematically introduces embedded Linux file systems and storage management practices:

    • Storage architecture and block device abstraction

    • MTD, NAND, NOR driver mechanisms

    • File system types, mounting methods, and Rootfs construction

    • Storage performance tuning strategies and debugging techniques

    • Practical case studies covering common platforms like SD cards, NAND, and eMMC

    Through this article, developers can establish a comprehensive understanding of embedded system storage management, laying a solid foundation for system stability, boot optimization, and performance enhancement.

    #Embedded Panorama Series #Linux Kernel Architecture #Performance Tuning Practices

    Leave a Comment