999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

Linux內核的Go語言實現研究

2021-07-06 02:10:20柴艷娜
計算機技術與發展 2021年6期
關鍵詞:語言

柴艷娜

(長安大學 信息與網絡管理處,陜西 西安 710064)

1 概 述

計算機是現代日常生活的一種必需品,其高效可靠的運行需要依賴于一套穩健無缺陷(bug-free)的操作系統。現代操作系統都會使用內核(kernel)來對硬件進行管理,因此可以說內核的安全穩定決定了人們與計算機相處的體驗。內核中的缺陷(bug)將可能使用戶的應用程序甚至操作系統本身變得不可靠[1]。

內核是用戶和應用程序與計算機硬件之間的橋梁,內核管理各種系統資源,包括內存和硬盤空間,并且處理CPU處理程序的調度。它也提供對輸入輸出設備和網絡的訪問。應用程序運行在內核之上,通過內核的系統調用從而使用到內核的功能。

1.1 現代內核的問題

大多數成熟的操作系統內核都是用C語言實現的。C語言因為允許高度控制內存使用以及其他如可與匯編語言互操作等低級程序操作特性,成為最受歡迎的內核語言[2]。這種高度的自由也會付出一些代價,比如內存釋放兩遍的錯誤、數組越界的錯誤以及死鎖[3]。同時它也不能防止數據類型的錯誤解析,保證不了類型的安全性。

隨著計算機多處理器以及多核處理器的增加,如何高效地利用多線程是評價內核優秀與否的一個有力因素。C語言實現的內核不能輕易地全面發揮多核的性能,因為C語言本身沒有涵蓋現代處理器的特性,C中的線程(thread)對內存和CPU來說都是很昂貴的一筆開銷,而線程之間的同步機制則更復雜,所以內核需要大費周章地實現一套機制來充分調動多核計算機的全部性能[4]。

如果用Java,Go等高級語言來開發內核,則可能會規避掉很多上述問題,比如許多高級語言提供了數組越界檢查和內存垃圾回收機制。然而,通常來說高級語言開發的程序會比C語言的慢,有時候由于代碼解釋、自動內存管理、垃圾回收等特性,會帶來很大的系統開銷。同時,高級語言很難操作匯編語言,因此可能很難滿足內核的底層任務調用。

1.2 現有社區項目

當下社區中有很多用高級語言實現內核的嘗試,諸多原因導致了它們沒有一個被廣泛采用。

Mirage是一個Linux基金會項目,致力于將Web應用變成一個運行在Xen虛擬機下的獨立的專屬精簡內核(Unikernel),它包含一個用OCaml開發的內核子系統的早期實現。因為它是為專屬內核(單用戶單進程,大多運行于虛擬機中)開發的,所以不能滿足大多數普通用戶的需求。另外,也不能在多核上并行,因為它本來就是為單進程運行而設計的。

Pycorn是一個用Python開發的操作系統,目前只兼容16位ARM微處理器。因為Python是一門解釋型語言,Pycorn實際運行十分慢,性能不是該項目的目標。因此它從未被廣泛使用過。

1.3 內核子系統

因為實現一個完整的內核是一項巨大的工程,所以該文代之以實現一個內核子系統,即網絡堆棧子系統,來進行相應的研究工作。網絡堆棧(network stack)是任何內核必須有的特性,網絡堆棧的功能和性能可以容易地比較和測試,因此是個比較理想的可用于研究的子系統。

1.4 Go語言

該文用Go語言實現內核子系統,用于研究用高級語言開發內核的相對優勢。之所以選擇Go是因為語言本身自帶的優秀的CSP并發模型(concurrent sequential processes)[4-6]。CSP模型將復雜任務解構成更小的、更加可管理的子任務。這些子任務都能被單個進程所處理,進程之間彼此保持通信,共同完成原始的復雜任務。

CSP模型的目標是幫助程序員設計,實現和驗證復雜的計算機系統,這是十分重要的,特別是要設計一個如內核般復雜的軟件。Go提供了線程安全(thread-safe)方式的CSP模型,Go語言的線程即協程(go-routines),同步的通信構造即通道(channel)[7]。Go語言運行時自動根據計算機的物理內核數量來管理調度協程。CSP模型能讓人很容易地使用計算機所有內核,同時改善代碼的可讀性,使得更簡單地進行調試和減少產生的缺陷。網絡堆棧很自然地可以被劃分成多個子任務去運行,可以充分利用Go協程去動態調度高效利用所有可用物理內核[8]。

