協(xié)議棧紀(jì)要

5月27日

基本上,我想要的功能都已經(jīng)完成了,接下來需要做的事情就是修修補補.還有,需要寫博文記錄一下到底干了什么以及怎么去干.

5月24日

c語言最讓人頭疼的事情是指針,真的,一旦指針出了一點兒故障,你都找不到原因.我跟你說.

今天的問題最終還是解決了,原因很簡單,是我的指針越界了,然后我往越界的地方寫入了一點東西,今天這個玩意折騰了我一個下午.郁悶.

5月21日

現(xiàn)在已經(jīng)基本上對這部分代碼非常熟悉了,所以修改起來也得心應(yīng)手,很爽.

5月20日

昨天一天改了很多代碼,添加了很多代碼,刪除了很多代碼,總之關(guān)于tcp部分的工作已經(jīng)做得差不多了.我覺得努力一把,在5月底的時候完成這個簡陋的該死的協(xié)議棧,還是有望的.

5月16日

最近突然有一項任務(wù)要完成,抽不出太多時間來弄協(xié)議棧啦,所以,協(xié)議棧的事情可能要延遲了,應(yīng)該不會超過一個月吧,一個月后,我會繼續(xù)來干的.

5月14日

造一個輪子代價昂貴,我太想吐槽這一點了,直到今天,我感覺還有非常多的事情要干,不知道一個簡單的協(xié)議棧什么時候才能搞得完.

5月12日

今天改進和精簡了一點代碼,發(fā)現(xiàn)要實現(xiàn)一個簡易的posix標(biāo)準(zhǔn)的網(wǎng)絡(luò)函數(shù),如bind, accept,listen等,還有一大段代碼要寫,而這,真是樂趣之所在,鬼知道還有多久能夠弄完這個協(xié)議棧,不過,在讀協(xié)議棧的實現(xiàn)和精簡協(xié)議棧的過程中,unp的不少內(nèi)容,現(xiàn)在已經(jīng)能夠讀懂了,記住,是真正懂了,原來unp上一些東西我壓根就不知道在講什么,包括那些高級的部分.

5月9日

撥開云霧見青天.終于調(diào)試正確了,tap設(shè)備正常工作.今天是非常非常重要的一天,因為今天終于將苦大仇深的代碼調(diào)試成功了.

5月8日

最近被tun/tap這個概念折磨得很慘,使用百度搜索了一下這個玩意,沒有一篇文章將這個東西完全講清楚了,自己對著書,對著自己的想法,鼓搗了很久,依舊不得法,我接近放棄的時候,明智地用了一下谷歌搜索,很幸運,搜到了幾篇文章,將tun/tap這個概念講清楚了,接下來的事情就好辦了.

5月6日

流年不利,我發(fā)現(xiàn)用tun/tap實現(xiàn)協(xié)議棧,貌似沒有很好的調(diào)試方法,特別蛋疼.或許是我還沒有找到一種好的調(diào)試辦法吧,今天嘗試了很多,試圖讓實現(xiàn)的這個協(xié)議棧連接上外網(wǎng),但是失敗了,老是失敗,我要重新理解一下,到底什么才是tun/tap.

大概能花在這個協(xié)議棧上的時間,只能有1個月啦,6月份開始,要立馬刷題了.希望最近幾天能夠找到一種好的方法來將它調(diào)試成功.

5月5日

廢了好大的勁,終于將昨天那個malloc,free的問題給解決了.這里我稍微記錄一下思路,以便給將來引以為戒.

昨天遇到的問題是,一旦我使用malloc,然后調(diào)用free,類似于這樣:

void *address = malloc(42);
free(address);  // 代碼沒有任何問題

立馬就報類似于這樣的錯誤,同時程序立馬崩潰:

free(): invalid next size (fast):

是不是非常詭異,我昨天調(diào)試了一個晚上,愣是沒有找出原因,今天想了一點小辦法,終于干掉了這個bug.

