自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊一聊Lwip內(nèi)存管理策略

存儲 存儲軟件
LWIP中的內(nèi)存池(POOL)分配策略簡單,但是內(nèi)存的分配、釋放效率高,可以有效的防止內(nèi)存碎片的產(chǎn)生。

[[394238]]

01內(nèi)存池

LWIP中的內(nèi)存池(POOL)分配策略簡單,但是內(nèi)存的分配、釋放效率高,可以有效的防止內(nèi)存碎片的產(chǎn)生。在內(nèi)存的策略下用戶只能申請固定大小的空間,內(nèi)存池方法主要用于LWIP內(nèi)核中固定數(shù)據(jù)結(jié)構(gòu)的分配,比如UDP控制塊,TCP控制塊等。LWIP內(nèi)核在初始化的時候已經(jīng)為每個數(shù)據(jù)結(jié)構(gòu)類型都初始化了一定數(shù)量的POOL,文件memp.c和memp.h就是內(nèi)存池相關內(nèi)容。

至于LWIP內(nèi)核建立多少種POOL依賴于用戶和系統(tǒng)配置,比如如果定義了宏LWIP_UDP為1,那么在編譯時與UDP控制塊數(shù)據(jù)結(jié)構(gòu)相關的內(nèi)存池POOL就會被建立(MEMP_UDP_PCB),如果定義了宏LWIP_TCP為1,編譯時與TCP數(shù)據(jù)結(jié)構(gòu)相關的內(nèi)存池就會被建立(MEMP_TCP_PCB、MEMP_TCP_SEG)等等!每種類型的POOL大小都是固定的。用戶可以在lwipopts.h文件中定義,LWIP在opt.h中已經(jīng)配置了默認值。

有6個與LWIP內(nèi)存池有關的全局變量和數(shù)據(jù)結(jié)構(gòu):memp_t、memp_tab[]、memp_sizes[]、memp_num[]、memp_desc[]和memp_memory[]。

1.1、memp_t數(shù)據(jù)類型

memp_t為一個枚舉類型變量,用來給每個POOL取個名字,或者說是編號。memp_t在文件memp.h文件中定義,定義如下:

  1. #define LWIP_MEMPOOL(name,num,size,desc)  MEMP_##name

這句代碼意思是:

遇到LWIP_MEMPOOL(name,num,size,desc) 換成MEMP_##name

例如:在memp_std.h的34行

  1. LWIP_MEMPOOL(RAW_PCB,        MEMP_NUM_RAW_PCB,         sizeof(structraw_pcb),        "RAW_PCB"

變成了

 

  1. MEMP_RAW_PCB 

所以memp_t編譯之后如下:

  1. typedef enum 
  2.     MEMP_ RAW_PCB, 
  3.     MEMP_ UDP_PCB, 
  4.     MEMP_ TCP_PCB, 
  5.     MEMP_ TCP_PCB_LISTEN, 
  6.     MEMP_ TCP_SEG, 
  7.     MEMP_ REASSDATA, 
  8.      ……. 
  9.     MEMP_MAX 
  10. } memp_t; 

其中MEMP_MAX代表memp_t代表枚舉類型中元素總個數(shù)(C語言基礎知識),并不代表任何類型的POOL

1.2、memp_tab全局指針數(shù)組

memp_tab為一個全局指針數(shù)組,指向每類POOL的第一個POOL,memp_tab在文件memp.c文件中定義,定義如下:

1.3、memp_sizes全局數(shù)組

memp_sizes為一個全局數(shù)組,用來記錄每個POOL的大小,memp_sizes在文件memp.c文件中定義,定義如下:

編譯之后

  1. const u16_t memp_sizes[MEMP_MAX] = 
  2.     LWIP_MEM_ALIGN_SIZE(sizeof(struct raw_pcb)), 
  3.     LWIP_MEM_ALIGN_SIZE(sizeof(struct udp_pcb)), 
  4.     LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)), 
  5.     LWIP_MEM_ALIGN_SIZE(sizeof(structtcp_pcb_listen)), 
  6.     LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)), 
  7.     ……. 

memp_sizes中保存了每種類型POOL的大小,這里的大小都是進行了內(nèi)存對齊的。

這個宏定義,MEM_ALIGNMENT為4,也就是4字節(jié)對齊。

分析這個宏定義,也就說,當MEM_ALIGNMENT為4時,傳入的size為3時,變?yōu)?

申請3個字節(jié),實際申請4個字節(jié)

申請6個字節(jié),實際申請8個字節(jié)

申請18個字節(jié),實際申請20個字節(jié)

1.4、 memp_num[]全局數(shù)組

memp_num為一個全局數(shù)組,用來記錄每類POOL中POOL的個數(shù),memp_num在文件memp.c文件中定義,定義如下:

編譯之后

  1. const u16_t memp_num[MEMP_MAX] = 
  2.     (MEMP_NUM_RAW_PCB), 
  3.     (MEMP_NUM_UDP_PCB), 
  4.     (MEMP_NUM_TCP_PCB), 
  5.     (MEMP_NUM_TCP_PCB_LISTEN), 
  6.     (MEMP_NUM_TCP_SEG), 
  7.     …… 
  8. }; 

上面的MEMP_NUM_RAW_PCB、MEMP_NUM_UDP_PCB等等都是由用戶定義的,用來記錄對應的POOL的數(shù)量,用戶可以在lwipopts.h文件中定義,LWIP在opt.h中已經(jīng)配置了默認值。

1.5、memp_desc[]全局型指針數(shù)組

memp_desc為一個全局型指針數(shù)組,指向每類POOL的描述符,memp_desc在文件memp.c文件中定義,定義如下:

