淺談 Linux下的零拷貝機(jī)制

什么是零拷貝

維基上是這么描述零拷貝的:零拷貝描述的是CPU不執(zhí)行拷貝數(shù)據(jù)從一個(gè)存儲(chǔ)區(qū)域到另一個(gè)存儲(chǔ)區(qū)域的任務(wù)笙瑟,這通常用于通過(guò)網(wǎng)絡(luò)傳輸一個(gè)文件時(shí)以減少CPU周期和內(nèi)存帶寬。

零拷貝給我們帶來(lái)的好處:
  • 減少甚至完全避免不必要的CPU拷貝,從而讓CPU解脫出來(lái)去執(zhí)行其他的任務(wù)
  • 減少內(nèi)存帶寬的占用
  • 通常零拷貝技術(shù)還能夠減少用戶空間和操作系統(tǒng)內(nèi)核空間之間的上下文切換

Linux系統(tǒng)的“用戶空間”和“內(nèi)核空間”

從Linux系統(tǒng)上看颜曾,除了引導(dǎo)系統(tǒng)的BIN區(qū)褐健,整個(gè)內(nèi)存空間主要被分成兩個(gè)部分:內(nèi)核空間(Kernel space)、用戶空間(User space)物蝙⊙字停“用戶空間”和“內(nèi)核空間”的空間、操作權(quán)限以及作用都是不一樣的诬乞。內(nèi)核空間是Linux自身使用的內(nèi)存空間册赛,主要提供給程序調(diào)度、內(nèi)存分配震嫉、連接硬件資源等程序邏輯使用森瘪;用戶空間則是提供給各個(gè)進(jìn)程的主要空間。用戶空間不具有訪問(wèn)內(nèi)核空間資源的權(quán)限票堵,因此如果應(yīng)用程序需要使用到內(nèi)核空間的資源扼睬,則需要通過(guò)系統(tǒng)調(diào)用來(lái)完成:從用戶空間切換到內(nèi)核空間,然后在完成相關(guān)操作后再?gòu)膬?nèi)核空間切換回用戶空間换衬。

Linux 中零拷貝技術(shù)的實(shí)現(xiàn)方向

① 直接 I/O:對(duì)于這種數(shù)據(jù)傳輸方式來(lái)說(shuō)痰驱,應(yīng)用程序可以直接訪問(wèn)硬件存儲(chǔ)证芭,操作系統(tǒng)內(nèi)核只是輔助數(shù)據(jù)傳輸。這種方式依舊存在用戶空間和內(nèi)核空間的上下文切換担映,但是硬件上的數(shù)據(jù)不會(huì)拷貝一份到內(nèi)核空間废士,而是直接拷貝至了用戶空間,因此直接I/O不存在內(nèi)核空間緩沖區(qū)和用戶空間緩沖區(qū)之間的數(shù)據(jù)拷貝蝇完。

② 在數(shù)據(jù)傳輸過(guò)程中官硝,避免數(shù)據(jù)在用戶空間緩沖區(qū)和系統(tǒng)內(nèi)核空間緩沖區(qū)之間的CPU拷貝,以及數(shù)據(jù)在系統(tǒng)內(nèi)核空間內(nèi)的CPU拷貝短蜕。本文主要討論的就是該方式下的零拷貝機(jī)制氢架。

③ copy-on-write(寫時(shí)復(fù)制技術(shù)):在某些情況下,Linux操作系統(tǒng)的內(nèi)核空間緩沖區(qū)可能被多個(gè)應(yīng)用程序所共享朋魔,操作系統(tǒng)有可能會(huì)將用戶空間緩沖區(qū)地址映射到內(nèi)核空間緩存區(qū)中岖研。當(dāng)應(yīng)用程序需要對(duì)共享的數(shù)據(jù)進(jìn)行修改的時(shí)候,才需要真正地拷貝數(shù)據(jù)到應(yīng)用程序的用戶空間緩沖區(qū)中警检,并且對(duì)自己用戶空間的緩沖區(qū)的數(shù)據(jù)進(jìn)行修改不會(huì)影響到其他共享數(shù)據(jù)的應(yīng)用程序孙援。所以,如果應(yīng)用程序不需要對(duì)數(shù)據(jù)進(jìn)行任何修改的話扇雕,就不會(huì)存在數(shù)據(jù)從系統(tǒng)內(nèi)核空間緩沖區(qū)拷貝到用戶空間緩沖區(qū)的操作拓售。