CSP模型只在垃圾回收語言里有可行性,Go提供了必要的垃圾回收。Go是一門強類型語言,能減少一大類錯誤,包括錯誤類型轉換,內存釋放兩遍,對象釋放后再使用等。Go的延遲聲明(defer statement)允許在函數結束時更方便地清理,減少那些疏于管理的資源導致死鎖的可能性。

1.5 研究目標

Go和CSP模型的優勢可能伴隨著某種代價,比如垃圾回收有性能花銷并導致運行時的短暫暫停。另外,多核的使用,將帶來昂貴的內核間通信。該文的目標是評估Go帶來的收益是否能蓋過性能損失帶來的劣勢。

2 實 現

該文實現的獨立網絡堆棧(項目代號NStack)是建立在Tap虛擬網卡的基礎上。為了功能完整,所有基礎網絡協議,包括以太網(Ethernet),ARP,IPv4,ICMP,UDP和TCP,都被實現。為確保性能不受影響,延遲(latency)和吞吐量(through-out)會被測試,并與C語言實現的網絡堆棧進行比較。

2.1 Tap接口

Tap接口即一種虛擬網絡接口(虛擬網卡),用軟件來模仿實際硬件。NStack會將Tap接口當作正常物理接口一樣讀寫[9]。Tap接口會關聯一橋接接口,就好像一個路由器作為主機的一個子網接入其中,這樣可以允許NStack能使用它自己的MAC地址和IP地址,連接到外部網絡。

2.2 協議實現

NStack會實現數據鏈路層,網絡層和傳輸層的協議,每一層獨立運行自己的協議,如圖1所示。分層模型可以增加并行,在高負載下提供高效服務[10]。

圖1 網絡協議棧

每一個協議的實現使用了類似的結構,包處理器(packet dealer)。IP包處理器如圖2所示。包處理器從低層級讀取數據包,并通過通道傳輸。通道以箭頭表示在圖2中。IP包處理器將數據包發給不同的IP reader協程。IP reader處理完接收到的數據包后,將處理結果轉發給下一層的包處理器。

圖2 IPv4包處理器

(1)以太協議層允許其他不同層的協議綁定到特定的以太協議。比如IPv4實現會綁定到以太協議2048去接收所有IPv4數據包,ARP實現則綁定到以太協議2054。

(2)地址解析協議(address resolution protocol,ARP)會被實現用于MAC地址的獲取,數據的網絡傳輸需要物理信息的支持。ARP能讓NStack從目標主機的目標協議地址中獲取MAC地址。NStack為每個ARP請求創建一個協程負責處理。處理時協程會被阻塞直到主ARP包處理器通知其響應或者請求超時。

(3)IPv4的設計如圖2所示,它使用包處理器結構,包含多個IP讀取器和分片重組器。所有組件之間的通信都是通過通道進行,如箭頭所示。

當IP包大小超過最大傳輸單元(maximum transmission unit,MTU)時,便會出現IP分片,IP包會被拆分成多個分片,每一個分片都包含一些信息用以重組。當分片數據包到達目的主機,它們便會被重組成原始IP包。

NStack的分片重組器演示了CSP模型的優點。每個分片重組器都囊括了對分片IP數據包的處理過程以及相應的數據。與用全局數據結構來管理所有分片數據包重組的傳統方法相比,為每個報文分片分配一個專屬重組器,這種CSP模型的做法可以大幅降低代碼的復雜度。輕量級的Go協程設計讓數據隔離變得可行,垃圾回收又大幅降低內存泄漏的可能。

(4)NStack實現了ping及ICMP協議。ICMP實現也是遵循包處理器結構。ping實現也有其相應的包處理器,ping的ICMP包會被ICMP包處理器先行處理,然后再發給ping的包處理器處理。ping包處理器會將ping請求轉發給一組特別的協程,用于回復ping請求。如果NStack已經發送了ping請求,則ping包處理器將會把回應轉發給對應請求的專屬協程負責。

(5)用戶報文協議(user datagram protocol,UDP)是個無連接的協議,因為它相對簡單,NStack便用一個基礎的包處理器將其轉發給對應的UDP讀取器。

(6)傳輸控制協議(transmission control protocol,TCP)是面向連接的傳輸層協議,它保證了數據傳輸的有序。因為TCP是面向連接的,所以它會需要服務端和客戶端來初始化連接。一旦連接建立成功,便由傳輸控制單元(transmission control block,TCB)進行管理。

