1. 程式人生 > 其它 >AliOS Things之romfs技術介紹

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的檔案和目錄結構如下:

截圖2020-12-11 20.19.51.png

通過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檔案。

總結,其工作原理和基本流程如下:

  1. 使用者準備好需要打包的目錄,該目錄下可以包含檔案和子目錄。
  2. 通過配套的mkromfs.py工具,將打包目錄中的資料,轉換成C語言程式碼,並將該程式碼加入romfs元件編譯。

注意:目前mkromfs打包功能已整合到編譯流程,即編譯過程中會自動打包,不需要手動處理了,而只需要在編譯前把需要打包的問題拷貝到components/fs/romfs/rootfs目錄下。

  1. 使用者(一般是檔案系統模組,而終端使用者是通過posix介面訪問romfs的)通過romfs_root變數訪問根目錄。
  2. 通過根目錄中記錄的entry資訊,逐步展開romfs目錄樹,可以依此訪問根目錄及其子目錄下的檔案資料

3、romfs檔案訪問

romfs檔案系統,會在系統初始化階段註冊到VFS虛擬檔案系統(掛載路徑為/)。應用層無需關注上一章節中介紹的資料結構,而是通過標準的posix介面訪問romfs中的目錄和檔案。

下圖展示了romfs檔案註冊和訪問的基本流程。

截圖2020-12-11 21.13.19.png

以下示例展示如何基於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/