嵌入式LwIP學(xué)習(xí)筆記之?dāng)?shù)據(jù)包管理2

一、其他數(shù)據(jù)包操作函數(shù)

本章接上篇《嵌入式LwIP學(xué)習(xí)筆記之?dāng)?shù)據(jù)包管理1》朝聋,繼續(xù)講解其他的數(shù)據(jù)包操作函數(shù)狮腿,

pbuf_realloc 函數(shù)、pbuf_header 函數(shù)脏榆、pbuf_take 函數(shù)的具體流程。

二台谍、pbuf_realloc 函數(shù)

pbuf_realloc 函數(shù)在相應(yīng) pbuf(鏈表)尾部釋放一定的空間须喂,將數(shù)據(jù)包 pbuf 中的數(shù)

據(jù)長度減少為某個長度值。對于 PBUF_RAM 類型的 pbuf趁蕊,函數(shù)將調(diào)用內(nèi)存堆管理中介紹到的 mem_realloc 函數(shù)坞生,釋放這些多余的空間;對于其他三種類型的 pbuf掷伙,該函數(shù)只是修改 pbuf 中的長度字段值是己,并不釋放對應(yīng)的內(nèi)存池空間。

/**

?* Shrink a pbuf chain to a desiredlength.

?*

?* @param p pbuf to shrink.

?* @param new_len desired new lengthof pbuf chain

?*

?* Depending on the desired length,the first few pbufs in a chain might

?* be skipped and left unchanged.The new last pbuf in the chain will be

?* resized, and any remaining pbufswill be freed.

?*

?* @note If the pbuf is ROM/REF,only the ->tot_len and ->len fields are adjusted.

?* @note May not be called on a packetqueue.

?*

?* @note Despite its name,pbuf_realloc cannot grow the size of a pbuf (chain).

?*/

//將數(shù)據(jù)鏈表pbuf的尾部釋放一定的空間任柜,以期獲得指定長度的pbuf

//p 需要釋放的數(shù)據(jù)鏈表pbuf

//new_len 釋放后的pbuf的數(shù)據(jù)長度

void pbuf_realloc(struct pbuf *p, u16_t new_len)

