关于lwip中pbuf_alloc()内存申请函数
生活随笔
收集整理的這篇文章主要介紹了
关于lwip中pbuf_alloc()内存申请函数
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1. PBUF_RAM一次性分配size大小的連續(xù)內(nèi)存
2. RBUF_ROM只需要分配小小的管理pbuf的控制管理內(nèi)存
3. PBUF_ROOL分配一個(gè)鏈表,鏈表上每個(gè)元素所管理的內(nèi)存最大不超過PBUF_POOL_BUFSIZE,它更像linux
?? 中的kmem_alloc內(nèi)存高速緩存機(jī)制,所以它也更適合在網(wǎng)卡驅(qū)動(dòng)irq中斷中為剛剛到來的網(wǎng)絡(luò)數(shù)據(jù)包申請存儲(chǔ)空間
/*-----------------------------------------------------------------------------------*/
/* pbuf_alloc():
?*
?* Allocates a pbuf at protocol layer l. The actual memory allocated
?* for the pbuf is determined by the layer at which the pbuf is
?* allocated and the requested size (from the size parameter). The
?* flag parameter decides how and where the pbuf should be allocated
?* as follows:
?*?
?* * PBUF_RAM: buffer memory for pbuf is allocated as one large
?*???????????? chunk. This includes protocol headers as well.?
?* * RBUF_ROM: no buffer memory is allocated for the pbuf, even for
?*???????????? protocol headers. Additional headers must be prepended
?*???????????? by allocating another pbuf and chain in to the front of
?*???????????? the ROM pbuf.?? ?????? ?
?* * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
?*????????????? the pbuf pool that is allocated during pbuf_init().
?*/
/*-----------------------------------------------------------------------------------*/
struct pbuf *
pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
{
? struct pbuf *p, *q, *r;
? u16_t offset;
? s32_t rsize;
? offset = 0;
? switch(l) {
? case PBUF_TRANSPORT:? // 如果為傳輸層申請pbuf,那么有效數(shù)據(jù)的偏移位置為PBUF_TRANSPORT_HLEN[luther.gliethttp]
??? offset += PBUF_TRANSPORT_HLEN;
??? /* FALLTHROUGH */
? case PBUF_IP:???????? // 如果為ip層申請pbuf,那么有效數(shù)據(jù)的偏移位置為PBUF_IP_HLEN+PBUF_LINK_HLEN
??? offset += PBUF_IP_HLEN;
??? offset += PBUF_LINK_HLEN;
??? /* FALLTHROUGH */
? case PBUF_LINK:?????? // 如果是鏈路層申請pbuf內(nèi)存,那么數(shù)據(jù)偏移位置就是0
??? break;
? case PBUF_RAW:
??? break;
? default:
??? ASSERT("pbuf_alloc: bad pbuf layer", 0);
??? return NULL;
? }
? switch(flag) {
? case PBUF_POOL:
??? /* Allocate head of pbuf chain into p. */
??? p = pbuf_pool_alloc(); // 為PBUF_POOL類型,那么需要多申請pbuf的head控制頭部所需內(nèi)存[luther.gliethttp]
??? if(p == NULL) {
#ifdef PBUF_STATS
????? ++stats.pbuf.err;
#endif /* PBUF_STATS */
????? return NULL;
??? }
??? p->next = NULL;
?? ?
??? /* Set the payload pointer so that it points offset bytes into
?????? pbuf data memory. */
??? p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); // 以offset為基準(zhǔn),登記有效數(shù)據(jù)存儲(chǔ)的起始偏移位置到p->payload[luther.gliethttp]
??? /* The total length of the pbuf is the requested size. */
??? p->tot_len = size; // pbuf鏈表上有效數(shù)據(jù)總大小
??? /* Set the length of the first pbuf is the chain. */
??? // pbuf鏈表上每個(gè)元素所能存儲(chǔ)的最大數(shù)據(jù)為PBUF_POOL_BUFSIZE,如果超過該值,那么就會(huì)
??? // 使用鏈表方式,鏈接其很多個(gè)pbuf,直到申請的size數(shù)據(jù)全部能夠正常存儲(chǔ)為止[luther.gliethttp]
??? p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;
??? p->flags = PBUF_FLAG_POOL;
????
??? /* Allocate the tail of the pbuf chain. */
??? r = p;
??? rsize = size - p->len; // 第1個(gè)pbuf所能存儲(chǔ)數(shù)據(jù)大小為p->len,這里計(jì)算還需要多少存儲(chǔ)空間存儲(chǔ)剩下的數(shù)據(jù).
??? while(rsize > 0) {???? // 構(gòu)成數(shù)據(jù)緩存鏈表,每個(gè)鏈表元素所能存儲(chǔ)的最大數(shù)據(jù)量為PBUF_POOL_BUFSIZE個(gè)字節(jié)[luther.gliethttp]
????? q = pbuf_pool_alloc();
????? if(q == NULL) {
??? DEBUGF(PBUF_DEBUG, ("pbuf_alloc: Out of pbufs in pool,\n"));
#ifdef PBUF_STATS
??????? ++stats.pbuf.err;
#endif /* PBUF_STATS */
??????? pbuf_pool_free(p);
??????? return NULL;
????? }
????? q->next = NULL;
????? r->next = q;
????? q->len = rsize > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rsize;
????? q->flags = PBUF_FLAG_POOL;
????? q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
????? r = q;
????? q->ref = 1;
????? q = q->next;
????? rsize -= PBUF_POOL_BUFSIZE;
??? }
??? r->next = NULL;
??? ASSERT("pbuf_alloc: pbuf->payload properly aligned",
??? ?? ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
??? break;
? case PBUF_RAM:
??? /* If pbuf is to be allocated in RAM, allocate memory for it. */
// PBUF_RAM類型內(nèi)存,那么一次性申請size大小的連續(xù)內(nèi)存
??? p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + size + offset));
??? if(p == NULL) {
????? return NULL;
??? }
??? /* Set up internal structure of the pbuf. */
??? p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
??? p->len = p->tot_len = size;
??? p->next = NULL;
??? p->flags = PBUF_FLAG_RAM;
??? ASSERT("pbuf_alloc: pbuf->payload properly aligned",
??? ?? ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
??? break;
? case PBUF_ROM:
??? /* If the pbuf should point to ROM, we only need to allocate
?????? memory for the pbuf structure. */
// PBUF_ROM類型內(nèi)存,那么只需要申請pbufs頭部控制結(jié)構(gòu)體所需內(nèi)存即可[luther.gliethttp]
??? p = memp_mallocp(MEMP_PBUF);
??? if(p == NULL) {
????? return NULL;
??? }
??? p->payload = NULL;
??? p->len = p->tot_len = size;
??? p->next = NULL;
??? p->flags = PBUF_FLAG_ROM;
??? break;
? default:
??? ASSERT("pbuf_alloc: erroneous flag", 0);
??? return NULL;
? }
? p->ref = 1;
? return p;
}?
2. RBUF_ROM只需要分配小小的管理pbuf的控制管理內(nèi)存
3. PBUF_ROOL分配一個(gè)鏈表,鏈表上每個(gè)元素所管理的內(nèi)存最大不超過PBUF_POOL_BUFSIZE,它更像linux
?? 中的kmem_alloc內(nèi)存高速緩存機(jī)制,所以它也更適合在網(wǎng)卡驅(qū)動(dòng)irq中斷中為剛剛到來的網(wǎng)絡(luò)數(shù)據(jù)包申請存儲(chǔ)空間
/*-----------------------------------------------------------------------------------*/
/* pbuf_alloc():
?*
?* Allocates a pbuf at protocol layer l. The actual memory allocated
?* for the pbuf is determined by the layer at which the pbuf is
?* allocated and the requested size (from the size parameter). The
?* flag parameter decides how and where the pbuf should be allocated
?* as follows:
?*?
?* * PBUF_RAM: buffer memory for pbuf is allocated as one large
?*???????????? chunk. This includes protocol headers as well.?
?* * RBUF_ROM: no buffer memory is allocated for the pbuf, even for
?*???????????? protocol headers. Additional headers must be prepended
?*???????????? by allocating another pbuf and chain in to the front of
?*???????????? the ROM pbuf.?? ?????? ?
?* * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
?*????????????? the pbuf pool that is allocated during pbuf_init().
?*/
/*-----------------------------------------------------------------------------------*/
struct pbuf *
pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
{
? struct pbuf *p, *q, *r;
? u16_t offset;
? s32_t rsize;
? offset = 0;
? switch(l) {
? case PBUF_TRANSPORT:? // 如果為傳輸層申請pbuf,那么有效數(shù)據(jù)的偏移位置為PBUF_TRANSPORT_HLEN[luther.gliethttp]
??? offset += PBUF_TRANSPORT_HLEN;
??? /* FALLTHROUGH */
? case PBUF_IP:???????? // 如果為ip層申請pbuf,那么有效數(shù)據(jù)的偏移位置為PBUF_IP_HLEN+PBUF_LINK_HLEN
??? offset += PBUF_IP_HLEN;
??? offset += PBUF_LINK_HLEN;
??? /* FALLTHROUGH */
? case PBUF_LINK:?????? // 如果是鏈路層申請pbuf內(nèi)存,那么數(shù)據(jù)偏移位置就是0
??? break;
? case PBUF_RAW:
??? break;
? default:
??? ASSERT("pbuf_alloc: bad pbuf layer", 0);
??? return NULL;
? }
? switch(flag) {
? case PBUF_POOL:
??? /* Allocate head of pbuf chain into p. */
??? p = pbuf_pool_alloc(); // 為PBUF_POOL類型,那么需要多申請pbuf的head控制頭部所需內(nèi)存[luther.gliethttp]
??? if(p == NULL) {
#ifdef PBUF_STATS
????? ++stats.pbuf.err;
#endif /* PBUF_STATS */
????? return NULL;
??? }
??? p->next = NULL;
?? ?
??? /* Set the payload pointer so that it points offset bytes into
?????? pbuf data memory. */
??? p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); // 以offset為基準(zhǔn),登記有效數(shù)據(jù)存儲(chǔ)的起始偏移位置到p->payload[luther.gliethttp]
??? /* The total length of the pbuf is the requested size. */
??? p->tot_len = size; // pbuf鏈表上有效數(shù)據(jù)總大小
??? /* Set the length of the first pbuf is the chain. */
??? // pbuf鏈表上每個(gè)元素所能存儲(chǔ)的最大數(shù)據(jù)為PBUF_POOL_BUFSIZE,如果超過該值,那么就會(huì)
??? // 使用鏈表方式,鏈接其很多個(gè)pbuf,直到申請的size數(shù)據(jù)全部能夠正常存儲(chǔ)為止[luther.gliethttp]
??? p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;
??? p->flags = PBUF_FLAG_POOL;
????
??? /* Allocate the tail of the pbuf chain. */
??? r = p;
??? rsize = size - p->len; // 第1個(gè)pbuf所能存儲(chǔ)數(shù)據(jù)大小為p->len,這里計(jì)算還需要多少存儲(chǔ)空間存儲(chǔ)剩下的數(shù)據(jù).
??? while(rsize > 0) {???? // 構(gòu)成數(shù)據(jù)緩存鏈表,每個(gè)鏈表元素所能存儲(chǔ)的最大數(shù)據(jù)量為PBUF_POOL_BUFSIZE個(gè)字節(jié)[luther.gliethttp]
????? q = pbuf_pool_alloc();
????? if(q == NULL) {
??? DEBUGF(PBUF_DEBUG, ("pbuf_alloc: Out of pbufs in pool,\n"));
#ifdef PBUF_STATS
??????? ++stats.pbuf.err;
#endif /* PBUF_STATS */
??????? pbuf_pool_free(p);
??????? return NULL;
????? }
????? q->next = NULL;
????? r->next = q;
????? q->len = rsize > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rsize;
????? q->flags = PBUF_FLAG_POOL;
????? q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
????? r = q;
????? q->ref = 1;
????? q = q->next;
????? rsize -= PBUF_POOL_BUFSIZE;
??? }
??? r->next = NULL;
??? ASSERT("pbuf_alloc: pbuf->payload properly aligned",
??? ?? ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
??? break;
? case PBUF_RAM:
??? /* If pbuf is to be allocated in RAM, allocate memory for it. */
// PBUF_RAM類型內(nèi)存,那么一次性申請size大小的連續(xù)內(nèi)存
??? p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + size + offset));
??? if(p == NULL) {
????? return NULL;
??? }
??? /* Set up internal structure of the pbuf. */
??? p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
??? p->len = p->tot_len = size;
??? p->next = NULL;
??? p->flags = PBUF_FLAG_RAM;
??? ASSERT("pbuf_alloc: pbuf->payload properly aligned",
??? ?? ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
??? break;
? case PBUF_ROM:
??? /* If the pbuf should point to ROM, we only need to allocate
?????? memory for the pbuf structure. */
// PBUF_ROM類型內(nèi)存,那么只需要申請pbufs頭部控制結(jié)構(gòu)體所需內(nèi)存即可[luther.gliethttp]
??? p = memp_mallocp(MEMP_PBUF);
??? if(p == NULL) {
????? return NULL;
??? }
??? p->payload = NULL;
??? p->len = p->tot_len = size;
??? p->next = NULL;
??? p->flags = PBUF_FLAG_ROM;
??? break;
? default:
??? ASSERT("pbuf_alloc: erroneous flag", 0);
??? return NULL;
? }
? p->ref = 1;
? return p;
}?
總結(jié)
以上是生活随笔為你收集整理的关于lwip中pbuf_alloc()内存申请函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 探索C++的秘密之详解extern C
- 下一篇: lwIP ARP协议分析