注意,對(duì)于各種零拷貝機(jī)制是否能夠?qū)崿F(xiàn)都是依賴于操作系統(tǒng)底層是否提供相應(yīng)的支持镶奉。


零拷貝機(jī)制的原理

下面我們通過(guò)一個(gè)Java非常常見(jiàn)的應(yīng)用場(chǎng)景:將系統(tǒng)中的文件發(fā)送到遠(yuǎn)端(該流程涉及:磁盤上文件 ——> 內(nèi)存(字節(jié)數(shù)組) ——> 傳輸給用戶/網(wǎng)絡(luò))來(lái)詳細(xì)展開(kāi)傳統(tǒng)I/O操作和通過(guò)零拷貝來(lái)實(shí)現(xiàn)的I/O操作础淤。

傳統(tǒng)I/O


① 發(fā)出read系統(tǒng)調(diào)用:導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第一次上下文切換)。通過(guò)DMA引擎將文件中的數(shù)據(jù)從磁盤上讀取到內(nèi)核空間緩沖區(qū)(第一次拷貝: hard drive ——> kernel buffer)哨苛。
② 將內(nèi)核空間緩沖區(qū)的數(shù)據(jù)拷貝到用戶空間緩沖區(qū)(第二次拷貝: kernel buffer ——> user buffer)鸽凶,然后read系統(tǒng)調(diào)用返回。而系統(tǒng)調(diào)用的返回又會(huì)導(dǎo)致一次內(nèi)核空間到用戶空間的上下文切換(第二次上下文切換)移国。
③ 發(fā)出write系統(tǒng)調(diào)用:導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第三次上下文切換)吱瘩。將用戶空間緩沖區(qū)中的數(shù)據(jù)拷貝到內(nèi)核空間中與socket相關(guān)聯(lián)的緩沖區(qū)中(即道伟,第②步中從內(nèi)核空間緩沖區(qū)拷貝而來(lái)的數(shù)據(jù)原封不動(dòng)的再次拷貝到內(nèi)核空間的socket緩沖區(qū)中迹缀。)(第三次拷貝: user buffer ——> socket buffer)。
④ write系統(tǒng)調(diào)用返回蜜徽,導(dǎo)致內(nèi)核空間到用戶空間的再次上下文切換(第四次上下文切換)祝懂。通過(guò)DMA引擎將內(nèi)核緩沖區(qū)中的數(shù)據(jù)傳遞到協(xié)議引擎(第四次拷貝: socket buffer ——> protocol engine)训枢,這次拷貝是一個(gè)獨(dú)立且異步的過(guò)程瑟蜈。

Q:你可能會(huì)問(wèn)獨(dú)立和異步這是什么意思荐绝?難道是調(diào)用會(huì)在數(shù)據(jù)被傳輸前返回故源?
A:事實(shí)上調(diào)用的返回并不保證數(shù)據(jù)被傳輸誉结;它甚至不保證傳輸?shù)拈_(kāi)始。它只是意味著將我們要發(fā)送的數(shù)據(jù)放入到了一個(gè)待發(fā)送的隊(duì)列中圣贸,在我們之前可能有許多數(shù)據(jù)包在排隊(duì)限次。除非驅(qū)動(dòng)器或硬件實(shí)現(xiàn)優(yōu)先級(jí)環(huán)或隊(duì)列,否則數(shù)據(jù)是以先進(jìn)先出的方式傳輸?shù)摹?/p>

總的來(lái)說(shuō)摩梧,傳統(tǒng)的I/O操作進(jìn)行了4次用戶空間與內(nèi)核空間的上下文切換物延,以及4次數(shù)據(jù)拷貝。其中4次數(shù)據(jù)拷貝中包括了2次DMA拷貝和2次CPU拷貝仅父。

