IO模式總結(jié)

網(wǎng)上看了好多IO,NIO的文字越庇,參差不齊顺呕,每篇總是差一兩個(gè)點(diǎn)沒(méi)有講到,所以這里對(duì)于我自己理解的做一個(gè)總結(jié),也許有不對(duì)的地方庸毫。

1供璧,基本概念

1.1)同步/異步,阻塞/非阻塞

同步異步主要針對(duì)C端:

所謂同步,就是在c端發(fā)出一個(gè)功能調(diào)用時(shí)弯屈,在沒(méi)有得到結(jié)果之前,該調(diào)用就不返回恋拷。也就是必須一件一件事做,等前一件做完了才能做下一件事资厉。

異步的概念和同步相對(duì)。當(dāng)c端一個(gè)異步過(guò)程調(diào)用發(fā)出后蔬顾,調(diào)用者不能立刻得到結(jié)果宴偿。實(shí)際處理這個(gè)調(diào)用的部件在完成后,通過(guò)狀態(tài)诀豁、通知和回調(diào)來(lái)通知調(diào)用者窄刘。

阻塞非阻塞主要針對(duì)S端:

阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起(線程進(jìn)入非可執(zhí)行狀態(tài)舷胜,在這個(gè)狀態(tài)下娩践,cpu不會(huì)給線程分配時(shí)間片,即線程暫停運(yùn)行)逞带。函數(shù)只有在得到結(jié)果之后才會(huì)返回欺矫。

非阻塞和阻塞的概念相對(duì)應(yīng),指在不能立刻得到結(jié)果之前展氓,該函數(shù)不會(huì)阻塞當(dāng)前線程穆趴,而會(huì)立刻返回。

1.2)面向流遇汞,面向緩沖區(qū)

面向流:每次從流中讀一個(gè)或多個(gè)字節(jié)未妹,直至讀取所有字節(jié),它們沒(méi)有被緩存在任何地方空入。

面向緩沖區(qū):數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū)络它,需要時(shí)可在緩沖區(qū)中前后移動(dòng)。這就增加了處理過(guò)程中的靈活性歪赢。

1.4)內(nèi)核態(tài)和用戶態(tài)

內(nèi)核空間可以訪問(wèn)受保護(hù)的內(nèi)存(32位下高位1G為內(nèi)核空間)化戳,剩下3G為用戶空間

操作系統(tǒng)限制用戶態(tài)不能直接訪問(wèn)硬件設(shè)備,所以數(shù)據(jù)從硬件移動(dòng)到用戶進(jìn)程的內(nèi)存時(shí)需要2步操作埋凯。

image.png

1.3)mmap(內(nèi)存映射)

將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間点楼,實(shí)現(xiàn)文件磁盤地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對(duì)映關(guān)系


image.png
image2.png

2,linux下的5種IO模型

ea103750d79f9799947fdb5a99da11fb.jpg

5種IO模式關(guān)于同步異步白对,阻塞非阻塞的關(guān)系

阻塞 非阻塞
同步 BIO nonblockingIO/多路復(fù)用IO(NIO1.0)
異步 X AIO
1掠廓,BIO:

阻塞當(dāng)前線程,等待數(shù)據(jù)準(zhǔn)備

image.png

2甩恼,nonblockingIO:

image.png

相當(dāng)于輪訓(xùn)蟀瞧,將大片的等待時(shí)間切割成小片沉颂,

3,多路復(fù)用IO(IO mulitplexing)NIO

監(jiān)聽多個(gè)socket悦污,當(dāng)任何一個(gè)數(shù)據(jù)準(zhǔn)備好后就返回铸屉,用戶進(jìn)程再調(diào)用read函數(shù)讀取數(shù)據(jù),極限情況塞关,如果只監(jiān)聽一個(gè)socket那么和BIO是一樣的抬探,只有監(jiān)聽的socket多時(shí),才會(huì)凸顯效率帆赢。

重點(diǎn),后面詳細(xì)說(shuō)明

image2.png

4线梗,信號(hào)驅(qū)動(dòng) I/O

5椰于, asynchronous IO

需要操作系統(tǒng)內(nèi)核支持

image.png

aio目前在linux下存在BUG,使用場(chǎng)景少

3仪搔,為什么說(shuō)JAVA的標(biāo)準(zhǔn)IO是面向流瘾婿,NIO面向緩沖區(qū)

標(biāo)準(zhǔn)IO:

SocketInputStream.read