{

? struct pbuf *q;

? u16_t rem_len;????? /*用于指定當(dāng)前pbuf的剩余長度*/

? s32_t grow;


//無效值判斷赃泡,及故障信息打印

? LWIP_ASSERT("pbuf_realloc: p!= NULL", p != NULL);

? LWIP_ASSERT("pbuf_realloc:sane p->type", p->type == PBUF_POOL ||

????????????? p->type == PBUF_ROM||

????????????? p->type == PBUF_RAM||

????????????? p->type ==PBUF_REF);


? /* desired length larger thancurrent length? */

? if (new_len >= p->tot_len) {??? //新的pbuf數(shù)據(jù)長度應(yīng)在原總的數(shù)據(jù)長度內(nèi)

??? /* enlarging not yet supported*/

??? return;

? }


? grow = new_len - p->tot_len;? //獲取需要釋放的數(shù)據(jù)

? rem_len = new_len;?? //保留當(dāng)前應(yīng)該剩余的數(shù)據(jù)長度

? q = p;?????? //使用q指向數(shù)據(jù)鏈表的p的首地址

??//剩余數(shù)據(jù)的長度大于數(shù)據(jù)鏈表q的數(shù)據(jù)長度寒波,則進(jìn)入循環(huán)乘盼,否則說明已經(jīng)找到需要釋

//放數(shù)據(jù)的pbuf在鏈表中的位置

? while (rem_len > q->len) {??

??? rem_len -= q->len;?????? //剩余的長度減去當(dāng)前的pbuf的數(shù)據(jù)長度

??? /* decrease total lengthindicator */

??? LWIP_ASSERT("grow

??? q->tot_len += (u16_t)grow;?????? //減少總的數(shù)據(jù)長度

??? q = q->next;??????????????????? //指向數(shù)據(jù)鏈表中的下一個pbuf

??? LWIP_ASSERT("pbuf_realloc:q != NULL", q != NULL);//判斷q是否為NULL

? }


//執(zhí)行到這一步升熊,說明我們找到了要釋放數(shù)據(jù)的pbuf的位置

? //為PBUF_RAM類型時,釋放內(nèi)存空間绸栅,其他的類型级野,只是減少數(shù)據(jù)長度

? if ((q->type == PBUF_RAM)&& (rem_len != q->len)) {??

??? /* reallocate and adjust thelength of the pbuf that will be split */

??? q = (struct pbuf *)mem_trim(q,(u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);

??? LWIP_ASSERT("mem_trimreturned q == NULL", q != NULL);

? }

? /* adjust length fields for newlast pbuf */

? q->len = rem_len;? //最后一個pbuf的數(shù)據(jù)長度為最后的剩余長度

? q->tot_len = q->len; //最后一個pbuf的數(shù)據(jù)總長度為最后的剩余長度,因為后面沒有pbuf

? /*如果pbuf后還接有鏈表粹胯,則釋放掉*/

? if (q->next != NULL) {

??? /* free remaining pbufs in chain*/

??? pbuf_free(q->next);

? }

? /* q is last packet in chain */

? q->next = NULL;?? //數(shù)據(jù)釋放后蓖柔,應(yīng)置空

}

三、pbuf_header 函數(shù)

pbuf_header 函數(shù)用于調(diào)整 pbuf 的 payload 指針(向前或向后移動一定的字節(jié)數(shù))风纠,

在前面也說到過了况鸣,在 pbuf 的數(shù)據(jù)區(qū)前可能會預(yù)留一些協(xié)議首部空間,而pbuf 被創(chuàng)建時竹观,payload 指針是指向數(shù)據(jù)區(qū)的镐捧,為了實現(xiàn)對這些預(yù)留空間的操作,可以調(diào)用函數(shù)pbuf_header 使 payload 指針指向數(shù)據(jù)區(qū)前的首部字段臭增,這就為各層對數(shù)據(jù)包首部的操作提供了方便懂酱。當(dāng)然,進(jìn)行這個操作的時候誊抛,len和 tot_len 字段值也會隨之更新列牺。

/**

?*Adjusts the payload pointer to hide or reveal headers in the payload.

* @param p pbuf to change the header size.

?*@param header_size_increment Number of bytes to increment header size which

?*increases the size of the pbuf. New space is on the front.

*/

//函數(shù)功能:調(diào)整 pbuf 的 payload 指針,指向數(shù)據(jù)區(qū)或pbuf的數(shù)據(jù)區(qū)的首部字段

//pbuf 需要更改的數(shù)據(jù)表pbuf

//header_size_increment? 更改payload的指向位置拗窃,向前或者向后

u8_t pbuf_header(struct pbuf *p, s16_theader_size_increment)

{

?u16_t type;

? void*payload;?? //指向pbuf的數(shù)據(jù)區(qū)首地址

?u16_t increment_magnitude;? //描述指針的改變值


?LWIP_ASSERT("p != NULL", p != NULL);

//位置改變量為0瞎领,說明不要更改,返回

//數(shù)據(jù)區(qū)p為空随夸,則無數(shù)據(jù)可操作九默,返回?

if ((header_size_increment == 0) || (p == NULL)) {

???return 0;

? }


? if(header_size_increment < 0){ // header_size_increment小于0,表示向數(shù)據(jù)區(qū)的首部移動

???increment_magnitude = -header_size_increment;? //獲取該變量

??? /*Check that we aren't going to move off the end of the pbuf */

???LWIP_ERROR("increment_magnitude <= p->len",(increment_magnitude <= p->len), return 1;);

? }else {

???increment_magnitude = header_size_increment;

? }

? type= p->type;? //獲取pbuf的類型

?payload = p->payload;? //獲取數(shù)據(jù)區(qū)的首地址

? //為PBUF_RAM或PBUF_POOL類型

? if(type == PBUF_RAM || type == PBUF_POOL) {

??? /*set new payload pointer */

???p->payload = (u8_t *)p->payload - header_size_increment;? //設(shè)置新的payload指向地址

??? /*新的payload指向地址超出最大值*/

?? ?if ((u8_t *)p->payload < (u8_t *)p +SIZEOF_STRUCT_PBUF) {

?????LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,

???????("pbuf_header: failed as %p < %p (not enough space for newheader size)\n",

???????(void *)p->payload, (void *)(p + 1)));

?????/* restore old payload pointer */

?????p->payload = payload;?? //更新原來的payload到pbuf的payload

?????/* bail out unsuccesfully */

?????return 1;???? //返回失敗

??? }

? /*為PBUF_REF或PBUF_ROM等外部內(nèi)存*/

? }else if (type == PBUF_REF || type == PBUF_ROM) {

??? /*pbuf的payload指針不能向前移動逃魄,只能向增加的方向移動*/

??? if((header_size_increment < 0) && (increment_magnitude <=p->len)) {

?????p->payload = (u8_t *)p->payload - header_size_increment;? //增加payload的指向地址

??? }else {

????? /*指針不能向前移動荤西,所以返回失敗*/

?????return 1;??

??? }

? }else {

??? /*Unknown type */

???LWIP_ASSERT("bad pbuf type", 0);

???return 1;

? }

? /*modify pbuf length fields */

?p->len += header_size_increment;???//增加pbuf的數(shù)據(jù)區(qū)的數(shù)據(jù)長度

?p->tot_len += header_size_increment; //增加pbuf的數(shù)據(jù)區(qū)的數(shù)據(jù)總長度


?LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new%p (%"S16_F")\n", (void *)payload, (void *)p->payload,header_size_increment));

?return 0;?????? //返回移動指針成功

}

四、pbuf_take 函數(shù)

  pbuf_take 函數(shù)用于向 pbuf 的數(shù)據(jù)區(qū)域拷貝數(shù)據(jù)伍俘;pbuf_copy 函數(shù)用于將一個任何類型的 pbuf中的數(shù)據(jù)拷貝到一個 PBUF_RAM 類型的 pbuf 中邪锌。pbuf_chain 函數(shù)用于連接兩個 pbuf(鏈表)為一個 pbuf 鏈表;pbuf_ref 函數(shù)用于將 pbuf 中的 ref 值加 1癌瘾。

?/**

?* Copyapplication supplied data into a pbuf.

?* Thisfunction can only be used to copy the equivalent of buf->tot_len data.

?*

?* @param bufpbuf to fill with data

?* @paramdataptr application supplied data buffer

?* @param lenlength of the application supplied data buffer

?*

?* @returnERR_OK if successful, ERR_MEM if the pbuf is not big enough

?*/

//向pbuf的數(shù)據(jù)區(qū)拷貝指定長度的數(shù)據(jù)

//buf 數(shù)據(jù)鏈表buf

//len 拷貝的數(shù)據(jù)長度

//dataptr 拷貝數(shù)據(jù)后存入的緩存區(qū)

err_t pbuf_take(struct pbuf *buf, const void*dataptr, u16_t len)

{

? struct pbuf*p;?? //定義數(shù)據(jù)表pbuf

? u16_tbuf_copy_len; //每個pbuf中需要拷貝的數(shù)據(jù)長度

? u16_ttotal_copy_len = len;? //需要拷貝的總的數(shù)據(jù)長度

? u16_tcopied_total = 0;


?LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return0;);

?LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL),return 0;);