Q: 傳統(tǒng)I/O模式為什么將數(shù)據(jù)從磁盤讀取到內(nèi)核空間緩沖區(qū)叛薯,然后再將數(shù)據(jù)從內(nèi)核空間緩沖區(qū)拷貝到用戶空間緩沖區(qū)了?為什么不直接將數(shù)據(jù)從磁盤讀取到用戶空間緩沖區(qū)就好笙纤?
A: 傳統(tǒng)I/O模式之所以將數(shù)據(jù)從磁盤讀取到內(nèi)核空間緩沖區(qū)而不是直接讀取到用戶空間緩沖區(qū)耗溜,是為了減少磁盤I/O操作以此來(lái)提高性能。因?yàn)镺S會(huì)根據(jù)局部性原理在一次read()系統(tǒng)調(diào)用的時(shí)候預(yù)讀取更多的文件數(shù)據(jù)到內(nèi)核空間緩沖區(qū)中省容,這樣當(dāng)下一次read()系統(tǒng)調(diào)用的時(shí)候發(fā)現(xiàn)要讀取的數(shù)據(jù)已經(jīng)存在于內(nèi)核空間緩沖區(qū)中的時(shí)候只要直接拷貝數(shù)據(jù)到用戶空間緩沖區(qū)中即可抖拴,無(wú)需再進(jìn)行一次低效的磁盤I/O操作(注意:磁盤I/O操作的速度比直接訪問(wèn)內(nèi)存慢了好幾個(gè)數(shù)量級(jí))。
Q: 既然系統(tǒng)內(nèi)核緩沖區(qū)能夠減少磁盤I/O操作腥椒,那么我們經(jīng)常使用的BufferedInputStream緩沖區(qū)又是用來(lái)干啥的城舞?
A: BufferedInputStream的作用是會(huì)根據(jù)情況自動(dòng)為我們預(yù)取更多的數(shù)據(jù)到它自己維護(hù)的一個(gè)內(nèi)部字節(jié)數(shù)據(jù)緩沖區(qū)中,這樣做能夠減少系統(tǒng)調(diào)用的次數(shù)以此來(lái)提供性能寞酿。

總的來(lái)說(shuō)內(nèi)核空間緩沖區(qū)的一大用處是為了減少磁盤I/O操作家夺,因?yàn)樗鼤?huì)從磁盤中預(yù)讀更多的數(shù)據(jù)到緩沖區(qū)中。而BufferedInputStream的用處是減少“系統(tǒng)調(diào)用”伐弹。

DMA
DMA(Direct Memory Access) ———— 直接內(nèi)存訪問(wèn) :DMA是允許外設(shè)組件將I/O數(shù)據(jù)直接傳送到主存儲(chǔ)器中并且傳輸不需要CPU的參與拉馋,以此將CPU解放出來(lái)去完成其他的事情。
而用戶空間與內(nèi)核空間之間的數(shù)據(jù)傳輸并沒(méi)有類似DMA這種可以不需要CPU參與的傳輸工具惨好,因此用戶空間與內(nèi)核空間之間的數(shù)據(jù)傳輸是需要CPU全程參與的煌茴。所有也就有了通過(guò)零拷貝技術(shù)來(lái)減少和避免不必要的CPU數(shù)據(jù)拷貝過(guò)程。

通過(guò)sendfile實(shí)現(xiàn)的零拷貝I/O

① 發(fā)出sendfile系統(tǒng)調(diào)用日川,導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第一次上下文切換)蔓腐。通過(guò)DMA引擎將磁盤文件中的內(nèi)容拷貝到內(nèi)核空間緩沖區(qū)中(第一次拷貝: hard drive ——> kernel buffer)。然后再將數(shù)據(jù)從內(nèi)核空間緩沖區(qū)拷貝到內(nèi)核中與socket相關(guān)的緩沖區(qū)中(第二次拷貝: kernel buffer ——> socket buffer)龄句。
② sendfile系統(tǒng)調(diào)用返回回论,導(dǎo)致內(nèi)核空間到用戶空間的上下文切換(第二次上下文切換)。通過(guò)DMA引擎將內(nèi)核空間socket緩沖區(qū)中的數(shù)據(jù)傳遞到協(xié)議引擎(第三次拷貝: socket buffer ——> protocol engine)