編譯之后

  1. static const char *memp_desc[MEMP_MAX] = 
  2.    ("RAW_PCB"), 
  3.    ("UDP_PCB"), 
  4.    ("TCP_PCB"), 
  5.    ("TCP_PCB_LISTEN"), 
  6.    ("TCP_PCB_LISTEN"), 
  7.    ……. 
  8. }; 

memp_desc中的每個元素指向了一個字符串,這些字符串在統(tǒng)計信息輸出中可能用到。

1.6、memp_memory[]數(shù)組

memp_memory為一個數(shù)組,這個數(shù)組才是真正的內(nèi)存池!!!這個數(shù)組在文件memp.c文件中定義,定義如下:

編譯之后

  1. static u8_t memp_memory 
  2.    MEM_ALIGNMENT – 1 
  3.    +((MEMP_NUM_RAW_PCB) * (MEMP_SIZE + 
  4.      MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)) )) 
  5.    +((MEMP_NUM_UDP_PCB) * (MEMP_SIZE + 
  6.     MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)) )) 
  7.    +((MEMP_NUM_TCP_PCB) * (MEMP_SIZE + 
  8.     MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb)) )) 
  9.    …….. 
  10. ]; 

其中MEMP_SIZE表示需要在每個POOL頭部預留的空間,LWIP中在某些特殊場合使用該空間中的值來對POOL進行特殊處理,這里不使用該項功能,所以MEMP_SIZE為0,。如果使用到MEMP_SIZE的話也需要對這個大小進行內(nèi)存對齊!

1.7、與內(nèi)存池管理相關的函數(shù):

使用內(nèi)存池分配內(nèi)存的優(yōu)點在于速度快,效率高,不會產(chǎn)生內(nèi)存碎片,但是缺點在于只能分配各種固定大小的內(nèi)存空間,LWIP必須實現(xiàn)知道用戶要使用哪些類型的POOL,每種類型的POOL數(shù)量,然后根據(jù)這個需求建立內(nèi)存池。

02內(nèi)存堆

LWIP還提供了另外一種內(nèi)存策略—內(nèi)存堆,使用內(nèi)存堆策略就可以隨便申請任意大小的內(nèi)存了。但是這種方法效率和速度會有所下降。

使用內(nèi)存堆策略的話用戶申請的內(nèi)存大小有最小限制,所申請的內(nèi)存大小不能小于MIN_SIZE,LWIP默認的MIN_SIZE為12個字節(jié),在mem.c文件中。該值用戶可以自行定義。

使用內(nèi)存堆策略,其有點事內(nèi)存浪費小,比較簡單,適合于小內(nèi)存的管理,但是缺點就是如果頻繁的進行動態(tài)內(nèi)存申請和釋放的話,可能會造成嚴重的內(nèi)存碎片,如果碎片嚴重的話可能會導致內(nèi)存分配失敗!

內(nèi)存堆策略下的內(nèi)存空間是數(shù)組:ram_heap[]。在mem.c文件中。

與內(nèi)存堆有關的函數(shù)有3個:

  1. mem_init() 
  2. mem_malloc() 
  3. mem_free() 

03其他內(nèi)存策略

前面講的內(nèi)存池(POOL)和內(nèi)存堆(HEAP)這兩個內(nèi)存策略都是LWIP默認的內(nèi)存策略,LWIP內(nèi)核中大量的使用了這兩個策略,不過LWIP也給我們提供了其他可選的內(nèi)存策略。

(1)、當定義宏MEM_LIBC_MALLOC為1,那么與內(nèi)存堆相關的代碼就不會被編譯的,內(nèi)存堆中的mem_malloc()和mem_free()就會被ANSIC編譯器自帶的malloc()和free()替代。

(2)、當定義宏MEMP_MEM_MALLOC為1,那么內(nèi)存池文件memp.c就不會被編譯。

(3)、當定義宏MEM_USE_POOLS定義為1,那么內(nèi)存堆分配相關的函數(shù)及全局變量不會被編譯,這個時候就用內(nèi)存池分配方式來實現(xiàn)內(nèi)存堆的的分配方式,因為內(nèi)存池的分配策略效率很高。

但是(3)中的方法使用起來比較麻煩,需要在lwipopts.h中定義宏MEM_USE_POOLS和MEM_USE_CUSTOM_POOLS都為1,還需要在另外一個頭文件lwippools.h中開辟一些用于內(nèi)存堆分配函數(shù)的內(nèi)存池。

 

責任編輯:武曉燕 來源: 知曉編程
相關推薦

2020-06-28 09:30:37

Linux內(nèi)存操作系統(tǒng)

2022-05-18 16:35:43

Redis內(nèi)存運維

2022-05-12 23:19:15

Redis內(nèi)存碎片處理

2023-03-06 21:23:23

Redis數(shù)據(jù)庫

2019-03-20 14:29:46

Linux虛擬內(nèi)存

2022-08-22 09:20:05

Kubernetes工作負載管理

2022-08-30 10:15:27

Kubernetes數(shù)據(jù)持久化管理

2023-07-25 15:06:39

2023-09-22 17:36:37

2021-01-28 22:31:33

分組密碼算法

2020-05-22 08:16:07

PONGPONXG-PON

2020-06-02 15:06:13

Tomcat配置頁面

2018-06-07 13:17:12

契約測試單元測試API測試

2023-03-03 12:37:50

JavaJVM內(nèi)存溢出

2021-08-02 07:57:02

內(nèi)存Go語言

2024-04-03 09:03:05

2021-08-04 09:32:05

Typescript 技巧Partial

2022-08-08 08:25:21

Javajar 文件

2022-11-01 08:46:20

責任鏈模式對象

2018-11-29 09:13:47

CPU中斷控制器
點贊
收藏

51CTO技術棧公眾號