NStack里TCP也是使用標準的包處理器結構管理源端口和目的端口,每個TCB里都有2個長期運行的協程。一個處理接收到的數據包,另一個則等待和發送數據,也會負責創建額外的協程管理數據包的重發,這2個協程便代表著半雙工TCP連接。TCB內部也會用到通道來同步和管理所有創建的協程。比如,處理接收數據包的協程發現收到一個確認數據包時,便會用通道通知數據包重傳協程。

2.3 測 試

NStack會與Tapip進行性能比較。Tapip是一個由C語言開發的多線程網絡堆棧。這個比較允許評估用高級語言開發網絡堆棧的優點和缺點。兩個網絡堆棧都實現了相似的協議,都在用戶空間(user space)操作,都使用tap虛擬接口。測試機器是Ubuntu 14.04/Linux 3.13.0,16 GB內存,Intel Xeon Quad Core Dual Socket處理器。

2.3.1 延 遲

為測試延遲,將取50次ping響應時間的平均值作比較。測試環境的一臺Linux虛擬機將運行兩個網絡堆棧,ping請求從該虛擬機發出。為判斷堆棧在負載增加情況下的性能,多個ping會被同時并發發送。從1個增加到1 000個并發ping“連接”來模擬網絡堆棧可能接受的負載。為保證對兩個網絡堆棧公平,其他的變量都將保持不變,包括每個ping“連接”發送的ping請求數,ICMP接受緩沖區大小以及ping請求數據包大小。

2.3.2 吞吐量

第二個將要評估的性能指標便是吞吐量。一個堆棧的吞吐量是在給定時間內,能發送或接收的數據量大小[11]。以下步驟將用以測量兩個堆棧的吞吐量:

(1)初始化一個TCP服務端。

(2)初始化一個TCP客戶端,連接會在local網絡(localhost)中建立,以排除tap虛擬網卡導致的開銷。

(3)客戶端發送4 KB數據給服務端。

(4)計算堆棧完成上述過程的總時間,該時間和發送的數據量將用來計算吞吐量。

為測量堆棧的相對擴展能力,將會逐步增加客戶端數來測量性能[12]。最大測試到100個并發客戶端。有許多預防措施將用于保證吞吐量的準確測量,比如所有可比較的緩沖區大小都一致[13]。在Tapip中,每個客戶端和服務端連接都運行在各自線程里,NStack類似,但是用的是Go的協程而不是線程。另外,也會確保所有連接完成且連接的負載被完整傳輸之后再停止運行網絡堆棧[14-15]。

3 結果分析

NStack的代碼與Tapip比較類似,但是從結果來看,性能上,包括延遲和吞吐量,NStack相比之下出色得多。

3.1 準確性

NStack和Tapip都能準確地運行協議,這可以通過分別測試兩個協議棧與一臺Linux終端的連接來進行判斷。測試中發現Tapip有內存泄漏的情況。這是因為Tapip會開辟緩存區存儲數據包,在某些情況下這些緩存區不會被釋放或者重復釋放。當緩存區被重復釋放時,Tapip會崩潰或者導致異常行為。當緩存區不會被釋放時,Tapip會不斷侵占內存,直至系統崩潰。Go則由于有內置的垃圾回收,可以很好地避免這種情況的發生。

3.2 代碼比較

雖然很難量化地評估編寫Go語言相比較C語言的優點,但是從一些代碼片段的比較還是可以看出高級語言的某些優勢。以下以IP報文分片重組的處理代碼舉例說明。

(1)當新的IP分片到達時,需要初始化分片重組器。Tapip則會使用全局結構體存儲所有待重組的數據,C代碼如下所示:

struct fragment *frag;

frag=xmalloc(sizeof(*frag));

list_add(& frag->frag_list, & frag_head);

list_init(& frag->frag_pkb);

return frag;

NStack會給每個待重組的包新建一個Go協程,Go語言代碼如下:

ipr.fragBuf[bufID]=make(chan []byte, FRAG_ASSEM_BUF_SZ)

quit:=make(chan bool, 1)

done:=make(chan bool, 1)

didQuit:=make(chan bool, 1)

go ipr.fragAssembler( /* ... */ )

go ipr.killFragAssembler( /* ... */ )

(2)當添加分片到重組隊列時,Tapip的C語言代碼如下:

int insert_frag(/* ... */) {

/*一些額外的分片處理 */

list_add(& pkb->pk_list, pos);

return 0;

frag_drop: free_pkb(pkb); return -1;

}