總的來(lái)說(shuō)分歇,通過(guò)sendfile實(shí)現(xiàn)的零拷貝I/O只使用了2次用戶空間與內(nèi)核空間的上下文切換傀蓉,以及3次數(shù)據(jù)的拷貝。其中3次數(shù)據(jù)拷貝中包括了2次DMA拷貝和1次CPU拷貝职抡。

Q:但通過(guò)是這里還是存在著一次CPU拷貝操作葬燎,即,kernel buffer ——> socket buffer。是否有辦法將該拷貝操作也取消掉了谱净?
A:有的窑邦。但這需要底層操作系統(tǒng)的支持。從Linux 2.4版本開(kāi)始壕探,操作系統(tǒng)底層提供了scatter/gather這種DMA的方式來(lái)從內(nèi)核空間緩沖區(qū)中將數(shù)據(jù)直接讀取到協(xié)議引擎中奕翔,而無(wú)需將內(nèi)核空間緩沖區(qū)中的數(shù)據(jù)再拷貝一份到內(nèi)核空間socket相關(guān)聯(lián)的緩沖區(qū)中。

帶有DMA收集拷貝功能的sendfile實(shí)現(xiàn)的I/O

從Linux 2.4版本開(kāi)始浩蓉,操作系統(tǒng)底層提供了帶有scatter/gather的DMA來(lái)從內(nèi)核空間緩沖區(qū)中將數(shù)據(jù)讀取到協(xié)議引擎中派继。這樣一來(lái)待傳輸?shù)臄?shù)據(jù)可以分散在存儲(chǔ)的不同位置上,而不需要在連續(xù)存儲(chǔ)中存放捻艳。那么從文件中讀出的數(shù)據(jù)就根本不需要被拷貝到socket緩沖區(qū)中去驾窟,只是需要將緩沖區(qū)描述符添加到socket緩沖區(qū)中去,DMA收集操作會(huì)根據(jù)緩沖區(qū)描述符中的信息將內(nèi)核空間中的數(shù)據(jù)直接拷貝到協(xié)議引擎中认轨。



① 發(fā)出sendfile系統(tǒng)調(diào)用绅络,導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第一次上下文切換)。通過(guò)DMA引擎將磁盤文件中的內(nèi)容拷貝到內(nèi)核空間緩沖區(qū)中(第一次拷貝: hard drive ——> kernel buffer)嘁字。
② 沒(méi)有數(shù)據(jù)拷貝到socket緩沖區(qū)恩急。取而代之的是只有相應(yīng)的描述符信息會(huì)被拷貝到相應(yīng)的socket緩沖區(qū)當(dāng)中。該描述符包含了兩方面的信息:a)kernel buffer的內(nèi)存地址纪蜒;b)kernel buffer的偏移量衷恭。
③ sendfile系統(tǒng)調(diào)用返回,導(dǎo)致內(nèi)核空間到用戶空間的上下文切換(第二次上下文切換)纯续。DMA gather copy根據(jù)socket緩沖區(qū)中描述符提供的位置和偏移量信息直接將內(nèi)核空間緩沖區(qū)中的數(shù)據(jù)拷貝到協(xié)議引擎上(第二次拷貝: kernel buffer ——> protocol engine)随珠,這樣就避免了最后一次CPU數(shù)據(jù)拷貝。

總的來(lái)說(shuō)猬错,帶有DMA收集拷貝功能的sendfile實(shí)現(xiàn)的I/O只使用了2次用戶空間與內(nèi)核空間的上下文切換窗看,以及2次數(shù)據(jù)的拷貝,而且這2次的數(shù)據(jù)拷貝都是非CPU拷貝倦炒。這樣一來(lái)我們就實(shí)現(xiàn)了最理想的零拷貝I/O傳輸了显沈,不需要任何一次的CPU拷貝,以及最少的上下文切換逢唤。

關(guān)于sendfile:

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