//數(shù)據(jù)有效性判斷

? if ((buf ==NULL) || (dataptr == NULL) || (buf->tot_len < len)) {

??? returnERR_ARG;

? }


? /* Notesome systems use byte copy if dataptr or one of the pbuf payload pointers areunaligned. */

//遍歷拷貝數(shù)據(jù)鏈表buf觅丰,直到拷貝完len的數(shù)據(jù)

? for(p =buf; total_copy_len != 0; p = p->next) {

???LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);

???buf_copy_len = total_copy_len;? //剩余需要拷貝的數(shù)據(jù)長度

??? if (buf_copy_len> p->len) {

????? /* thispbuf cannot hold all remaining data */

?????buf_copy_len = p->len;??? //本次需要從pbuf數(shù)據(jù)區(qū)中拷貝的數(shù)據(jù)長度

??? }

??? /*拷貝pbuf中的數(shù)據(jù)區(qū)到緩存區(qū)中*/

???MEMCPY(p->payload, &((char*)dataptr)[copied_total],buf_copy_len);

???total_copy_len -= buf_copy_len;?//更新還需要拷貝的數(shù)據(jù)長度

???copied_total += buf_copy_len;???//標(biāo)記已經(jīng)拷貝的數(shù)據(jù)長度

? }

?LWIP_ASSERT("did not copy all data", total_copy_len == 0&& copied_total == len);