Go語言代碼則如下:

ipr.fragBuf[bufID] <- b

Go可以用協程處理IP報文分片,因此它可以簡單地將分片轉發給對應的協程處理,同時可以緊接著處理后續數據包。此舉會改進NStack代碼的模塊性、可讀性和并發性。

(3)分片處理完成時的C語言代碼片段如下:

if (complete_frag(frag))

pkb=reass_frag(frag);

else pkb=NULL;

return pkb;

struct pkbuf *reass_frag(

struct fragment *frag) {

/* more processing */

delete_frag(frag);

return pkb;

}

Go語言代碼片段如下:

ipr.incomingPackets <- append(

fullPacketHdr ,payload ...)

done <- true

經過對比,可以凸顯出Go語言以及CSP模型的優勢。Tapip必需按順序處理數據包,在前一個數據包未處理完時,下一個數據包只能在緩沖區中等待。這會帶來一些問題,比如這便需要C語言的IP實現去跟蹤所有正在進行的分片重組的狀態,這樣不可避免地會使用全局變量和結構體來記錄共享信息,并且會讓線程同步變得困難。NStack與之相反,它會對接收到的每個分片IP包創建一個獨立的分片重組器協程,每個協程各自負責獨立的分片組裝成IP片段。分片重組器處理重組完數據包后,它便簡單地將重組片段發回后續的IP數據包處理過程。IP數據包這個主處理過程與分片重組器是獨立的協程,因此可以實現完全的并行和并發,代碼也更簡潔可讀。

(4)在清理分片時,C語言的Tapip需要顯性地釋放每一個內存緩存區,代碼如下:

struct pkbuf *pkb;

list_del(& frag->frag_list);

while (!list_empty(& frag->frag_pkb)) {

pkb=frag_head_pkb(frag);

list_del(& pkb->pk_list);

free_pkb(pkb);

}

free(frag);

而Go語言只需跟蹤通道即可:

delete(ipr.fragBuf, bufID)

Go語言的簡潔友好可讀由此可見一斑。

3.3 延 遲

1個ping請求時,Tapip的0.074 ms優于NStack的0.234 ms,但是隨著并發請求的增加,當1 000個ping請求時,NStack的延遲為0.717 ms,差不多比Tapip的3.279 ms好5倍。NStack在連接數為600時,開始領先于Tapip。NStack延遲的增加是線性的,而Tapip是指數型的。NStack的延遲趨勢是優于Tapip的,因為在請求數很少時,兩者之間延遲的差距很小,可以忽略不計,但是在大量并發ping時,差異就明顯變大,如圖3所示。

圖3 并發延遲性測試結果

基于圖3的結果,可以得出Tapip能非常快地處理小量級的數據包,而對于大量的數據包涌入時,則顯得處理乏力,性能極差。相對應的,NStack會用相對較長的時間來處理每個數據包,但是因為其在每個協議實現中良好的并發控制,在負載大量增加的情況下,幾乎不影響其處理性能。表現出來便是結果中,Tapip雖然開始性能優秀,但延遲卻隨著并發量的增長,迅速增大上升,而NStack則小幅平緩的增加。Tapip陡峭的增長趨勢凸顯了其底層架構的問題,即在所有的協議層處理完一個數據包后,再處理下一個數據包,這種做法不是一個高效的方法,因為這會導致擴展或并發難以實現。

3.4 吞吐量

測試結果如圖4所示,1個并發連接時,NStack的吞吐量達到7.3 Mbit/s,而Tapip的只有4.6 Mbit/s。當100個并發連接時,NStack達到了284.9 Mbit/s,而Tapip則只有195 Mbit/s。并且,NStack的吞吐量增加速度比Tapip快得多。這表明NStack可以繼續在更大量的并發情況下擴展吞吐量而Tapip則很可能處理不了這種負載。

圖4 并發吞吐量測試結果

結果有力地驗證了NStack的架構。在Tapip里,所有的傳輸控制塊(transmission control block,TCB)都是由單個線程管理的;相應的,在NStack中,每個TCB由兩個線程進行管理,分別負責一半的上下行連接,因而NStack可以更高效地在有限的CPU核數上多路復用大量的連接,可以達到更大的吞吐量。在小量并發連接時,NStack也工作地更高效,因為它把TCB的處理工作拆分為兩個Go協程,而Tapip則自始至終都是一個線程執行處理任務。

4 結束語