在linux2.6.33版本之前 sendfile指支持文件到套接字之間傳輸數(shù)據(jù)拉讯,即in_fd相當(dāng)于一個(gè)支持mmap的文件,out_fd必須是一個(gè)socket智玻。但從linux2.6.33版本開(kāi)始遂唧,out_fd可以是任意類型文件描述符芙代。所以從linux2.6.33版本開(kāi)始sendfile可以支持“文件到文件”和“文件到套接字”之間的數(shù)據(jù)傳輸吊奢。

"傳統(tǒng)I/O” VS “sendfile零拷貝I/O”
  • 傳統(tǒng)I/O通過(guò)兩條系統(tǒng)指令read、write來(lái)完成數(shù)據(jù)的讀取和傳輸操作,以至于產(chǎn)生了4次用戶空間與內(nèi)核空間的上下文切換的開(kāi)銷页滚;而sendfile只使用了一條指令就完成了數(shù)據(jù)的讀寫操作召边,所以只產(chǎn)生了2次用戶空間與內(nèi)核空間的上下文切換。
  • 傳統(tǒng)I/O產(chǎn)生了2次無(wú)用的CPU拷貝裹驰,即內(nèi)核空間緩存中數(shù)據(jù)與用戶空間緩沖區(qū)間數(shù)據(jù)的拷貝隧熙;而sendfile最多只產(chǎn)出了一次CPU拷貝,即內(nèi)核空間內(nèi)之間的數(shù)據(jù)拷貝幻林,甚至在底層操作體系支持的情況下贞盯,sendfile可以實(shí)現(xiàn)零CPU拷貝的I/O。
  • 因傳統(tǒng)I/O用戶空間緩沖區(qū)中存有數(shù)據(jù)沪饺,因此應(yīng)用程序能夠?qū)Υ藬?shù)據(jù)進(jìn)行修改等操作躏敢;而sendfile零拷貝消除了所有內(nèi)核空間緩沖區(qū)與用戶空間緩沖區(qū)之間的數(shù)據(jù)拷貝過(guò)程,因此sendfile零拷貝I/O的實(shí)現(xiàn)是完成在內(nèi)核空間中完成的整葡,這對(duì)于應(yīng)用程序來(lái)說(shuō)就無(wú)法對(duì)數(shù)據(jù)進(jìn)行操作了件余。

Q:對(duì)于上面的第三點(diǎn),如果我們需要對(duì)數(shù)據(jù)進(jìn)行操作該怎么辦了遭居?
A:Linux提供了mmap零拷貝來(lái)實(shí)現(xiàn)我們的需求啼器。

通過(guò)mmap實(shí)現(xiàn)的零拷貝I/O

mmap(內(nèi)存映射)是一個(gè)比sendfile昂貴但優(yōu)于傳統(tǒng)I/O的方法。



① 發(fā)出mmap系統(tǒng)調(diào)用俱萍,導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第一次上下文切換)端壳。通過(guò)DMA引擎將磁盤文件中的內(nèi)容拷貝到內(nèi)核空間緩沖區(qū)中(第一次拷貝: hard drive ——> kernel buffer)。
② mmap系統(tǒng)調(diào)用返回枪蘑,導(dǎo)致內(nèi)核空間到用戶空間的上下文切換(第二次上下文切換)更哄。接著用戶空間和內(nèi)核空間共享這個(gè)緩沖區(qū),而不需要將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間腥寇。因?yàn)橛脩艨臻g和內(nèi)核空間共享了這個(gè)緩沖區(qū)數(shù)據(jù)成翩,所以用戶空間就可以像在操作自己緩沖區(qū)中數(shù)據(jù)一般操作這個(gè)由內(nèi)核空間共享的緩沖區(qū)數(shù)據(jù)。
③ 發(fā)出write系統(tǒng)調(diào)用赦役,導(dǎo)致用戶空間到內(nèi)核空間的上下文切換(第三次上下文切換)麻敌。將數(shù)據(jù)從內(nèi)核空間緩沖區(qū)拷貝到內(nèi)核空間socket相關(guān)聯(lián)的緩沖區(qū)(第二次拷貝: kernel buffer ——> socket buffer)。
④ write系統(tǒng)調(diào)用返回掂摔,導(dǎo)致內(nèi)核空間到用戶空間的上下文切換(第四次上下文切換)术羔。通過(guò)DMA引擎將內(nèi)核空間socket緩沖區(qū)中的數(shù)據(jù)傳遞到協(xié)議引擎(第三次拷貝: socket buffer ——> protocol engine)