int read(byte b[], int off, int length, int timeout) throws IOException {

int n;

// EOF already encountered

if (eof) {

return -1;

}

// connection reset

if (impl.isConnectionReset()) {

throw new SocketException("Connection reset");

}

// bounds check

if (length <= 0 || off < 0 || off + length > b.length) {

if (length == 0) {

return 0;

}

throw new ArrayIndexOutOfBoundsException();

}

boolean gotReset = false;

// acquire file descriptor and do the read

FileDescriptor fd = impl.acquireFD();

try {

n = socketRead(fd, b, off, length, timeout);//native函數(shù)

if (n > 0) {

return n;

}

} catch (ConnectionResetException rstExc) {

gotReset = true;

} finally {

impl.releaseFD();

}

/*

* We receive a "connection reset" but there may be bytes still

* buffered on the socket

*/

if (gotReset) {

impl.setConnectionResetPending();

impl.acquireFD();

try {

n = socketRead(fd, b, off, length, timeout);//native函數(shù),這里從內(nèi)核態(tài)中讀取數(shù)據(jù)到數(shù)組b中

if (n > 0) {

return n;

}

} catch (ConnectionResetException rstExc) {

} finally {

impl.releaseFD();

}

}

/*

* If we get here we are at EOF, the socket has been closed,

* or the connection has been reset.

*/

if (impl.isClosedOrPending()) {

throw new SocketException("Socket closed");

}

if (impl.isConnectionResetPending()) {

impl.setConnectionReset();

}

if (impl.isConnectionReset()) {

throw new SocketException("Connection reset");

}

eof = true;

return -1;

}

面向緩沖區(qū)(NIO):

DatagramChannelImpl.receive

private int receive(FileDescriptor fd, ByteBuffer dst)

throws IOException

{

int pos = dst.position();

int lim = dst.limit();

assert (pos <= lim);

int rem = (pos <= lim ? lim - pos : 0);

if (dst instanceof DirectBuffer && rem > 0)

return receiveIntoNativeBuffer(fd, dst, rem, pos);

// Substitute a native buffer. If the supplied buffer is empty

// we must instead use a nonempty buffer, otherwise the call

// will not block waiting for a datagram on some platforms.

int newSize = Math.max(rem, 1);

ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);//申請(qǐng)一塊newSize大小的緩沖區(qū)塊

try {

int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);//數(shù)據(jù)讀取到緩沖區(qū)中烤咧,buffer可以做標(biāo)記偏陪,操作指針等

bb.flip();

if (n > 0 && rem > 0)

dst.put(bb);

return n;

} finally {

Util.releaseTemporaryDirectBuffer(bb);

}

}

channel buffer 說(shuō)明:

http://www.reibang.com/p/052035037297

4,select,poll,epoll詳解

select

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

監(jiān)視所有的readFD,writeFD,exceptFD

select的一 個(gè)缺點(diǎn)在于單個(gè)進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制

poll

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

pollfd并沒(méi)有最大數(shù)量限制

select和poll沒(méi)有太大區(qū)別煮嫌,都是輪訓(xùn)所有的fd/pollfd來(lái)獲取準(zhǔn)備好的fd笛谦,當(dāng)有大量連接的客戶端時(shí),效率會(huì)線性下降

epoll

1)int epfd = epoll_create(intsize); 創(chuàng)建一個(gè)ep句柄(/proc/進(jìn)程id/fd/),用于監(jiān)聽所有注冊(cè)的套接字昌阿,存在一個(gè)紅黑樹的數(shù)據(jù)結(jié)構(gòu)中饥脑,這棵紅黑樹的存儲(chǔ)通過(guò)mmap將內(nèi)核態(tài)和用戶態(tài)共享,減少用戶態(tài)和內(nèi)核態(tài)之間的數(shù)據(jù)交換懦冰,而select/poll每次輪訓(xùn)時(shí)都要將相關(guān)的句柄從內(nèi)核態(tài)拷貝至用戶態(tài)灶轰。

2)int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 添加/修改/刪除注冊(cè)的套接字,由于是在紅黑樹中刷钢,效率較高笋颤,當(dāng)事件添加時(shí),該事件會(huì)與相應(yīng)的設(shè)備(網(wǎng)卡)驅(qū)動(dòng)程序建立回調(diào)連接内地,一旦事件發(fā)生(文件fd改變)相應(yīng)fd會(huì)回調(diào)這個(gè)函數(shù)伴澄,將事件添加到一個(gè)rdllist(雙向鏈表)中

事件類型:

EPOLLIN :表示對(duì)應(yīng)的文件描述符可以讀(包括對(duì)端SOCKET正常關(guān)閉); EPOLLOUT:表示對(duì)應(yīng)的文件描述符可以寫瓤鼻; EPOLLPRI:表示對(duì)應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀(這里應(yīng)該表示有帶外數(shù)據(jù)到來(lái))秉版; EPOLLERR:表示對(duì)應(yīng)的文件描述符發(fā)生錯(cuò)誤; EPOLLHUP:表示對(duì)應(yīng)的文件描述符被掛斷茬祷;

3)int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)

3.1)調(diào)用ep_poll清焕,當(dāng)rdllist為空時(shí)掛起,一直到rdllist不為空時(shí)喚醒

