乙個簡易的基於tun tap裝置的協議棧

2021-08-01 17:38:06 字數 3573 閱讀 9828

從上一次準備開坑開幹,到現在初步完成,已經過了乙個半月了,造乙個輪子確實是非常耗時耗力的一件事情,但是不管怎樣,我終究還是做完了,完成了當初的目標,雖然**還有非常多值得改進的地方,但是現在已經不是很著急了,一步一步慢慢來吧,接下來的一段時間裡,我會將這個協議棧背後涉及到的一些知識貼成博文,但是我不會去講實現,沒有任何意義.自己去讀吧,**非常簡潔.

接下來一直到畢業,估計都很難像這個學期一樣,花上這樣一大段的時間來造輪子了,造乙個輪子代價實在昂貴.真心的.接下來的幾個月準備複習,找工作了.複習演算法的時候,順帶將之前的那個stl的坑填掉.

下面是乙個多月以來的紀要.

基本上,我想要的功能都已經完成了,接下來需要做的事情就是修修補補.還有,需要寫博文記錄一下到底幹了什麼以及怎麼去幹.還是很開心的.

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

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

我發現,用c語言程式設計的話,記憶體檢測工具必不可少,今天多虧了valgrind,不然真的找不到**記憶體出現了問題.

現在已經基本上對這部分**非常熟悉了,所以修改起來也得心應手,很爽.

昨天一天改了很多**,新增了很多**,刪除了很多**,總之關於tcp部分的工作已經做得差不多了.我覺得努力一把,在5月底的時候完成這個簡陋的該死的協議棧,還是有望的.

最近突然有一項任務要完成,抽不出太多時間來弄協議棧啦,所以,協議棧的事情可能要延遲了,應該不會超過乙個月吧,乙個月後,我會繼續來幹的.

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

今天改進和精簡了一點**,發現要實現乙個簡易的posix標準的網路函式,如bind,accept,listen等,還有一大段**要寫,而這,真是樂趣之所在,鬼知道還有多久能夠弄完這個協議棧,不過,在讀協議棧的實現和精簡協議棧的過程中,unp的不少內容,現在已經能夠讀懂了,記住,是真正懂了,原來unp上一些東西我壓根就不知道在講什麼,包括那些高階的部分.

撥開雲霧見青天.終於除錯正確了,tap裝置正常工作.今天是非常非常重要的一天,因為今天終於將苦大仇深的**除錯成功了.

流年不利,我發現用tun/tap實現協議棧,貌似沒有很好的除錯方法,特別蛋疼.或許是我還沒有找到一種好的除錯辦法吧,今天嘗試了很多,試圖讓實現的這個協議棧連線上外網,但是失敗了,老是失敗,我要重新理解一下,到底什麼才是tun/tap.

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

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

昨天遇到的問題是,一旦我使用malloc,然後呼叫free,類似於這樣:

void *address = malloc(42);

free(address); // **沒有任何問題

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

free(): invalid next size (fast):
是不是非常詭異,我昨天除錯了乙個晚上,愣是沒有找出原因,今天想了一點小辦法,終於乾掉了這個bug.

事實上,上面的**並沒有錯,真正的錯誤原因在於,我在呼叫上面的**之前,已經在別的地方用malloc分配了一塊記憶體,然後一不小心,在操縱這塊記憶體的時候,往越界的位址寫入了一些資料,此後,我呼叫malloc不會出問題,但是呼叫free有很大的機率程式會立即崩潰掉,同時會爆出上面的錯誤.

個人懷疑是我越界寫入的那些資料覆蓋了malloc分配記憶體時記錄的一些關於記憶體塊大小的資訊,使得呼叫free的時候無法找到這些資訊,也就無從**記憶體,導致出錯.**不離十啦.

我這裡試圖還原一下當時的場景:

#define eth_hdr_len 10

#define ip_hdr_len 20

#define tcp_hdr_len 20

struct sk_buff ;

// skb_reserve丟棄掉前len個資料,或者說是保留前面長度為len的資料

void *

skb_reserve(struct sk_buff *skb, unsigned

int len)

void

free_skb(struct sk_buff *skb)

struct sk_buff *

alloc_skb(unsigned

int size)

static

struct sk_buff *

tcp_alloc_skb(int optlen, int size)

void manipulate()

上面的問題看似很簡單,或許你會拍一拍胸膛,我絕對不會犯這種錯誤,但是真的當**多了之後,估計你就不會說這樣的話了,如果嘗試過除錯了7,8個小時,連bug的半點頭緒都找不到這種絕望的話,估計你也會說–c語言呀,指標這個東西,真的需要特別小心.

原來沒有想到的乙個問題是,應用程式究竟是如何同協議棧進行交流的,現在明白了,使用的是ipc機制,從昨天一直到現在,終於將unix本機通訊的程式調通了.接下來就只要將三次握手除錯成功就差不多了.

媽蛋,c語言的記憶體分配真是個大問題,調了半天不知道錯在**,先malloc,然後free,立馬出錯,這玩意和玄學差不多.

學習網路程式設計最好的方式,的確是摸透乙個tcp ip協議棧的實現.讀level-ip,結合tcp ip詳解卷,再配合上手實驗,個人感覺收穫非常大,畢竟看到了抽象背後的東西.

越是讀源**實現,我越是覺得,真正要在linux做系統程式設計的話,對作業系統原理的理解是必不可少的,最好的作業系統教程,不是書本,而是原始碼.當然,書本比不可少,它記錄了一些原理性的東西,但是原始碼會使我們對一些東西明白得更加透徹.xv6,ucore都是不錯的教材.

基於koajs的乙個簡易Excel生成服務

運營人員需要將後台的 匯出成excel,由於後端的同學忙於其他事情,想著是不是可以自己做乙個服務來生成。了解到有node xlsx這樣的工具以後就開工了。後台選用了koa,因為非常輕巧,寫個介面只需要幾行 this.body hello console.log listening on port 3...

乙個簡易的shell

shell本質上就是將程序程式替換 替換原理 用fork建立子程序後執行的是和父程序相同的程式 但有可能執行不同的 分支 子程序往往要呼叫一種exec函式以執行另乙個程式。當程序呼叫一種exec函式時,該程序的使用者空間 和資料完全被新程式替換,從新程式的啟動例程開始執行。呼叫exec並不建立新程序...

乙個簡易的SocketIM

今天做了乙個簡易的socketim的小示例。基本思想是開啟兩個winform,每個winform既充當伺服器也充當客戶端。乙個監聽8000埠,另外乙個監聽8001埠,兩個winform接收到資訊之後將資訊顯示在form的控制項上。這篇記錄一下碼code中學到的一些東西。net的socket庫已經將c...