AliOS Things之romfs技術介紹
技術標籤:AliOS Things物聯網作業系統物聯網嵌入式實時作業系統HaaSAliOS Things
1、概述
romfs主要在Linux和一些類Unix系統上被使用,它具有體積小、可靠性好、效能高等特點,非常適合在構造最小核心階段使用。AliOS Things中也提供了romfs功能,主要用於只讀檔案系統、微核心階段最小系統等場景下。
romfs的主要特點和用途如下:
- 體積小,節省資源,可以在構造最小核心時使用。
- 只讀檔案系統,防止檔案內容被篡改。
- 檔案順序儲存,讀取效能高。
- 不需要寫入,操作簡單,可靠性高。
- 可以做到不依賴驅動,可被獨立載入。
2、romfs的資料儲存
AliOS Things中提供的romfs,將檔案、目錄等資料打包在只讀程式碼段中。因此,romfs檔案系統沒有獨立的映象,而是被包含在核心映象中。系統啟動後,使用者可以通過一個指定的資料結構訪問romfs檔案系統的資料。
mkromfs.py
工具是romfs的一個配套轉換工具,它可以將目錄樹資料轉換成一種C語言結構體(struct romfs_dirent
),使用者通過訪問該型別的結構體變數訪問檔案資料。
該結構體的定義如下:
struct romfs_dirent { uint32_t type; /* dirent type */ const char *name; /* dirent name */ const uint8_t *data; /* file date ptr */ size_t size; /* file size */ };
其中,type表明某個entry(每個entry對應一個檔案或目錄項)的型別、名稱、資料指標、資料大小等資訊。
entry指向的data和size根據type的不同而不同。
如檔案型別的entry,其data指標指向一個二進位制陣列,該陣列的內容就是檔案的二進位制內容,其size就是檔案的長度;
如果是目錄型別的entry,則其data指標指向一個struct romfs_dirent
結構體,即下一個目錄記錄,size則表示該目錄記錄中的成員個數,依此類推。
例如,需要打包成romfs的檔案和目錄結構如下:
通過mkromfs.py工具轉換後,生成的C語言檔案(components/fs/romfs/romfs.c)如下:
/* Generated by mkromfs. Edit with caution. */
#include "romfs_def.h"
static const uint8_t _romfs_root_README[] = {
0x48,0x65,0x6c,0x6c,0x6f,0x20,0x48,0x61,0x61,0x73,0x0a
};
static const uint8_t _romfs_root_bin_README[] = {
0x48,0x65,0x6c,0x6c,0x6f,0x77,0x6f,0x72,0x6c,0x64,0x0a
};
static const struct romfs_dirent _romfs_root_bin[] = {
{ROMFS_DIRENT_FILE, "README", (uint8_t *)_romfs_root_bin_README, sizeof(_romfs_root_bin_README)/sizeof(_romfs_root_bin_README[0])}
};
static const struct romfs_dirent _romfs_root[] = {
{ROMFS_DIRENT_FILE, "README", (uint8_t *)_romfs_root_README, sizeof(_romfs_root_README)/sizeof(_romfs_root_README[0])},
{ROMFS_DIRENT_DIR, "bin", (uint8_t *)_romfs_root_bin, sizeof(_romfs_root_bin)/sizeof(_romfs_root_bin[0])}
};
const struct romfs_dirent romfs_root = {
ROMFS_DIRENT_DIR, "/", (uint8_t *)_romfs_root, sizeof(_romfs_root)/sizeof(_romfs_root[0])
};
即:
(1)romfs的根目錄資訊記錄在一個名為romfs_root
的全域性變數中。該變數是一個struct romfs_dirent
型別的結構體變數,它記錄了根目錄的如下資料:型別(DIR)、名稱(“/”)、data指標(指向_romfs_root
變數)、資料大小。
(2)通過data指標,又可以繼續訪問根目錄下的成員(即bin目錄和REAMDE檔案)。根目錄下的成員,每個entry都是一個struct romfs_dirent
型別的結構體變數。
(3)通過_romfs_root中的第一個entry,可以訪問REAMDE檔案的資訊。該entry的data指標指向一個名為_romfs_root_REAMDE
的結構體變數,型別為檔案(FILE)。_romfs_root_REAMDE
中儲存了根目錄下README檔案的內容(即“Helloworld”字串的二進位制資料)。
(4)通過_romfs_root
的第二個entry,可以訪問bin目錄的資訊。該entry的data指標指向一個名為_romfs_root_bin
的結構體變數,型別為(DIR)。_romfs_root_bin
中儲存了bin目錄下的資料資訊。
(5)_romfs_root_bin
結構體包含一個entry,是FILE型別的資料,對應bin目錄下的README檔案。
總結,其工作原理和基本流程如下:
- 使用者準備好需要打包的目錄,該目錄下可以包含檔案和子目錄。
- 通過配套的
mkromfs.py
工具,將打包目錄中的資料,轉換成C語言程式碼,並將該程式碼加入romfs元件編譯。
注意:目前mkromfs打包功能已整合到編譯流程,即編譯過程中會自動打包,不需要手動處理了,而只需要在編譯前把需要打包的問題拷貝到components/fs/romfs/rootfs
目錄下。
- 使用者(一般是檔案系統模組,而終端使用者是通過posix介面訪問romfs的)通過
romfs_root
變數訪問根目錄。 - 通過根目錄中記錄的entry資訊,逐步展開romfs目錄樹,可以依此訪問根目錄及其子目錄下的檔案資料
3、romfs檔案訪問
romfs檔案系統,會在系統初始化階段註冊到VFS虛擬檔案系統(掛載路徑為/
)。應用層無需關注上一章節中介紹的資料結構,而是通過標準的posix介面訪問romfs中的目錄和檔案。
下圖展示了romfs檔案註冊和訪問的基本流程。
以下示例展示如何基於helloworld_demo新增訪問romfs的邏輯。
1、修改application/example/helloworld_demo/aos.mk檔案,新增romfs元件依賴。
diff --git a/application/example/helloworld_demo/aos.mk b/application/example/helloworld_demo/aos.mk
index 233896d..a5db41b 100644
--- a/application/example/helloworld_demo/aos.mk
+++ b/application/example/helloworld_demo/aos.mk
@@ -5,7 +5,7 @@ $(NAME)_VERSION := 1.0.1
$(NAME)_SUMMARY := helloworld demo
$(NAME)_SOURCES := maintask.c appdemo.c
-$(NAME)_COMPONENTS += osal_aos
+$(NAME)_COMPONENTS += osal_aos romfs
GLOBAL_DEFINES += AOS_NO_WIFI
2、修改application/example/helloworld_demo/appdemo.c檔案,新增romfs檔案測試邏輯,讀取romfs中/bin/README
檔案的內容。
diff --git a/application/example/helloworld_demo/appdemo.c b/application/example/helloworld_demo/appdemo.c
index 50b153e..7c9462b 100644
--- a/application/example/helloworld_demo/appdemo.c
+++ b/application/example/helloworld_demo/appdemo.c
@@ -8,6 +8,9 @@
#include "aos/init.h"
#include "board.h"
#include <k_api.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
int application_start(int argc, char *argv[])
{
@@ -18,6 +21,19 @@ int application_start(int argc, char *argv[])
//fd = board_lcd_create("name");
//board_lcd_write(fd,buffer,len);
+ int fd, ret;
+ const char *file = "/bin/README";
+ char fcontent[64] = {0};
+
+ fd = open(file, O_RDONLY);
+ if (fd >= 0) {
+ ret = read(fd, fcontent, sizeof(fcontent));
+ if (ret > 0) {
+ printf("Content read from file %s: %s\r\n", file, fcontent);
+ }
+ close(fd);
+ }
+
while(1) {
printf("hello world! count %d \r\n", count++);
3、編譯和燒錄韌體,系統執行後將會看到如下列印輸出:
Content read from file /bin/README: Helloworld
注意:romfs為只讀檔案系統,檔案不支援寫入。
4、總結
本文介紹了romfs的用途和特點,並重點說明了AliOS Things中romfs的資料儲存方式,以及應用層訪問romfs資料的方法。
想了解更多關於AliOS Things的知識,請加入我們的釘釘開發者群。
更多技術與解決方案介紹,請訪問阿里雲AIoT首頁https://iot.aliyun.com/