操作系統內核對于管理計算機系統資源而言是十分重要的核心組件,如何在兼顧性能的前提下,引入高級語言進行開發,降低低級語言開發內核帶來的復雜性和安全隱患是該文的初衷。該文以內核的網絡堆棧子系統為出發點,用Go語言實現NStack,研究高級語言開發內核的可行性和便利性。NStack和對比實驗的C語言開發的Tapip都是基于tap接口,都實現了相類似的協議,比如IPv4,ARP,UDP和TCP。在延遲性和吞吐量的對比實驗中,可以發現NStack有優秀的性能表現,在延遲性測試中,當并發數大于600時,NStack取得更低的延時;在吞吐量的測試中,NStack的并行化讓其在所有的測試場景中都取得了優于Tapip的吞吐量。

實驗表明,Go語言帶來的簡潔和模塊化可以提供優于C語言的幫助,用Go開發內核子系統可以改善代碼的可讀性和可靠性,結構模塊清晰,良好的并發能力和穩定性,同時又對內核整體性能沒有產生重大不良影響。結果表明,對于內核開發來說,Go語言可以是一個重要的C語言替代者。

猜你喜歡
語言
詩之新,以語言創造為基
中華詩詞(2023年8期)2023-02-06 08:51:28
語言是刀
文苑(2020年4期)2020-05-30 12:35:30
讓語言描寫搖曳多姿
多向度交往對語言磨蝕的補正之道
累積動態分析下的同聲傳譯語言壓縮
日常語言與播音語言
新聞傳播(2016年10期)2016-09-26 12:15:04
語言技能退化與語言瀕危
我有我語言
論語言的“得體”
語文知識(2014年10期)2014-02-28 22:00:56
Only Words慎用你的語言
主站蜘蛛池模板: 18黑白丝水手服自慰喷水网站| 伊人天堂网| 久久婷婷六月| 亚洲第一网站男人都懂| 都市激情亚洲综合久久| 亚洲视频免费播放| 四虎永久免费地址| 大陆精大陆国产国语精品1024 | 国产高清精品在线91| 国产精品成人一区二区不卡| 精品人妻AV区| 亚洲中久无码永久在线观看软件| 波多野结衣一区二区三区AV| 国产成人综合欧美精品久久| 亚洲欧美成人在线视频| 久久精品人人做人人爽| 亚洲中文字幕无码爆乳| 国产自在线播放| Aⅴ无码专区在线观看| 亚洲第一av网站| 国产极品嫩模在线观看91| 亚洲欧美综合在线观看| a在线亚洲男人的天堂试看| 久久这里只精品热免费99| 国模沟沟一区二区三区| 91久久精品国产| 国产精品久久久久久久久kt| 欧美在线伊人| 国产成人高清精品免费5388| 91年精品国产福利线观看久久 | 亚洲av无码人妻| 日韩无码视频专区| 97国产精品视频自在拍| 亚洲一区毛片| 黄色国产在线| 亚洲视屏在线观看| 亚洲欧美在线综合图区| 国产91精品久久| 国产一级小视频| 国产精品真实对白精彩久久| 国产高清色视频免费看的网址| 狠狠干欧美| 午夜天堂视频| 欧美午夜在线播放| 99热国产这里只有精品无卡顿"| 狠狠色噜噜狠狠狠狠色综合久| 中文精品久久久久国产网址| 熟妇丰满人妻| 国产大片黄在线观看| 高清国产在线| 中文成人在线视频| 亚洲中久无码永久在线观看软件 | 亚洲h视频在线| 中文字幕欧美成人免费| 欧美精品在线免费| 视频一本大道香蕉久在线播放| 午夜欧美在线| 亚洲久悠悠色悠在线播放| 欧美天堂久久| 日韩在线永久免费播放| 亚洲an第二区国产精品| 久996视频精品免费观看| 免费av一区二区三区在线| 九九热视频精品在线| 亚洲成人手机在线| 黄色一及毛片| 免费三A级毛片视频| 亚洲欧美一区二区三区蜜芽| 国产精品页| 日韩高清一区 | 亚洲αv毛片| 欧美亚洲一区二区三区导航 | 国产精品主播| 四虎国产永久在线观看| 最新亚洲人成无码网站欣赏网| 日韩高清在线观看不卡一区二区| 国产精品综合色区在线观看| 亚洲人成在线免费观看| 免费毛片视频| 中文字幕无码电影| 国产色爱av资源综合区| 国内精品久久久久鸭|