了解更多开源请访问:开源基础软件社区https://ost.51cto.com前言littlefs原理分析5篇,包括:littlefs提交机制的整体存储结构fetch操作目录操作文件读写操作,块分配算法也会介绍。littlefs有以下几种防止磨损的措施:写入时进行坏块检测和写入恢复。均匀分配块:由块分配算法实现。定期重新分配元数据所在的块。1、写入过程中的坏块检测和写入恢复在littlefs中,写入文件、目录元数据等时,会调用函数lfs_bd_flush,最终将数据写入磁盘。lfs_bd_flush函数写完后,会将写入内存的数据与磁盘上的数据进行比较。如果数据不一致,则可能是坏块。方法如下:写入时通过回读磁盘数据进行校验,检测坏块。检测到坏块后,清除坏块,重新分配块,然后重写。lfs_bd_flush函数检查数据是否一致的分析如下://缓存中的数据回写磁盘时,检测坏块lfs_bd_flush(lfs_t*lfs,|lfs_cache_t*pcache,lfs_cache_t*rcache,布尔验证)|...||//调用lfs_bd_cmp比较磁盘上的数据和写入的数据是否一致|//如果它们不同,你可能遇到了坏块|->if(validate){|lfs_bd_cmp(lfs,|NULL,rcache,diff,|pcache->block,pcache->off,pcache->buffer,diff);|}||->...比如往文件写数据,在函数lfs_file_flush中,当检测到坏块时,会重新分配块,然后进行Write操作:lfs_file_flush(lfs_t*lfs,lfs_file_t*file)|->...||->while(true){|//调用lfs_bd_flush写入数据,比较数据是否写入正确|interr=lfs_bd_flush(lfs,&file->cache,&lfs->rcache,true);|如果(错误){|//如果检测到坏块则跳转重定位|如果(错误==LFS_ERR_CORRUPT){|转到搬迁;|}|返回错误;|}|打破;||搬迁:|//重新定位块并再次写入|LFS_DEBUG("坏块在0x%"PRIx32,file->block);|err=lfs_file_relocate(lfs,文件);|如果(错误){|返回错误;|}|}2。块分配(一)lookaheadbufferlittlefs使用lookaheadbuffer来管理和分配块。前瞻缓冲区是一个固定大小的位图,它记录有关区域中块分配的信息。lookaheadbuffer的例子如下,假设总共有64个block,lookaheadbuffer的大小为8,lookaheadbuffer对应的block分别分配了文件A、D和目录B、C:相关的前瞻缓冲区的数据结构如下:structlfs_free{lfs_block_toff;//lookaheadlfs_block_tsize中所有block的整体偏移量;//lookahead中的块总数lfs_block_ti;//lookahead_size中的索引表示当前块lfs_block_tack;//所有剩余的空闲块Numberuint32_t*buffer;//lookahead的位图块管理缓冲区}free;(2)查找已分配块先行缓冲区只记录了一个区域的块分配信息,当需要知道其他区域的块分配情况时,可以通过扫描文件系统来查找已分配的块。如果先行缓冲区中没有空闲块,则需要移动先行缓冲区以寻找文件系统中的其他空闲块。扫描查找已分配块的过程如下:将先行缓冲区位置移动一个lookahead_size,并将先行缓冲区清零。从超级块开始遍历文件系统中的所有目录和文件,以遍历所有已分配的块。如果block位于lookaheadbuffer管理的区域,则将lookaheadbuffer中的相应位设置为1。lookaheadbuffer只使用固定大小的位图来存储分配块的信息,这是一个trade-off在littlefs.虽然比较费时,但是有效的节省了RAM空间资源。代码分析如下:lfs_alloc(lfs_t*lfs,lfs_block_t*block)|...||//当先行缓冲区中没有空闲块时,需要扫描||//1.移动前瞻缓冲区|->lfs->free.off=(lfs->free.off+lfs->free.size)|%lfs->cfg->block_count;|lfs->free.size=lfs_min(8*lfs->cfg->lookahead_size,lfs->free.ack);|lfs->free.i=0;||//2.将先行缓冲区清除为0|->memset(lfs->free.buffer,0,lfs->cfg->lookahead_size);||//3.遍历文件系统进行扫描搜索|->lfs_fs_rawtraverse(lfs,lfs_alloc_lookahead,lfs,true);||->...其中,lfs_fs_rawtraverse函数会从superblock开始遍历整个文件系统,对于整个文件系统中所有分配的块调用回调函数lfs_alloc_lookahead。lfs_alloc_lookahead函数分析如下://lfs_fs_rawtraverse函数传递给lfs_alloc_lookahead函数的参数//是lfs结构体指针p和块号blocklfs_alloc_lookahead(void*p,lfs_block_tblock)|->lfs_t*lfs=(lfs_t*)p;||//获取块号相对于先行缓冲区的偏移量|->lfs_block_toff=((block-lfs->free.off)|+lfs->cfg->block_count)%lfs->cfg->block_count;||//如果块在前瞻缓冲区管理的范围内,|//设置位图的相应位,表示该块已经分配|->if(off