總的來(lái)說(shuō),通過(guò)mmap實(shí)現(xiàn)的零拷貝I/O進(jìn)行了4次用戶空間與內(nèi)核空間的上下文切換乙漓,以及3次數(shù)據(jù)拷貝级历。其中3次數(shù)據(jù)拷貝中包括了2次DMA拷貝和1次CPU拷貝。

FileChannel與零拷貝

FileChannel中大量使用了我們上面所提及的零拷貝技術(shù)叭披。
FileChannel的map方法會(huì)返回一個(gè)MappedByteBuffer寥殖。MappedByteBuffer是一個(gè)直接字節(jié)緩沖器,該緩沖器的內(nèi)存是一個(gè)文件的內(nèi)存映射區(qū)域。map方法底層是通過(guò)mmap實(shí)現(xiàn)的嚼贡,因此將文件內(nèi)存從磁盤讀取到內(nèi)核緩沖區(qū)后熏纯,用戶空間和內(nèi)核空間共享該緩沖區(qū)。
MappedByteBuffer內(nèi)存映射文件是一種允許Java程序直接從內(nèi)存訪問(wèn)的一種特殊的文件粤策。我們可以將整個(gè)文件或者整個(gè)文件的一部分映射到內(nèi)存當(dāng)中樟澜,那么接下來(lái)是由操作系統(tǒng)來(lái)進(jìn)行相關(guān)的頁(yè)面請(qǐng)求并將內(nèi)存的修改寫入到文件當(dāng)中。我們的應(yīng)用程序只需要處理內(nèi)存的數(shù)據(jù)叮盘,這樣可以實(shí)現(xiàn)非常迅速的I/O操作秩贰。

FileChannel map的三種模式

  • 只讀模式
/**
 * Mode for a read-only mapping.
 */
public static final MapMode READ_ONLY = new MapMode("READ_ONLY");

只讀模式來(lái)說(shuō),如果程序試圖進(jìn)行寫操作柔吼,則會(huì)拋出ReadOnlyBufferException異常

  • 讀寫模式
/**
 * Mode for a read/write mapping.
 */
public static final MapMode READ_WRITE = new MapMode("READ_WRITE");

讀寫模式表明萍膛,對(duì)結(jié)果對(duì)緩沖區(qū)所做的修改將最終廣播到文件。但這個(gè)修改可能會(huì)也可能不會(huì)被其他映射了相同文件程序可見(jiàn)嚷堡。

  • 專用模式
/**
 * Mode for a private (copy-on-write) mapping.
 */
public static final MapMode PRIVATE = new MapMode("PRIVATE");

私有模式來(lái)說(shuō)蝗罗,對(duì)結(jié)果緩沖區(qū)的修改將不會(huì)被廣播到文件并且也不會(huì)對(duì)其他映射了相同文件的程序可見(jiàn)。取而代之的是蝌戒,它將導(dǎo)致被修改部分緩沖區(qū)獨(dú)自拷貝一份到用戶空間串塑。這便是OS的“copy on write”原則。


FileChannel的transferTo北苟、transferFrom
如果操作系統(tǒng)底層支持的話transferTo桩匪、transferFrom也會(huì)使用相關(guān)的零拷貝技術(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)的傳輸。所以友鼻,這里是否使用零拷貝必須依賴于底層的系統(tǒng)實(shí)現(xiàn)傻昙。

后記