3.2)ep_events_transfer函數(shù)將rdlist中的epitem拷貝到txlist中,并將rdlist清空秸妥。ep_send_events函數(shù)(很關(guān)鍵)滚停,它掃描txlist中的每個(gè)epitem,調(diào)用其關(guān)聯(lián)fd對(duì)用的poll方法粥惧。此時(shí)對(duì)poll的調(diào)用僅僅是取得fd上較新的events(防止之前events被更新)键畴,之后將取得的events和相應(yīng)的fd發(fā)送到用戶空間(封裝在struct epoll_event,從epoll_wait返回)突雪。

epoll.jpg

3起惕,asynchronous IO

IO詳解:https://segmentfault.com/a/1190000003063859#articleHeader14

select、poll咏删、epoll之間的區(qū)別總結(jié)[整理]http://www.cnblogs.com/Anker/p/3265058.html

http://www.cnblogs.com/lojunren/p/3856290.html

http://www.smithfox.com/?e=191

這篇對(duì)IO流操作寫的比較好 http://www.cnblogs.com/hapjin/p/5736188.html

補(bǔ)充:

創(chuàng)建Selectorprovider

當(dāng)linux內(nèi)核>2.6時(shí)使用epoll

public static SelectorProvider create() {

String osname = AccessController.doPrivileged(

new GetPropertyAction("os.name"));

if ("SunOS".equals(osname)) {

return new sun.nio.ch.DevPollSelectorProvider();

}

// use EPollSelectorProvider for Linux kernels >= 2.6

if ("Linux".equals(osname)) {

String osversion = AccessController.doPrivileged(

new GetPropertyAction("os.version"));

String[] vers = osversion.split("\\.", 0);

if (vers.length >= 2) {

try {

int major = Integer.parseInt(vers[0]);

int minor = Integer.parseInt(vers[1]);

if (major > 2 || (major == 2 && minor >= 6)) {

return new sun.nio.ch.EPollSelectorProvider();

}

} catch (NumberFormatException x) {

// format not recognized

}

}

}

return new sun.nio.ch.PollSelectorProvider();

}

select poll模式

int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

通過(guò)程序去控制傳入的監(jiān)控fd

代碼層面監(jiān)視多個(gè)描述符惹想,描述文件越多越慢

nio selector:

http://www.reibang.com/p/0d497fe5484a

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市督函,隨后出現(xiàn)的幾起案子嘀粱,更是在濱河造成了極大的恐慌,老刑警劉巖辰狡,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锋叨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宛篇,警方通過(guò)查閱死者的電腦和手機(jī)娃磺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)些己,“玉大人豌鸡,你說(shuō)我怎么就攤上這事《伪辏” “怎么了涯冠?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)逼庞。 經(jīng)常有香客問(wèn)我蛇更,道長(zhǎng),這世上最難降的妖魔是什么赛糟? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任派任,我火速辦了婚禮,結(jié)果婚禮上璧南,老公的妹妹穿的比我還像新娘掌逛。我一直安慰自己,他們只是感情好司倚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布豆混。 她就那樣靜靜地躺著篓像,像睡著了一般。 火紅的嫁衣襯著肌膚如雪皿伺。 梳的紋絲不亂的頭發(fā)上员辩,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音鸵鸥,去河邊找鬼奠滑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛妒穴,可吹牛的內(nèi)容都是我干的宋税。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼讼油,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弃甥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起汁讼,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阔墩,沒(méi)想到半個(gè)月后嘿架,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啸箫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年耸彪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忘苛。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蝉娜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扎唾,到底是詐尸還是另有隱情召川,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布胸遇,位于F島的核電站荧呐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纸镊。R本人自食惡果不足惜倍阐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逗威。 院中可真熱鬧峰搪,春花似錦、人聲如沸凯旭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至咐蚯,卻和暖如春童漩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背春锋。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工矫膨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人期奔。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓侧馅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親呐萌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子馁痴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • 同步IO和異步IO赠堵,阻塞IO和非阻塞IO分別是什么小渊,到底有什么區(qū)別?不同的人在不同的上下文下給出的答案是不同的茫叭。所...
    Daniel521閱讀 1,377評(píng)論 0 6
  • IO模型介紹 為了更好地了解IO模型酬屉,我們需要事先回顧下:同步、異步揍愁、阻塞呐萨、非阻塞 同步(synchronous)...
    可笑的黑耀斑閱讀 1,187評(píng)論 0 2
  • 同步IO和異步IO烁登,阻塞IO和非阻塞IO分別是什么怯屉,到底有什么區(qū)別?不同的人在不同的上下文下給出的答案是不同的饵沧。所...
    lxqfirst閱讀 2,145評(píng)論 0 47
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口锨络,提供良好的抽象接口。 管理調(diào)度進(jìn)程狼牺,并將多個(gè)進(jìn)程對(duì)硬件...
    drfung閱讀 3,541評(píng)論 0 5
  • python之路——IO模型 IO模型介紹 為了更好地了解IO模型是钥,我們需要事先回顧下:同步掠归、異步缅叠、阻塞、非阻塞 ...
    go以恒閱讀 544評(píng)論 0 2