2.3 接收端丟失確認(rèn)及滑動(dòng)窗口
發(fā)送UDP報(bào)文時(shí)在自定義的內(nèi)部數(shù)據(jù)頭中加入所發(fā)送數(shù)據(jù)的序號(hào),接收端收到后發(fā)送確認(rèn)信息,如果發(fā)送方在規(guī)定時(shí)間內(nèi)沒有收到確認(rèn)信息,則認(rèn)為該包丟失,會(huì)連同原包的序號(hào)重新發(fā)送。
滑動(dòng)窗口的目的主要是為了實(shí)現(xiàn)流量控制,防止擁塞。每個(gè)發(fā)送方維護(hù)一個(gè)重發(fā)隊(duì)列,保存著一定數(shù)量的發(fā)送而沒被確認(rèn)的報(bào)文,該隊(duì)列剩余空間的大小可以限制應(yīng)用部分發(fā)包的速率。由于UDP協(xié)議是基于消息的傳輸協(xié)議而非基于流的,因此不必考慮發(fā)送端可以接收多少數(shù)據(jù),只需知道能否接收數(shù)據(jù)即可。
總之,采用UDP傳輸控制方式主要考慮到其傳輸簡(jiǎn)單快速、額外開銷較小的特點(diǎn),但這是以犧牲一定的可靠性為前提的,因此必須在應(yīng)用程序中增加可靠性保護(hù)機(jī)制。在實(shí)際應(yīng)用中證明上述方法可靠高效,能夠維護(hù)內(nèi)部通信有序、快速的數(shù)據(jù)傳輸。
3 基于多用戶的用戶接入管理
在Linux操作系統(tǒng)下,系統(tǒng)把設(shè)備映射為一個(gè)特殊的設(shè)備文件,用戶程序可以像對(duì)其他文件一樣對(duì)該設(shè)備文件進(jìn)行讀寫操作。虛擬驅(qū)動(dòng)模塊運(yùn)行在Linux操作系統(tǒng)下,模擬從處理單元上的接口單元,形成收發(fā)協(xié)議報(bào)文功能和數(shù)量與此一致的硬件抽象層虛擬接口單元。因此,每個(gè)實(shí)際的接口單元都在內(nèi)核中對(duì)應(yīng)一個(gè)注冊(cè)的虛擬設(shè)備,以便于上層控制軟件對(duì)數(shù)據(jù)平面的管理與數(shù)據(jù)交互。
3.1 多用戶虛擬設(shè)備驅(qū)動(dòng)程序的動(dòng)態(tài)加載
虛擬驅(qū)動(dòng)在內(nèi)核中的功能通過(guò)動(dòng)態(tài)加載方式實(shí)現(xiàn)。通常的動(dòng)態(tài)加載方式是將驅(qū)動(dòng)程序作為一個(gè)整體模塊,在需要時(shí)再加入內(nèi)核[6];由于多用戶接入方式使得在某一時(shí)刻內(nèi)核中注冊(cè)的接口單元數(shù)量不確定,如果實(shí)施一次性加載會(huì)冗余太多,不利于資源的有效利用。因此,在內(nèi)核中加載一個(gè)基本模塊的前提下,實(shí)現(xiàn)各虛擬設(shè)備的動(dòng)態(tài)加載過(guò)程,達(dá)到以一個(gè)基本的虛擬設(shè)備控制多個(gè)設(shè)備驅(qū)動(dòng)模塊的功能。
如圖4所示,對(duì)虛擬驅(qū)動(dòng)設(shè)備的控制由內(nèi)部通信模塊與設(shè)備管理模塊共同完成。設(shè)備管理模塊通過(guò)內(nèi)部通信模塊下達(dá)加載、卸載虛擬驅(qū)動(dòng)的命令,通過(guò)內(nèi)部通信模塊與虛擬驅(qū)動(dòng)的控制通道進(jìn)行。內(nèi)部通信模塊通過(guò)調(diào)用ioctl()采用不同的命令字完成對(duì)虛擬驅(qū)動(dòng)模塊的控制過(guò)程。

圖4模塊動(dòng)態(tài)加載過(guò)程
基本驅(qū)動(dòng)模塊的加載采用通常的驅(qū)動(dòng)模塊加載方式,即調(diào)用module_init()函數(shù)進(jìn)行基本模塊的初始化及在內(nèi)核中的注冊(cè)過(guò)程。以該基本驅(qū)動(dòng)模塊為基礎(chǔ),當(dāng)內(nèi)部通信模塊收到加載某個(gè)用戶設(shè)備接口的命令后,通過(guò)調(diào)用該基本模塊的Base_ioctl()在內(nèi)核中注冊(cè)一個(gè)新的驅(qū)動(dòng)設(shè)備,該注冊(cè)設(shè)備才是與實(shí)際接口單元相對(duì)應(yīng)的虛擬驅(qū)動(dòng)模塊,應(yīng)用程序?qū)τ脩粼O(shè)備數(shù)據(jù)的讀寫都是通過(guò)這些注冊(cè)的接口設(shè)備而非基本設(shè)備提供的標(biāo)準(zhǔn)函數(shù)進(jìn)行。這樣的動(dòng)態(tài)加載過(guò)程使得當(dāng)沒有設(shè)備加載時(shí)在內(nèi)核中只存在一個(gè)基本的虛擬驅(qū)動(dòng)模塊,只有需要注冊(cè)的用戶才將其對(duì)應(yīng)的設(shè)備接口的虛擬驅(qū)動(dòng)模塊加載到內(nèi)核中,從而減少系統(tǒng)冗余,便于管理。
各用戶接口單元與虛擬驅(qū)動(dòng)的數(shù)據(jù)交互通過(guò)內(nèi)部通信模塊與虛擬驅(qū)動(dòng)的數(shù)據(jù)通道進(jìn)行,所對(duì)應(yīng)的系統(tǒng)調(diào)用為該注冊(cè)設(shè)備的dev_ioctl()。在該功能函數(shù)中,實(shí)現(xiàn)用戶空間與內(nèi)核空間的數(shù)據(jù)交互。
3.2 對(duì)多用戶接口設(shè)備虛擬驅(qū)動(dòng)的管理
為實(shí)現(xiàn)內(nèi)核虛擬驅(qū)動(dòng)模塊與實(shí)際接口單元的一一對(duì)應(yīng),必須解決各驅(qū)動(dòng)模塊的命名原則問(wèn)題。將每個(gè)實(shí)際接口單元在接入段拓?fù)渲械奈恢迷O(shè)置為不同的參數(shù),在內(nèi)部通信中這些參數(shù)作為傳輸數(shù)據(jù)的報(bào)頭信息出現(xiàn),根據(jù)它們可以生成一個(gè)唯一的字符串作為對(duì)應(yīng)該接口單元的虛擬驅(qū)動(dòng)設(shè)備名稱,而且根據(jù)設(shè)備名稱亦可還原出實(shí)際接口單元的拓?fù)湫畔?以供內(nèi)部通信使用。在內(nèi)核中維護(hù)一個(gè)由各注冊(cè)設(shè)備名稱所組成的動(dòng)態(tài)鏈表,每個(gè)鏈表節(jié)點(diǎn)維護(hù)一個(gè)收發(fā)報(bào)文的數(shù)據(jù)隊(duì)列,虛擬驅(qū)動(dòng)與其他模塊的數(shù)據(jù)交互都通過(guò)該鏈表進(jìn)行。
3.3 對(duì)虛擬設(shè)備數(shù)據(jù)讀寫過(guò)程





