使用littlefs-fuse在PC端除錯littlefs檔案系統
背景
littlefs是arm面向嵌入式裝置推出的一款掉電安全的小型檔案系統,具有抗掉電,動態磨損均衡,RAM/ROM需求少等特點,具體介紹可見 https://github.com/ARMmbed/littlefs
作為一款在嵌入式裝置上使用的檔案系統,出問題時,一般是需要將資料dump出來進行分析的。此時就需要PC端的除錯工具了。
littlefs-fuse簡介
這個專案提供了一個littlefs的FUSE封裝,也就是你可以藉助此專案,在PC上直接將littlefs映象掛載起來,並正常進行一些檔案系統的操作。
原始碼位於:https://github.com/ARMmbed/littlefs-fuse
結構
我們直接下載下來
$ git clone https://github.com/ARMmbed/littlefs-fuse.git
$ cd littlefs-fuse
先看下結構
$ tree -L 2 . ├── lfs_fuse_bd.c ├── lfs_fuse_bd.h ├── lfs_fuse.c ├── LICENSE.md ├── littlefs │ ├── DESIGN.md │ ├── emubd │ ├── lfs.c │ ├── lfs.h │ ├── lfs_util.c │ ├── lfs_util.h │ ├── LICENSE.md │ ├── Makefile │ ├── README.md │ ├── scripts │ ├── SPEC.md │ └── tests ├── Makefile └── README.md
外層是封裝,裡面則直接包含了littlefs資料夾。當我們需要特定版本的littlefs,例如使用跟裝置上同一版本的littlefs時,只需要替換掉裡層的這個littlefs即可,非常方便。
編譯
根據README,專案依賴 FUSE version 2.6及以上的版本,可以使用如下命令檢視版本
fusermount -V
另外還需要安裝下 libfuse-dev:
sudo apt-get install libfuse-dev
依賴項滿足之後,直接make即可生成lfs應用程式
make
生成裝置並掛載使用
首先需要造一個塊裝置出來
sudo chmod a+rw /dev/loop0 # make loop device user accessible dd if=/dev/zero of=image bs=512 count=2048 # create a 1MB image losetup /dev/loop0 image # attach the loop device
我們上一步是dd生成了一個空的image,所以需要先格式化,
./lfs --format /dev/loop0
再掛載
mkdir -p mount
./lfs /dev/loop0 mount
掛載成功後,執行mount可以看到掛載情況
$ mount | grep lfs
/home/zhuangqiubin/debug_littlefs/littlefs-fuse/lfs on /home/zhuangqiubin/debug_littlefs/littlefs-fuse/mount type fuse.lfs (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
現在就可以在mount目錄下,隨意進行操作了,建立刪除讀出寫入,都會被轉換成littlefs的操作,最終作用到image上
過程中,可以隨時dump出資料,就可以看到你的操作,最終儲存到littlefs上時什麼樣的資料格式了,例如
$ echo "www.cnblogs.com/zqb-all/" >> mount/test_littlefs.txt
$ hexdump -C image
00000000 03 00 00 00 f0 0f ff f7 6c 69 74 74 6c 65 66 73 |........littlefs|
00000010 2f e0 00 10 00 00 02 00 00 02 00 00 00 08 00 00 |/...............|
00000020 ff 00 00 00 ff ff ff 7f fe 03 00 00 20 00 04 09 |............ ...|
00000030 74 65 73 74 5f 6c 69 74 74 6c 65 66 73 2e 74 78 |test_littlefs.tx|
00000040 74 20 00 00 11 70 0f f9 b7 ee c0 48 bb ff ff ff |t ...p.....H....|
00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000200 04 00 00 00 f0 0f ff f7 6c 69 74 74 6c 65 66 73 |........littlefs|
00000210 2f e0 00 10 00 00 02 00 00 02 00 00 00 08 00 00 |/...............|
00000220 ff 00 00 00 ff ff ff 7f fe 03 00 00 20 00 04 09 |............ ...|
00000230 74 65 73 74 5f 6c 69 74 74 6c 65 66 73 2e 74 78 |test_littlefs.tx|
00000240 74 20 00 00 08 77 77 77 2e 63 6e 62 6c 6f 67 73 |t ...www.cnblogs|
00000250 2e 63 6f 6d 2f 7a 71 62 2d 61 6c 6c 2f 0a 70 0f |.com/zqb-all/.p.|
00000260 f9 87 46 fe c1 ad ff ff ff ff ff ff ff ff ff ff |..F.............|
00000270 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100000
使用完畢之後,用以下命令解除安裝
umount mount
sudo losetup -d /dev/loop0
掛載一個指定映象
以上是生成了空的映象,格式化再掛載。如果要掛載一個現成的映象,步驟也是差不多的,只是映象換一下。假設現成的映象叫littlefs.img,則
sudo chmod a+rw /dev/loop0 # make loop device user accessible
losetup /dev/loop0 littlefs.img # attach the loop device
mkdir -p mount
./lfs /dev/loop0 mount
解除安裝命令沒有差別
umount mount
sudo losetup -d /dev/loop0
但從裝置上dump出的littlefs映象,其配置不一定會跟littlefs-fuse的預設配置匹配。
此時為了能正確掛載,以及準確地模擬littlefs在裝置上執行的情況,我們需要將配置改成一樣的。
解決方式一,直接修改原始碼,例如
diff --git a/lfs_fuse.c b/lfs_fuse.c
index 3c87dad..d1a99a2 100644
--- a/lfs_fuse.c
+++ b/lfs_fuse.c
@@ -26,7 +26,16 @@
// config and other state
-static struct lfs_config config = {0};
+/* static struct lfs_config config = {0}; */
+static struct lfs_config config = {
+ .read_size = 256,
+ .prog_size = 256,
+ .block_size = 4096,
+ .block_count = 1224,
+ .block_cycles = 512,
+ .cache_size = 256,
+ .lookahead_size = 32
+};
修改後重新make生成即可
解決方式二,在呼叫的時候,通過命令列引數指定,例如
./lfs --block_size=512 --format /dev/loop0
./lfs --block_size=512 /dev/loop0 mount
支援的選項,可以在help中找到
$lfs -h
usage: ./lfs [options] device mountpoint
general options:
-o opt,[opt...] FUSE options
-h --help print help
-V --version print version
littlefs options:
--format format instead of mounting
--migrate migrate previous version instead of mounting
-b --block_size logical block size, overrides the block device
--block_count block count, overrides the block device
--block_cycles number of erase cycles before eviction (512)
--read_size readable unit (block_size)
--prog_size programmable unit (block_size)
--cache_size size of caches (block_size)
--lookahead_size size of lookahead buffer (8192)
--name_max max size of file names (255)
--file_max max size of file contents (2147483647)
--attr_max max size of custom attributes (1022)
FUSE options:
-d -o debug enable debug output (implies -f)
-f foreground operation
-s disable multi-threaded operation
-o allow_other allow access to other users
-o allow_root allow access to root
-o auto_unmount auto unmount on process termination
-o nonempty allow mounts over non-empty file/dir
-o default_permissions enable permission checking by kernel
-o fsname=NAME set filesystem name
-o subtype=NAME set filesystem type
-o large_read issue large read requests (2.4 only)
-o max_read=N set maximum size of read requests
-o hard_remove immediate removal (don't hide files)
-o use_ino let filesystem set inode numbers
-o readdir_ino try to fill in d_ino in readdir
-o direct_io use direct I/O
-o kernel_cache cache files in kernel
-o [no]auto_cache enable caching based on modification times (off)
-o umask=M set file permissions (octal)
-o uid=N set file owner
-o gid=N set file group
-o entry_timeout=T cache timeout for names (1.0s)
-o negative_timeout=T cache timeout for deleted names (0.0s)
-o attr_timeout=T cache timeout for attributes (1.0s)
-o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)
-o noforget never forget cached inodes
-o remember=T remember cached inodes for T seconds (0s)
-o nopath don't supply path if not necessary
-o intr allow requests to be interrupted
-o intr_signal=NUM signal to send on interrupt (10)
-o modules=M1[:M2...] names of modules to push onto filesystem stack
-o max_write=N set maximum size of write requests
-o max_readahead=N set maximum readahead
-o max_background=N set number of maximum background requests
-o congestion_threshold=N set kernel's congestion threshold
-o async_read perform reads asynchronously (default)
-o sync_read perform reads synchronously
-o atomic_o_trunc enable atomic open+truncate support
-o big_writes enable larger than 4kB writes
-o no_remote_lock disable remote file locking
-o no_remote_flock disable remote file locking (BSD)
-o no_remote_posix_lock disable remove file locking (POSIX)
-o [no_]splice_write use splice to write to the fuse device
-o [no_]splice_move move data while splicing to the fuse device
-o [no_]splice_read use splice to read from the fuse device
Module options:
[iconv]
-o from_code=CHARSET original encoding of file names (default: UTF-8)
-o to_code=CHARSET new encoding of the file names (default: UTF-8)
[subdir]
-o subdir=DIR prepend this directory to all paths (mandatory)
-o [no]rellinks transform absolute symlinks to relative
除錯
既然可以在PC上模擬掛載和讀寫,那首先最直觀的,就是可以在littlefs的原始碼中按需新增除錯程式碼,再重新掛載dump出來的映象,通過列印來分析問題。
其次,必要的時候,我們還可以上gdb
make DEBUG=1 clean all # build with debug info
gdb --args ./lfs -d /dev/loop0 mount # run with gdb
本文地址:https://www.cnblogs.com/zqb-all/p/12078659.h