? returnERR_OK;?? //返回數(shù)據(jù)拷貝成功

}





五、pbuf_fill_chksum函數(shù)


/**

?*Copies data into a single pbuf (*not* into a pbuf queue!) and updates

?*the checksum while copying

?*

?*@param p the pbuf to copy data into

?*@param start_offset offset of p->payload where to copy the data to

?*@param dataptr data to copy into the pbuf

?*@param len length of data to copy into the pbuf

?*@param chksum pointer to the checksum which is updated

?*@return ERR_OK if successful, another error if the data does not fit

?*????????within the (first) pbuf (no pbuf queues!)

?*/

err_t

pbuf_fill_chksum(struct pbuf *p, u16_tstart_offset, const void *dataptr,

???????????????? u16_t len, u16_t *chksum)

{

?u32_t acc;

?u16_t copy_chksum;

?char *dst_ptr;

?LWIP_ASSERT("p != NULL", p != NULL);

?LWIP_ASSERT("dataptr != NULL", dataptr != NULL);

? LWIP_ASSERT("chksum!= NULL", chksum != NULL);

?LWIP_ASSERT("len != 0", len != 0);


? if((start_offset >= p->len) || (start_offset + len > p->len)) {

???return ERR_ARG;

? }


?dst_ptr = ((char*)p->payload) + start_offset;?? //目的地址為數(shù)據(jù)區(qū)首地址 + 偏移地址

? //以目的地址為首地址拷貝指定長度len的數(shù)據(jù)到dataptr中

copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);?

? if((start_offset & 1) != 0) {? //若偏移地址為奇數(shù)妨退,需要補(bǔ)齊計算校驗和

???copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);

? }

? acc= *chksum;??? //獲取已有數(shù)據(jù)的校驗和?

? acc+= copy_chksum; //加上當(dāng)前新拷貝的數(shù)據(jù)的檢驗和

?*chksum = FOLD_U32T(acc);? //取校驗和的反碼

?return ERR_OK;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妇萄,一起剝皮案震驚了整個濱河市蜕企,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冠句,老刑警劉巖轻掩,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懦底,居然都是意外死亡唇牧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門聚唐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丐重,“玉大人,你說我怎么就攤上這事杆查“绲耄” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵亲桦,是天一觀的道長崖蜜。 經(jīng)常有香客問我,道長烙肺,這世上最難降的妖魔是什么纳猪? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桃笙,結(jié)果婚禮上氏堤,老公的妹妹穿的比我還像新娘。我一直安慰自己搏明,他們只是感情好鼠锈,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著星著,像睡著了一般购笆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虚循,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天同欠,我揣著相機(jī)與錄音,去河邊找鬼横缔。 笑死铺遂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茎刚。 我是一名探鬼主播襟锐,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼膛锭!你這毒婦竟也來了粮坞?” 一聲冷哼從身側(cè)響起蚊荣,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莫杈,沒想到半個月后互例,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡姓迅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年敲霍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丁存。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柴我,靈堂內(nèi)的尸體忽然破棺而出解寝,到底是詐尸還是另有隱情,我是刑警寧澤艘儒,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布聋伦,位于F島的核電站,受9級特大地震影響界睁,放射性物質(zhì)發(fā)生泄漏觉增。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一翻斟、第九天 我趴在偏房一處隱蔽的房頂上張望逾礁。 院中可真熱鬧,春花似錦访惜、人聲如沸嘹履。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砾嫉。三九已至,卻和暖如春窒篱,著一層夾襖步出監(jiān)牢的瞬間焕刮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工墙杯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留配并,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓霍转,卻偏偏與公主長得像荐绝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子避消,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容