事實上,上面的代碼并沒有錯,真正的錯誤原因在于,我在調(diào)用上面的代碼之前,已經(jīng)在別的地方用malloc分配了一塊內(nèi)存,然后一不小心,在操縱這塊內(nèi)存的時候,往越界的地址寫入了一些數(shù)據(jù),此后,我調(diào)用malloc不會出問題,但是調(diào)用free有很大的幾率程序會立即崩潰掉,同時會爆出上面的錯誤.

個人懷疑是我越界寫入的那些數(shù)據(jù)覆蓋了malloc分配內(nèi)存時記錄的一些關(guān)于內(nèi)存塊大小的信息,使得調(diào)用free的時候無法找到這些信息,也就無從回收內(nèi)存,導(dǎo)致出錯.八九不離十啦.

我這里試圖還原一下當(dāng)時的場景:

#define ETH_HDR_LEN 10
#define IP_HDR_LEN 20
#define TCP_HDR_LEN 20

struct sk_buff {
    ...
    uint32_t dlen;          // 數(shù)據(jù)的大小,不包含頭部(以太網(wǎng),ip,tcp頭部)
    uint8_t *end;
    uint8_t *head;
    uint8_t *data;
    uint8_t *payload;
};

// skb_reserve丟棄掉前l(fā)en個數(shù)據(jù),或者說是保留前面長度為len的數(shù)據(jù)
void *
skb_reserve(struct sk_buff *skb, unsigned int len)
{
    skb->data += len;
    return skb->data;
}


void 
free_skb(struct sk_buff *skb)
{
    free(skb->head);
    free(skb);
}

struct sk_buff *
alloc_skb(unsigned int size)
{
    struct sk_buff *skb = malloc(sizeof(struct sk_buff));
    memset(skb, 0, sizeof(struct sk_buff));
    skb->data = malloc(size);    // 記錄下數(shù)據(jù)
    memset(skb->data, 0, size);

    skb->refcnt = 0;
    skb->head = skb->data;       // 數(shù)據(jù)開始的地方
    skb->end = skb->data + size; // 數(shù)據(jù)結(jié)束的地方
    list_init(&skb->list);
    return skb;
}

static struct sk_buff *
tcp_alloc_skb(int optlen, int size)
{
    // optlen表示tcp首部選項的大小
    // 這里要特別注意一下,因為忘記了TCP_HDR_LEN導(dǎo)致出錯
    // ===============================================
    int reserved = ETH_HDR_LEN + IP_HDR_LEN + /*TCP_HDR_LEN +*/ optlen + size; // 如果這里丟了一個TCP_HDR_LEN
    struct sk_buff *skb = alloc_skb(reserved);

    skb_reserve(skb, reserved); // skb->data部分留出reserved個字節(jié)
    skb->dlen = size;   // dlen表示數(shù)據(jù)的大小
    return skb;
}

void manipulate()
{
    struct sk_buff *skb = tcp_alloc_skb(0, 0);
    // 因為optlen和size都為0
    // 用一個tcphdr的結(jié)構(gòu)的指針tcp獲取skb中的tcp頭部部分,并填入數(shù)據(jù),其實在這里就越界了.
    ...
    // 用一個iphdr的結(jié)構(gòu)的指針ip獲取skb中關(guān)于ip頭部部分,填入數(shù)據(jù)
    ...
    // 用一個ethhdr結(jié)構(gòu)的指針eth獲取skb中關(guān)于以太網(wǎng)頭部部分,填入數(shù)據(jù)
    // 用一副示意圖表示如下,其實在第一步,tcp就指向了不屬于自己的內(nèi)存的首部,對其進行填充之后
    // 當(dāng)時沒有任何問題,但是到了free_skb的時候,立馬出錯,我懷疑malloc函數(shù)將內(nèi)存塊的信息恰好填
    // 入到了tcphdr那一部分
    /*
            |-------------------|   <--- skb->head, eth
            |     ethhdr       |
            |-------------------|   <--- iphdr, ip  
            |     iphdr     |       
            |                  |
            |-------------------|   <--- skb->end, tcp
            |     tcphdr       |     bad memory 
            |                  |    
    */
    
    free_skb(skb); // 立馬出錯,因為在不屬于你的內(nèi)存部分寫入了數(shù)據(jù)
}

