鴻蒙的DFX子系統

做者:liangkz  更新時間:2021.05.05shell

咱們仍然是先對子系統的目錄結構作一次整理,作成表格,把模塊之間的調用關係理一下:app

鴻蒙的DFX子系統

鴻蒙的DFX子系統

1. Hi3861 平臺如上表,上電後在SystemInit階段會依次init:HiviewConfigInit、HiLogInit、hiview serviceiview

[system_init] HOS_SystemInit begin: %%%%%%%%%%%函數

[system_init] MODULE_INIT(core)============================ui

[hiview_config] CORE_INIT_PRI(HiviewConfigInit, 0);        this

[hiview_log] HiLogInit. CORE_INIT_PRI(HiLogInit, 0) url

[hiview_output_log] InitCoreLogOutput. call HiviewRegisterMsgHandlespa

 

[system_init] SYS_INIT(service)============================.net

[hiview_service] SYS_SERVICE_INIT(Init).debug

[samgr_lite] RegisterService(name: hiview)

[hiview_service] Init.InitHiviewComponent.

[hiview_file] InitHiviewFile

......

......

[hiview_service] Initialize.

咱們分別來看一下他們都作了些什麼事情:

A. HiviewConfigInit

位於:Hi3861/base/hiviewdfx/utils/lite/hiview_config.c

其主要是初始化全局變量g_hiviewConfig的配置,以下

鴻蒙的DFX子系統

  • hiviewInited:標記hiview service是否已經完成初始化。hiview service完成初始化以後將其置爲TRUE,

     「The communication of task can be use after the service is running.」,包括了相關的Message Handle纔可用。

  • outputOption:標記Control log output mode. default to OUTPUT_OPTION_FLOW. 