本文是通過(guò)視頻學(xué)習(xí)以及大量資料查詢后對(duì)零拷貝機(jī)制進(jìn)行的一個(gè)非常膚淺的知識(shí)梳理,至少個(gè)人是這么覺(jué)得彩扔。通過(guò)這次的學(xué)習(xí)妆档,對(duì)Linux操作系統(tǒng)又多了一丟丟的了解,也希望在之后的學(xué)習(xí)中能對(duì)Linux系統(tǒng)有更近一步的深入的理解虫碉。非常歡迎大家對(duì)文中的不足和錯(cuò)誤進(jìn)行指點(diǎn)~

參考:

It's all about buffers: zero-copy, mmap and Java NIO
Zero Copy I: User-Mode Perspective
Linux Programmer's Manual SENDFILE(2)
Linux 中的零拷貝技術(shù)贾惦,第 1 部分
Linux 中的零拷貝技術(shù),第 2 部分
圣思園《精通并發(fā)與Netty》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末敦捧,一起剝皮案震驚了整個(gè)濱河市须板,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兢卵,老刑警劉巖习瑰,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秽荤,居然都是意外死亡甜奄,警方通過(guò)查閱死者的電腦和手機(jī)柠横,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)贺嫂,“玉大人滓鸠,你說(shuō)我怎么就攤上這事雁乡〉谠” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵踱稍,是天一觀的道長(zhǎng)曲饱。 經(jīng)常有香客問(wèn)我,道長(zhǎng)珠月,這世上最難降的妖魔是什么扩淀? 我笑而不...
    開(kāi)封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮啤挎,結(jié)果婚禮上驻谆,老公的妹妹穿的比我還像新娘。我一直安慰自己庆聘,他們只是感情好胜臊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著伙判,像睡著了一般象对。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宴抚,一...
    開(kāi)封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天勒魔,我揣著相機(jī)與錄音,去河邊找鬼菇曲。 笑死冠绢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的常潮。 我是一名探鬼主播唐全,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蕊玷!你這毒婦竟也來(lái)了邮利?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤垃帅,失蹤者是張志新(化名)和其女友劉穎延届,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贸诚,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡方庭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年厕吉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片械念。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡头朱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出龄减,到底是詐尸還是另有隱情项钮,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布希停,位于F島的核電站烁巫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宠能。R本人自食惡果不足惜亚隙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望违崇。 院中可真熱鬧阿弃,春花似錦、人聲如沸羞延。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肴楷。三九已至水由,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赛蔫,已是汗流浹背砂客。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呵恢,地道東北人鞠值。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渗钉,于是被迫代替她去往敵國(guó)和親彤恶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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

  • 本文探討Linux中主要的幾種零拷貝技術(shù)以及零拷貝技術(shù)適用的場(chǎng)景鳄橘。為了迅速建立起零拷貝的概念声离,我們拿一個(gè)常用的場(chǎng)景...
    卡巴拉的樹閱讀 65,387評(píng)論 13 112
  • 已同步更新到微信公眾號(hào),手機(jī)閱讀更舒適~ 零拷貝機(jī)制原理分析之前瘫怜,我們先來(lái)看下傳統(tǒng)IO在數(shù)據(jù)拷貝的基本原理术徊,從數(shù)據(jù)...
    東升的思考閱讀 5,678評(píng)論 0 8
  • 目錄 [TOC] 簡(jiǎn)介 零拷貝(zero-copy)技術(shù)可以減少數(shù)據(jù)拷貝和共享總線操作的次數(shù),消除通信數(shù)據(jù)在存儲(chǔ)器...
    狼爺?shù)奶?hào)閱讀 1,393評(píng)論 0 2
  • 轉(zhuǎn)自JAVA IO 以及 NIO 理解 一段話總結(jié):傳統(tǒng)io中從磁盤中中讀文件鲸湃,并把文件通過(guò)網(wǎng)絡(luò)(socket)發(fā)...
    抓兔子的貓閱讀 1,333評(píng)論 0 4
  • 人赠涮,總會(huì)長(zhǎng)大子寓,長(zhǎng)大之后,不笋除,應(yīng)該說(shuō)是人從生下來(lái)身上就背負(fù)了各種各樣形形色色的壓力與負(fù)擔(dān)斜友。有時(shí)候就在說(shuō)人生來(lái)就是悲哀...
    軒軒軒軒軒砰閱讀 308評(píng)論 0 0