色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > 【嵌入式SD NAND】基于FATFS/Littlefs文件系統(tǒng)的日志框架實現(xiàn)

          【嵌入式SD NAND】基于FATFS/Littlefs文件系統(tǒng)的日志框架實現(xiàn)

          發(fā)布人:13537608950 時間:2024-03-13 來源:工程師 發(fā)布文章
          文章目錄

          【嵌入式】基于FATFS/Littlefs文件系統(tǒng)的日志框架實現(xiàn)

          1. 概述

          2. 設(shè)計概要

          3. 設(shè)計實現(xiàn)

          3.1 初始化 `init`

          3.2 日志寫入 `write`

          3.3 日志讀取 `read`

          3.4 注銷 `deinit`

          3.5 全部代碼匯總

          4. 測試

          5. 總結(jié)


          1. 概述

          那么在移植好了文件系統(tǒng)之后,我們又應(yīng)該如何應(yīng)用文件系統(tǒng)呢?


          很多人會說,這個簡單,就操作文件嘛!open、read、write、close不就行了嗎!當(dāng)然對于簡單的使用,掌握open、read、write、close,去存儲一兩個文件或者從一兩個文件中簡單的讀取下數(shù)據(jù)這確實沒有什么難度。但在實際應(yīng)用中,特別是產(chǎn)品開發(fā)過程中,往往不只是簡單的操作一兩個文件就可以的,如果真是這樣,那費那么大勁移植文件系統(tǒng)多少有點浪費!


          在實際項目開發(fā)中,往往需要依托文件系統(tǒng)操作諸多的文件,操作諸多的數(shù)據(jù)。如通過配置文件配置機(jī)器設(shè)備信息、通過升級文件進(jìn)行產(chǎn)品升級、通過存放字庫文件實現(xiàn)多語言支持等等,這些都是比較簡單的操作,讀寫不是很頻繁,相對來說實現(xiàn)比較簡單,還有一類需求讀寫會相當(dāng)頻繁,且大多數(shù)產(chǎn)品內(nèi)都希望存在的,那便是日志文件,通過日志文件來記錄設(shè)備的運行數(shù)據(jù)。日志文件不同于其他功能,其往往需要具備幾個基本特性需求:


          • 單個文件大小限制

          • 日志總大小空間占用限制

          • 自動循環(huán)覆蓋


          網(wǎng)上也有一些開源的日志框架,如 Log4j,不過大都是基于 java / c ++ 實現(xiàn)的,雖然功能比較全面,但比較繁雜,且也難以移植應(yīng)用于嵌入式開發(fā)中。而在嵌入式開發(fā)中,可能也受限于資源限制,并沒有發(fā)現(xiàn)不錯的基于文件系統(tǒng)的開源日志框架(至少博主目前沒有發(fā)現(xiàn),有的話歡迎大家評論區(qū)討論 ),對于如何實現(xiàn)一個日志框架很多人一下子可能沒有頭緒,綜上,本文將分享一個簡單的基于文件系統(tǒng)的日志程序以供大家思考。

          2. 設(shè)計概要

          我們需要實現(xiàn)的日志模塊的核心需求為:


          • 單個文件大小限制

          • 日志總大小空間占用限制

          • 自動循環(huán)覆蓋

          對于一個模塊,對外僅需提供其操作的接口即可,內(nèi)部的算法實現(xiàn)均無需對外開放,而對于此日志模塊,對外只需提供基本的以下四個接口即可:


          • 初始化 init

          • 寫日志 write

          • 讀日志 read

          • 注銷 deinit

          關(guān)于日志存儲的核心思想如下:


          寫數(shù)據(jù)之前先判斷當(dāng)前操作的文件是否超出單個文件大小限制,如超出大小限制則進(jìn)行日志輪轉(zhuǎn),創(chuàng)建一個新的日志文件并判斷日志文件總大小是否超出限制,如果超出則刪除最早的那一份日志文件


          關(guān)于日志存儲的詳細(xì)設(shè)計如下:


          日志文件格式采用:<filename>.log ,當(dāng)當(dāng)前文件達(dá)到單個文件大小之后,進(jìn)行文件輪轉(zhuǎn);


          假定當(dāng)前限制日志每個日志文件大小為2048Byte,最多存儲10個文件;


          當(dāng)當(dāng)前文件達(dá)到單個文件大小之后,迭代修改日志文件名:


          • <filename>.log -> <filename>.log.0

          • <filename>.log.0 -> <filename>.log.1

          • <filename>.log.1 -> <filename>.log.2

          • <filename>.log.8 -> <filename>.log.9

          • 刪除 <filename>.log.9

          ps:注意實際代碼操作的時候,文件修改順序是反過來的,也就是先 刪除 <filename>.log.9 再將<filename>.log.8 -> <filename>.log.9

          3. 設(shè)計實現(xiàn)3.1 初始化 init

          初始化部分代碼主要功能是完成日志數(shù)據(jù)結(jié)構(gòu)體的構(gòu)造,并通過傳入?yún)?shù) log_file_cfg_t cfg 配置日志文件的配置信息,如單個日志文件大小、日志文件名、最多存放的日志文件數(shù)等內(nèi)容,日志模塊初始化部分代碼如下:

          1. log_file_t log_storage_init(log_file_cfg_t cfg)

          2. {

          3.     log_file_t log = NULL;

          4.     log_file_cfg_t log_cfg = NULL;

          5.     log_file_read_t log_read = NULL;


          6.     log = (log_file_t)malloc(sizeof(struct log_file_config));

          7.     if (log == NULL)

          8.         goto error;

          9.     

          10.     log_cfg = (log_file_cfg_t)malloc(sizeof(struct log_file_config));

          11.     if (log_cfg == NULL) {

          12.         free(log);

          13.         log = NULL;

          14.         goto error;

          15.     }


          16.     log_read = (log_file_read_t)malloc(sizeof(struct log_file_read));

          17.     if (log_read == NULL) {

          18.         free(log);

          19.         log = NULL;

          20.         free(log_cfg);

          21.         log_cfg = NULL;

          22.         goto error;

          23.     }


          24.     memcpy(log_cfg, cfg, sizeof(struct log_file_config));

          25.     log_read->rotate_index = 0;

          26.     log_read->file_offset = 0;

          27.     

          28.     log->cfg = log_cfg;

          29.     log->read = log_read;

          30.     log->user_data = NULL;


          31. error:

          32.     return log;

          33. }

          3.2 日志寫入 write

          日志寫入部分代碼主要分為兩大部分,一部分是正常寫入,另一部分是文件輪轉(zhuǎn);當(dāng)寫入的文件超過單個文件大小限制時,即會觸發(fā)文件輪轉(zhuǎn)操作。


          在文件輪轉(zhuǎn)中,主要做的是:創(chuàng)建一個新的日志文件并判斷日志文件總大小是否超出限制,如果超出則刪除最早的那一份日志文件,具體設(shè)計細(xì)節(jié)可參考上文設(shè)計概要中的詳細(xì)設(shè)計部分。


          實現(xiàn)代碼如下:

          1. static int log_rotate(log_file_t log)

          2. {

          3.     int ret = 0;

          4.     FILE *fp;

          5.     char old_filename[NAME_MAX + 10] = {0};

          6.     char new_filename[NAME_MAX + 10] = {0};


          7.     for (int i = log->cfg->rotate_num; i > 0; i --) {

          8.         memset(old_filename, 0, sizeof(old_filename));

          9.         memset(new_filename, 0, sizeof(new_filename));


          10.         snprintf(old_filename, sizeof(old_filename), i ? "%s_%d.log" : "%s.log", log->cfg->filename, i - 1);

          11.         snprintf(new_filename, sizeof(new_filename), "%s_%d.log", log->cfg->filename, i);


          12.         printf("old:%s new:%s\n", old_filename, new_filename);

          13.         

          14.         if ((fp = fopen(new_filename, "r")) != NULL) {

          15.             if (fclose(fp) != 0) {

          16.                 ret = -1;

          17.                 goto error;

          18.             }

          19.             if (remove(new_filename) != 0) {

          20.                 ret = -2;

          21.                 goto error;

          22.             }

          23.         }


          24.         if ((fp = fopen(old_filename, "r")) != NULL) {

          25.             if (fclose(fp) != 0) {

          26.                 ret = -1;

          27.                 goto error;

          28.             }

          29.             if (rename(old_filename, new_filename) != 0) {

          30.                 ret = -3;

          31.                 goto error;

          32.             }

          33.         }

          34.     }


          35. error:

          36.     return ret;

          37. }


          38. int log_storage_write(log_file_t log, const unsigned char *buf, unsigned int len)

          39. {

          40.     int ret = 0;

          41.     int file_size = 0;

          42.     char full_filename[NAME_MAX + 5] = {0};

          43.     FILE *fp = NULL;


          44.     if (log == NULL || log->cfg == NULL || log->read == NULL || buf == NULL || len == 0) {

          45.         ret = -1;

          46.         goto param_error;

          47.     }


          48.     snprintf(full_filename, sizeof(full_filename), "%s.log", log->cfg->filename);

          49.     

          50.     printf("fullfilename:%s\n", full_filename);

          51.     log_file_lock();


          52.     fp = fopen(full_filename, "a+b");

          53.     if (fp == NULL) {

          54.         ret = -2;

          55.         goto error;

          56.     }


          57.     fseek(fp, 0L, SEEK_END);

          58.     file_size = ftell(fp);

          59.     printf("file_size:%d\n", file_size);

          60.     if ((file_size + len) > log->cfg->max_size) {

          61.         if (fclose(fp) != 0) {

          62.             ret = -3;

          63.             goto error;

          64.         }


          65.         int j = 0;

          66.         j = log_rotate(log);

          67.         printf("log rotate:%d\n", j);

          68.         fp = fopen(full_filename, "a+b");

          69.         if (fp == NULL) {

          70.             ret = -2;

          71.             goto error;

          72.         }

          73.     }


          74.     if (fwrite(buf, len, 1, fp) != 1) {

          75.         fclose(fp);

          76.         ret = -4;

          77.         goto error;

          78.     }


          79. error:

          80. if (fp != NULL) {

          81. if (fclose(fp) != 0) {

          82. ret = -3;

          83. goto error;

          84. }

          85. }

          86.     log_file_unlock();

          87. param_error:

          88.     return ret;

          89. }

          3.3 日志讀取 read

          此處日志讀取在本文主題中非重點設(shè)計內(nèi)容,因此此處做簡單設(shè)計,通過傳入?yún)?shù)判斷應(yīng)該讀取哪一份文件之后進(jìn)行直接讀取。設(shè)計代碼如下:

          1. int log_storage_read(log_file_t log, unsigned int rotate_num, unsigned char *buf, unsigned int *len)

          2. {

          3.     int ret = 0;

          4.     int file_size = 0;

          5.     char full_filename[NAME_MAX + 5] = {0};

          6.     FILE *fp = NULL;


          7.     if (log == NULL || log->cfg == NULL || log->read == NULL || buf == NULL || len == 0) {

          8.         ret = -1;

          9.         goto param_error;

          10.     }


          11.     if (rotate_num == 0)

          12.         snprintf(full_filename, sizeof(full_filename), "%s.log", log->cfg->filename);

          13.     else

          14.         snprintf(full_filename, sizeof(full_filename), "%s.log.%d", log->cfg->filename, rotate_num);


          15.     log_file_lock();


          16.     fp = fopen(full_filename, "a+b");

          17.     if (fp == NULL) {

          18.         ret = -2;

          19.         goto error;

          20.     }

          21.     /* check file length. */

          22.     fseek(fp, 0L, SEEK_END);

          23.     file_size = ftell(fp);

          24.     printf("file_size:%d\n", file_size);

          25.     if (file_size < *len)

          26.         *len = file_size;


          27.     fseek(fp, 0L, SEEK_SET);

          28.     if (fread(buf, *len, 1, fp) != 1) {

          29.         ret = -3;

          30.         fclose(fp);

          31.         goto error;

          32.     }


          33. error:

          34. if (fp != NULL) {

          35. if (fclose(fp) != 0) {

          36. ret = -4;

          37. goto error;

          38. }

          39. }

          40.     log_file_unlock();

          41. param_error:

          42.     return ret;

          43. }

          3.4 注銷 deinit

          注銷的主要功能是將我們在 init 時創(chuàng)建的數(shù)據(jù)結(jié)構(gòu)進(jìn)行回收,如果模塊內(nèi)部有功能處于打開裝填,也應(yīng)關(guān)閉模塊的功能,此處我們僅需對 init 時創(chuàng)建的 log_file_t log 數(shù)據(jù)結(jié)構(gòu)體進(jìn)行注銷、內(nèi)存回收即可,具體代碼實現(xiàn)如下:

          1. int log_storage_deinit(log_file_t log)

          2. {

          3. if (log == NULL)

          4. return -1;

          5. if (log->cfg != NULL)

          6. free(log->cfg);

          7. if (log->read != NULL)

          8. free(log->read);

          9. if (log->user_data != NULL)

          10. free(log->user_data);

          11. free(log);

          12. return 0;

          13. }

          3.5 全部代碼匯總

          日志模塊內(nèi)核頭文件:simple_storage.h

          1. #ifndef __SIMPLE_STORAGE_H__

          2. #define __SIMPLE_STORAGE_H__


          3. #define NAME_MAX        40


          4. struct log_file_config {

          5.     const char filename[NAME_MAX];     /* Filename of this type. */

          6.     int max_size;       /* single file max size. */

          7.     int rotate_num;     /* The number of files that support rotate. */

          8. };

          9. typedef struct log_file_config* log_file_cfg_t;


          10. struct log_file_read {

          11.     int rotate_index;   /* The rotate file index. */

          12.     int file_offset;    /* The offset of the currently read file. */

          13. };

          14. typedef struct log_file_read* log_file_read_t;


          15. struct log_file {

          16.     log_file_cfg_t cfg;

          17.     log_file_read_t read;

          18.     void *user_data;

          19. };

          20. typedef struct log_file* log_file_t;



          21. log_file_t log_storage_init(log_file_cfg_t cfg);

          22. int log_storage_write(log_file_t log, const unsigned char *buf, unsigned int len);

          23. int log_storage_read(log_file_t log, unsigned int rotate_num, unsigned char *buf, unsigned int *len);

          24. int log_storage_deinit(log_file_t log);



          25. #endif /* __SIMPLE_STORAGE_H__ */


          日志模塊內(nèi)核文件: simple_storage.c

          1. #include "simple_storage.h"

          2. #include "simple_storage_port.h"

          3. #include <stdio.h>

          4. #include <string.h>


          5. log_file_t log_storage_init(log_file_cfg_t cfg)

          6. {

          7.     log_file_t log = NULL;

          8.     log_file_cfg_t log_cfg = NULL;

          9.     log_file_read_t log_read = NULL;


          10.     log = (log_file_t)malloc(sizeof(struct log_file_config));

          11.     if (log == NULL)

          12.         goto error;

          13.     

          14.     log_cfg = (log_file_cfg_t)malloc(sizeof(struct log_file_config));

          15.     if (log_cfg == NULL) {

          16.         free(log);

          17.         log = NULL;

          18.         goto error;

          19.     }


          20.     log_read = (log_file_read_t)malloc(sizeof(struct log_file_read));

          21.     if (log_read == NULL) {

          22.         free(log);

          23.         log = NULL;

          24.         free(log_cfg);

          25.         log_cfg = NULL;

          26.         goto error;

          27.     }


          28.     memcpy(log_cfg, cfg, sizeof(struct log_file_config));

          29.     log_read->rotate_index = 0;

          30.     log_read->file_offset = 0;

          31.     

          32.     log->cfg = log_cfg;

          33.     log->read = log_read;

          34.     log->user_data = NULL;


          35. error:

          36.     return log;

          37. }


          38. static int log_rotate(log_file_t log)

          39. {

          40.     int ret = 0;

          41.     FILE *fp;

          42.     char old_filename[NAME_MAX + 10] = {0};

          43.     char new_filename[NAME_MAX + 10] = {0};


          44.     for (int i = log->cfg->rotate_num; i > 0; i --) {

          45.         memset(old_filename, 0, sizeof(old_filename));

          46.         memset(new_filename, 0, sizeof(new_filename));


          47.         snprintf(old_filename, sizeof(old_filename), i ? "%s_%d.log" : "%s.log", log->cfg->filename, i - 1);

          48.         snprintf(new_filename, sizeof(new_filename), "%s_%d.log", log->cfg->filename, i);


          49.         printf("old:%s new:%s\n", old_filename, new_filename);

          50.         

          51.         if ((fp = fopen(new_filename, "r")) != NULL) {

          52.             if (fclose(fp) != 0) {

          53.                 ret = -1;

          54.                 goto error;

          55.             }

          56.             if (remove(new_filename) != 0) {

          57.                 ret = -2;

          58.                 goto error;

          59.             }

          60.         }


          61.         if ((fp = fopen(old_filename, "r")) != NULL) {

          62.             if (fclose(fp) != 0) {

          63.                 ret = -1;

          64.                 goto error;

          65.             }

          66.             if (rename(old_filename, new_filename) != 0) {

          67.                 ret = -3;

          68.                 goto error;

          69.             }

          70.         }

          71.     }


          72. error:

          73.     return ret;

          74. }


          75. int log_storage_write(log_file_t log, const unsigned char *buf, unsigned int len)

          76. {

          77.     int ret = 0;

          78.     int file_size = 0;

          79.     char full_filename[NAME_MAX + 5] = {0};

          80.     FILE *fp = NULL;


          81.     if (log == NULL || log->cfg == NULL || log->read == NULL || buf == NULL || len == 0) {

          82.         ret = -1;

          83.         goto param_error;

          84.     }


          85.     snprintf(full_filename, sizeof(full_filename), "%s.log", log->cfg->filename);

          86.     

          87.     printf("fullfilename:%s\n", full_filename);

          88.     log_file_lock();


          89.     fp = fopen(full_filename, "a+b");

          90.     if (fp == NULL) {

          91.         ret = -2;

          92.         goto error;

          93.     }


          94.     fseek(fp, 0L, SEEK_END);

          95.     file_size = ftell(fp);

          96.     printf("file_size:%d\n", file_size);

          97.     if ((file_size + len) > log->cfg->max_size) {

          98.         if (fclose(fp) != 0) {

          99.             ret = -3;

          100.             goto error;

          101.         }


          102.         int j = 0;

          103.         j = log_rotate(log);

          104.         printf("log rotate:%d\n", j);

          105.         fp = fopen(full_filename, "a+b");

          106.         if (fp == NULL) {

          107.             ret = -2;

          108.             goto error;

          109.         }

          110.     }


          111.     if (fwrite(buf, len, 1, fp) != 1) {

          112.         fclose(fp);

          113.         ret = -4;

          114.         goto error;

          115.     }


          116. error:

          117. if (fp != NULL) {

          118. if (fclose(fp) != 0) {

          119. //TODO: check the amount of disk space, delete if there is not enough space.

          120. ret = -3;

          121. goto error;

          122. }

          123. }

          124.     log_file_unlock();

          125. param_error:

          126.     return ret;

          127. }


          128. int log_storage_read(log_file_t log, unsigned int rotate_num, unsigned char *buf, unsigned int *len)

          129. {

          130.     int ret = 0;

          131.     int file_size = 0;

          132.     char full_filename[NAME_MAX + 5] = {0};

          133.     FILE *fp = NULL;


          134.     if (log == NULL || log->cfg == NULL || log->read == NULL || buf == NULL || len == 0) {

          135.         ret = -1;

          136.         goto param_error;

          137.     }


          138.     if (rotate_num == 0)

          139.         snprintf(full_filename, sizeof(full_filename), "%s.log", log->cfg->filename);

          140.     else

          141.         snprintf(full_filename, sizeof(full_filename), "%s.log.%d", log->cfg->filename, rotate_num);


          142.     log_file_lock();


          143.     fp = fopen(full_filename, "a+b");

          144.     if (fp == NULL) {

          145.         ret = -2;

          146.         goto error;

          147.     }

          148.     /* check file length. */

          149.     fseek(fp, 0L, SEEK_END);

          150.     file_size = ftell(fp);

          151.     printf("file_size:%d\n", file_size);

          152.     if (file_size < *len)

          153.         *len = file_size;


          154.     fseek(fp, 0L, SEEK_SET);

          155.     if (fread(buf, *len, 1, fp) != 1) {

          156.         ret = -3;

          157.         fclose(fp);

          158.         goto error;

          159.     }


          160. error:

          161. if (fp != NULL) {

          162. if (fclose(fp) != 0) {

          163. ret = -4;

          164. goto error;

          165. }

          166. }

          167.     log_file_unlock();

          168. param_error:

          169.     return ret;

          170. }


          171. int log_storage_deinit(log_file_t log)

          172. {

          173. if (log == NULL)

          174. return -1;

          175. if (log->cfg != NULL)

          176. free(log->cfg);

          177. if (log->read != NULL)

          178. free(log->read);

          179. if (log->user_data != NULL)

          180. free(log->user_data);

          181. free(log);

          182. return 0;

          183. }


          在日志模塊源文件的代碼中,我們可以看到實際每次操作文件的時候,都有調(diào)用一個函數(shù)鎖操作,考慮到不同平臺的鎖操作實現(xiàn)不一樣,因此將此部分通過函數(shù)導(dǎo)出來,放置在模塊的端口文件中。不同的平臺、系統(tǒng)根據(jù)各自的平臺和系統(tǒng)的情況進(jìn)行實現(xiàn),如像裸機(jī)編程這類不需要進(jìn)行鎖操作的不進(jìn)行函數(shù)實現(xiàn)即可。


          日志模塊端口頭文件:simple_storage_port.c

          1. #ifndef __SIMPLE_STORAGE_PORT_H__

          2. #define __SIMPLE_STORAGE_PORT_H__


          3. int log_file_init(void);

          4. int log_file_lock(void);

          5. int log_file_unlock(void);



          6. #endif /* __SIMPLE_STORAGE_PORT_H__ */


          日志模塊端口源文件:simple_storage_port.h

          1. #include "simple_storage_port.h"


          2. int log_file_init(void)

          3. {

          4.     return 0;

          5. }


          6. int log_file_lock(void)

          7. {

          8.     return 0;

          9. }


          10. int log_file_unlock(void)

          11. {

          12.     return 0;

          13. }

          4. 測試

          將以上代碼進(jìn)行運行測試,硬件平臺如下:


          • 控制器: stm32f103vet6,野火指南者開發(fā)板


          • 存儲芯片: CS創(chuàng)世 SD nand,型號:CSNP4GCR01-AMW


          • 文件系統(tǒng): FATFS,注意此日志不受文件系統(tǒng)限制


          • 操作系統(tǒng): RT-Thread,此模塊與操作系統(tǒng)無關(guān),此處只是方便使用故自行移植了rtthread

          【嵌入式SD NAND】基于FATFS/Littlefs文件系統(tǒng)的日志框架實現(xiàn)

          應(yīng)用層代碼如下:


          1. int main(void)

          2. {

          3. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

          4. HAL_Init();

          5. /* USER CODE BEGIN Init */

          6. /* USER CODE END Init */

          7. /* Configure the system clock */

          8. SystemClock_Config();

          9. /* USER CODE BEGIN SysInit */

          10. /* USER CODE END SysInit */

          11. /* Initialize all configured peripherals */

          12. MX_GPIO_Init();

          13. MX_SDIO_SD_Init();

          14. MX_USART1_UART_Init();

          15. MX_FATFS_Init();

          16. /* USER CODE BEGIN 2 */

          17. struct log_file_config log_cfg = {

          18. .filename = "test",

          19. .max_size = 2048,

          20. .rotate_num = 10,

          21. };

          22. log_file_t log = NULL;

          23. log = log_storage_init(&log_cfg);

          24. if (log == NULL)

          25. return;

          26. /* USER CODE END 2 */

          27. /* Infinite loop */

          28. /* USER CODE BEGIN WHILE */

          29. unsigned char buf[2048] = {0};

          30. int len = 0;

          31. while (1) {

          32. // ... 省略用戶代碼

          33. /* 寫入測試 */

          34. for (int i = 0; i < 2048; i++) {

          35. log_storage_write(log, "hello world", sizeof("hello world"));

          36. rt_thread_mdelay(100);

          37. }

          38. /* 讀取測試 */

          39. len = sizeof(buf);

          40. memset(buf, 0, sizeof(buf));

          41. log_storage_read(log, 1, buf, &len);

          42. for (int i = 0; i < len; i ++)

          43. rt_kprintf("%c", buf[i]);

          44. rt_thread_mdelay(1000);

          45. }

          46. }


          測試結(jié)果如下:

          1. msg> hello worldhello world hello world hello world hello world hello world hello world hello world hello world ...省略


          2. msh > ls

          3. test.log    2046

          4. test.log.0     2046

          5. test.log.1     2046

          6. test.log.2     2046

          7. test.log.3     2046

          8. test.log.4     2046

          5. 總結(jié)

          綜上便是基于文件系統(tǒng)的簡易日志模塊設(shè)計的全部內(nèi)容了,雖然簡陋了點,但相信對于大部分沒有接觸過日志系統(tǒng)設(shè)計的人來說提供了很好的一條設(shè)計思路。


          也正因為簡易,給大家對于日志系統(tǒng)設(shè)計的優(yōu)化留足了大量的優(yōu)化空間。比如:


          文件輪轉(zhuǎn)的時候需要對每個文件的文件名進(jìn)行修改,是否可以有更好的方式不用每個文件都修改呢?

          文件名的設(shè)計是不方便閱讀的,是否可以引入時間參數(shù)?

          文件名設(shè)計如何引入了時間參數(shù),當(dāng)設(shè)備RTC備用電池掉電的時候又如何保證文件不會被錯誤覆蓋?

          文件的讀取顯然優(yōu)化空間更大,實際上用戶不應(yīng)該傳入rotate_num 參數(shù),因為這是模塊內(nèi)部的參數(shù),用戶不可感知的

          文件讀取如何做到分多次讀取一個文件的內(nèi)容,且不會重復(fù),是順序讀?。?/p>

          等等,以上只是我簡單想到的幾點內(nèi)容,大家不妨思考下如何實現(xiàn)方案更好呢?當(dāng)然又還有哪些需求是需要引入的呢,也歡迎大家在評論區(qū)留言,關(guān)注我,后續(xù)抽時間再分享下改良版日志系統(tǒng)!??!


          *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。




          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