typedef enum { //不通過buffer,直接在終端上實時打印log,Debug版本建議用這個 OUTPUT_OPTION_DEBUG = 0, /* Output to the UART without buffer. Commercial versions are forbidden. */ //不會實時打印log,先保存到buffer裏,知足條件時纔會經過SAMGR發消息一次性打印一條或多條log到終端上 OUTPUT_OPTION_FLOW, /* Output to UART via SAMGR */ //不會實時打印log,先保存到buffer裏,知足條件時纔會經過SAMGR發消息將buffer的log寫入TextFile OUTPUT_OPTION_TEXT_FILE, /* Output to Text File: 「/user/log/debug.log」, see ‘HIVIEW_FILE_PATH_LOG’ */ //不會實時打印log,先保存到buffer裏,知足條件時纔會經過SAMGR發消息將buffer的log寫入BinFile OUTPUT_OPTION_BIN_FILE, OUTPUT_OPTION_MAX } HiviewOutputOption;
  • level:標記Control log output level. Default to HILOG_LV_DEBUG. 

低於此標記級別的log不會打印出來(?),仍是不會被記錄到TEXT_FILE/BIN_FILE裏(??)

#define HILOG_LV_INVALID 0 #define HILOG_LV_DEBUG 1 #define HILOG_LV_INFO 2 #define HILOG_LV_WARN 3 #define HILOG_LV_ERROR 4 #define HILOG_LV_FATAL 5 #define HILOG_LV_MAX 6

B. HiLogInit

位於:Hi3861/base/hiviewdfx/frameworks/hilog_lite/mini/hiview_log.c

鴻蒙的DFX子系統

  •  InitCoreLogOutput();

鴻蒙的DFX子系統

先去初始化全局變量HiviewCache  g_logCache

typedef struct { HiviewMutexId_t mutex; uint16 wCursor; // 0-65535 uint16 usedSize; // 0-65535,buffer已經使用掉的size uint16 size; // cache size 0-65535,由LOG_STATIC_CACHE_SIZE指定,1024 Byte HiviewCacheType type; uint8 *buffer; // Circular buffer,由g_logCacheBuffer 指定的空間,1024 Byte  } HiviewCache;

而全局變量 HiviewFile  g_logFile,這是在上面將outputOption標記設置爲 OUTPUT_OPTION_TEXT_FILE/BIN_FILE 時用得上的配置,

如輸出TextFile時,文件會生成在「user/log/debug.log」。

 

接下來是註冊三個MsgHandle,用於處理知足條件時,將g_logCache/g_logCacheBuffer 中的log寫入文件 或者經過Uart在默認終端上打印出來。這中間還有一個從新格式化log的處理,如:

HILOG_INFO(HILOG_MODULE_SAMGR, "Initialized all system and application services!"); 

這條log會處理成:

00 00:00:00 0 220 I 1/SAMGR: Initialized all system and application services!

前面新增一串字符分別表明着:開機以來的天數+時:分:秒+0+task+logLevel+module+moduleName.

task這個看起來並非打印這個log的任務的TaskID,貌似是能夠自行修改的,待驗證。

logLevel 就是:

static char g_logLevelInfo[HILOG_LV_MAX] = { 'N', // "NONE" 'D', // "DEBUG" 'I', // "INFO" 'W', // "WARN" 'E', // "ERROR" 'F' // "FATAL" };

module就是枚舉HiLogModuleType定義的數字,這裏的1就是 HILOG_MODULE_SAMGR 的值。

moduleName就是module對應的字符名字,見下面經過HiLogRegisterModule()註冊的module參數。

  • HiLogRegisterModule()

註冊log的模塊,按照官方文檔的「Hilog_lite開發指導」中的例子進行配置便可。

  • HiviewRegisterInitFunc()

註冊InitLogOutput()是爲了在hiview service init時建立和初始化log輸出的TextFile/BinFile等文件的相關信息,outputOption == OUTPUT_OPTION_DEBUG/OUTPUT_OPTION_FLOW 是不須要建立文件的。

 

註冊InitLogLimit()是爲了在hiview service init時給log的打印設置一些限制條件:

    SetLimitThreshold(HILOG_MODULE_HIVIEW, LOG_LIMIT_LEVEL3);

    SetLimitThreshold(HILOG_MODULE_APP, LOG_LIMIT_LEVEL2);

過於頻繁地打印log,有可能會致使log的丟失。

 

C. hiview service

位於:Hi3861/base/hiviewdfx/services/hiview_lite/hiview_service.c

鴻蒙的DFX子系統

先是向SAMGR註冊了g_hiviewService以及FeatureApi,而後經過InitHiviewComponent()去依次執行 g_hiviewInitFuncList[ ] 中的 InitLogOutput()和InitLogLimit()作相關的配置。

 

注意,這裏僅僅是向SAMGR註冊服務和註冊MsgHandle API而已,還須要等到後面SAMGR把各類資源環境配置好後,纔會調用g_hiviewService.Initialize()去初始化和拉起hiview service,提供log方面的相關服務。

 

2. 在接下來的系統啓動過程、系統運行過程、應用運行過程當中,只要有調用上表C的聲明中 log.h/hiview_log.h頭文件定義的宏,來打印log,就都會跑到下面所分析的流程中去。

 

hiview_log.h 定義了:一些宏、枚舉、輔助函數和

/* * Interface for printing basic logs. Use the macro definition interface instead of directly using this interface. * @param module Module ID. * @param level Log Level. * @param nums Parameters automatically generated by macro. * @param fmt Format string. * @attention Do not use this interface directly, you should use the HILOG_XXX interface. */ void HiLogPrintf(uint8 module, uint8 level, const char *nums, const char *fmt, ...) __attribute__((format(printf, 4, 5))); #define HILOG_DEBUG(mod, fmt, ...) HiLogPrintf(mod, HILOG_LV_DEBUG, FUN_ARG_NUM(__VA_ARGS__), fmt, ##__VA_ARGS__) #define HILOG_INFO(mod, fmt, ...) HiLogPrintf(mod, HILOG_LV_INFO, FUN_ARG_NUM(__VA_ARGS__), fmt, ##__VA_ARGS__) #define HILOG_WARN(mod, fmt, ...) HiLogPrintf(mod, HILOG_LV_WARN, FUN_ARG_NUM(__VA_ARGS__), fmt, ##__VA_ARGS__) #define HILOG_ERROR(mod, fmt, ...) HiLogPrintf(mod, HILOG_LV_ERROR, FUN_ARG_NUM(__VA_ARGS__), fmt, ##__VA_ARGS__) #define HILOG_FATAL(mod, fmt, ...) HiLogPrintf(mod, HILOG_LV_FATAL, FUN_ARG_NUM(__VA_ARGS__), fmt, ##__VA_ARGS__)

系統建議不要直接使用HiLogPrintf()來打印log,而是使用下面的一組宏來分級別/類型來打印log。

鴻蒙的DFX子系統

HiLogPrintf() 的實如今:Hi3861/base/hiviewdfx/frameworks/hilog_lite/mini/hiview_log.c

通過一些判斷後,調用  Hi3861/base/hiviewdfx/frameworks/hilog_lite/mini/hiview_output_log.c

文件內的OutputLog():

鴻蒙的DFX子系統

Hi3861/base/hiviewdfx/services/hiview_lite/hiview_service.c

【這裏的MessageHandle()和Output()函數,若是進一步深刻去分析和理解,就會涉及到samgr_lite組件的一些東西了,這裏先不進一步細說。文末我把我作的兩張圖附上,你們能夠先自行理解一下。】

鴻蒙的DFX子系統

鴻蒙的DFX子系統

hiview service經過MessageHandle()調用以前InitCoreLogOutput()註冊的MsgHandle API來處理相關消息:

實時打印log、把log寫入TextFile或者寫入BinFile。

鴻蒙的DFX子系統

最上面表格中「D的實現」中關於hiview_cache.c、hiview_file.c、hiview_util.c等輔助函數的實現以及DFX系統外部提供的支持,就請各位本身去研究了。

 

Hi3516工程上的目錄結構,相比Hi3861的多了:

  • hilog.cpp  C++類對上面幾個宏的封裝;上層應用開發,有本身的JS/Java的相關類的封裝,請自行根據API參考文檔進行配置和調用。
  • hiview_applogcat.c  apphilogcat 服務進程,負責從日誌設備(dev/hilog)讀取數據,格式化輸出到終端,同時也寫入磁盤文件。
  • hiview_logcat.c  編譯成可執行程序hilogcat,看起來是能夠經過shell執行,傳入參數來動態調整log的打印,不過並不會寫入磁盤文件。

 

我沒有Hi3516平臺,暫沒法驗證。

 

附上兩張我在整理 HiviewService 時作的展開圖片:

鴻蒙的DFX子系統

鴻蒙的DFX子系統

做者:liangkz

想了解更多內容,請訪問51CTO和華爲合做共建的鴻蒙社區:https://harmonyos.51cto.com

相關文章
相關標籤/搜索