TCP/IP協(xié)議棧是網(wǎng)絡(luò)中廣泛使用的事實(shí)網(wǎng)絡(luò)通信標(biāo)準(zhǔn)。最初的TCP實(shí)現(xiàn)源自4.4BSD lite,在Linux興起后,也不可避免得支持它。但Linux的實(shí)現(xiàn)自成體系,僅與傳統(tǒng)實(shí)現(xiàn)保持接口上的兼容,下面我們將針對源碼級的實(shí)現(xiàn),來分析一下兩者的異同。但是,對于Linux和FreeBSD這樣優(yōu)秀的系統(tǒng)來說,已經(jīng)無所謂何優(yōu)何劣,有的僅僅是實(shí)現(xiàn)策略與側(cè)重點(diǎn)上的不同而已。
從進(jìn)程的角度上講,可以調(diào)用send,sendto,sendmsg來發(fā)送一段數(shù)據(jù),來可以使用文件系統(tǒng)中的write和writev來發(fā)送數(shù)據(jù)。同理,接收數(shù)據(jù)可以使用相應(yīng)的recv,recvmsg,recvfrom,也可以使用文件系統(tǒng)提供的read,readv來接收一段數(shù)據(jù)。對于接收來說,這是異步進(jìn)行的,也就是說,這是中斷驅(qū)動的,在以后的分析中,我們要注意這點(diǎn)。為簡單起見,同時不失一般性,我們將分析TCP協(xié)議的輸入輸出全過程,并以已對LINUX及FreeBSD的實(shí)現(xiàn)作一對比。
首先我們來看FreeBSD上的協(xié)議實(shí)現(xiàn),這也是最正統(tǒng)的實(shí)現(xiàn)。下面是完整的輸入輸出路徑。
首先來看左邊的輸出,不管應(yīng)用程序調(diào)用哪個輸出函數(shù),最終都要調(diào)用sosend來完成輸出。Sosend將從用戶空間把數(shù)據(jù)復(fù)制進(jìn)內(nèi)核管理的m_buf數(shù)據(jù)結(jié)構(gòu),m_buf是FreeBSD的TCP實(shí)現(xiàn)使用的數(shù)據(jù)緩沖結(jié)構(gòu)。在sosend完成數(shù)據(jù)復(fù)制后,將調(diào)用TCP的輸出函數(shù),tcp_output要做的事情是分配一個新的m_buf來保存tcp頭,并計(jì)算相應(yīng)的數(shù)據(jù)校驗(yàn)碼,在下一步的ip_output中,同樣也要進(jìn)行數(shù)據(jù)校驗(yàn)工作,并進(jìn)行數(shù)據(jù)路由選擇。最終ether_output將通過if_start來調(diào)用具體的硬件驅(qū)動程序來完成數(shù)據(jù)發(fā)送。在某個網(wǎng)卡的驅(qū)動中,ex_start將負(fù)責(zé)將數(shù)據(jù)從內(nèi)核的m_buf緩沖復(fù)制進(jìn)硬件自己的緩沖區(qū),以完成數(shù)據(jù)發(fā)送工作。在這整個過程中,數(shù)據(jù)被復(fù)制兩次,并且也被遍歷兩次(計(jì)算校驗(yàn)碼),這也是主要的影響效率的地方。