上面的問題看似很簡單,或許你會拍一拍胸膛,我絕對不會犯這種錯誤,但是真的當(dāng)代碼多了之后,估計你就不會說這樣的話了,如果嘗試過調(diào)試了7,8個小時,連bug的半點頭緒都找不到這種絕望的話,估計你也會說--c語言呀,指針這個東西,真的需要特別小心.

5月4日

原來沒有想到的一個問題是,應(yīng)用程序究竟是如何同協(xié)議棧進行交流的,現(xiàn)在明白了,使用的是IPC機制,從昨天一直到現(xiàn)在,終于將unix本機通信的程序調(diào)通了.接下來就只要將三次握手調(diào)試成功就差不多了.

媽蛋,c語言的內(nèi)存分配真是個大問題,調(diào)了半天不知道錯在哪里,先malloc,然后free,立馬出錯,這玩意和玄學(xué)差不多.

5月3日

學(xué)習(xí)網(wǎng)絡(luò)編程最好的方式,的確是摸透一個TCP IP協(xié)議棧的實現(xiàn).讀level-ip,結(jié)合tcp ip詳解卷,再配合上手實驗,個人感覺收獲非常大,畢竟看到了抽象背后的東西.

越是讀源代碼實現(xiàn),我越是覺得,真正要在linux做系統(tǒng)編程的話,對操作系統(tǒng)原理的理解是必不可少的,最好的操作系統(tǒng)教程,不是書本,而是源碼.當(dāng)然,書本比不可少,它記錄了一些原理性的東西,但是源碼會使我們對一些東西明白得更加透徹.xv6, ucore都是不錯的教材.

=======================
這篇文章什么也不干,我就是想記錄一下自己讀tcp ip協(xié)議棧的實現(xiàn),自己的一點感想.僅此而已.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宠蚂,隨后出現(xiàn)的幾起案子店雅,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棚辽,死亡現(xiàn)場離奇詭異兢孝,居然都是意外死亡,警方通過查閱死者的電腦和手機睬捶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門黔宛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人擒贸,你說我怎么就攤上這事臀晃。” “怎么了介劫?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵徽惋,是天一觀的道長。 經(jīng)常有香客問我座韵,道長险绘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任誉碴,我火速辦了婚禮宦棺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘黔帕。我一直安慰自己代咸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布成黄。 她就那樣靜靜地躺著呐芥,像睡著了一般逻杖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上思瘟,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天荸百,我揣著相機與錄音,去河邊找鬼潮太。 笑死管搪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铡买。 我是一名探鬼主播更鲁,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奇钞!你這毒婦竟也來了澡为?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤景埃,失蹤者是張志新(化名)和其女友劉穎媒至,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谷徙,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡拒啰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了完慧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谋旦。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屈尼,靈堂內(nèi)的尸體忽然破棺而出册着,到底是詐尸還是另有隱情,我是刑警寧澤脾歧,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布甲捏,位于F島的核電站,受9級特大地震影響鞭执,放射性物質(zhì)發(fā)生泄漏司顿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一兄纺、第九天 我趴在偏房一處隱蔽的房頂上張望免猾。 院中可真熱鬧,春花似錦囤热、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锨苏。三九已至,卻和暖如春棺聊,著一層夾襖步出監(jiān)牢的瞬間伞租,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工限佩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留葵诈,地道東北人。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓祟同,卻偏偏與公主長得像作喘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晕城,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,318評論 25 707
  • 1.OC里用到集合類是什么泞坦? 基本類型為:NSArray,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,379評論 0 3
  • 每天都奔跑著 去遇見你 祈禱著 人潮 讓我們相擁
    leahsu閱讀 243評論 0 0
  • 何為目的砖顷?行動和努力最終要達到的境界贰锁。做任何事帶著目的去做,事半功倍滤蝠,達到或超越自己所想的效果豌熄。 知識萃取第二...
    icecream_29a4閱讀 238評論 2 0
  • 親愛的CC:你好! 不久前物咳,給你買了小天才電話手表锣险,專門給你挑選了手機號碼。使用了一陣子所森,挺方便囱持,不過,很快被老師...
    Leice閱讀 227評論 0 1