同步IO哈雏、異步IO载荔、阻塞IO、非阻塞IO之間的聯(lián)系與區(qū)別
轉(zhuǎn)自:https://www.cnblogs.com/euphie/p/6376508.html
POSIX
同步IO凹炸、異步IO戏阅、阻塞IO、非阻塞IO啤它,這幾個詞常見于各種各樣的與網(wǎng)絡(luò)相關(guān)的文章之中饲握,往往不同上下文中它們的意思是不一樣的,以致于我在很長一段時間對此感到困惑蚕键,所以想寫一篇文章整理一下救欧。
POSIX(可移植操作系統(tǒng)接口)把同步IO操作定義為導(dǎo)致進程阻塞直到IO完成的操作,反之則是異步IO
按POSIX的描述似乎把同步和阻塞劃等號锣光,異步和非阻塞劃等號笆怠,但是為什么有的人說同步IO不等于阻塞IO呢?先來說說幾種常見的IO模型吧誊爹。
IO模型
這里統(tǒng)一使用Linux下的系統(tǒng)調(diào)用recv作為例子蹬刷,它用于從套接字上接收一個消息,因為是一個系統(tǒng)調(diào)用频丘,所以調(diào)用時會從用戶進程空間切換到內(nèi)核空間運行一段時間再切換回來办成。默認情況下recv會等到網(wǎng)絡(luò)數(shù)據(jù)到達并且復(fù)制到用戶進程空間或者發(fā)生錯誤時返回,而第4個參數(shù)flags可以讓它馬上返回搂漠。
阻塞IO模型
使用recv的默認參數(shù)一直等數(shù)據(jù)直到拷貝到用戶空間迂卢,這段時間內(nèi)進程始終阻塞。A同學(xué)用杯子裝水桐汤,打開水龍頭裝滿水然后離開而克。這一過程就可以看成是使用了阻塞IO模型,因為如果水龍頭沒有水怔毛,他也要等到有水并裝滿杯子才能離開去做別的事情员萍。很顯然,這種IO模型是同步的拣度。
非阻塞IO模型
改變flags碎绎,讓recv不管有沒有獲取到數(shù)據(jù)都返回,如果沒有數(shù)據(jù)那么一段時間后再調(diào)用recv看看抗果,如此循環(huán)筋帖。B同學(xué)也用杯子裝水,打開水龍頭后發(fā)現(xiàn)沒有水窖张,它離開了幕随,過一會他又拿著杯子來看看……在中間離開的這些時間里蚁滋,B同學(xué)離開了裝水現(xiàn)場(回到用戶進程空間)宿接,可以做他自己的事情赘淮。這就是非阻塞IO模型。但是它只有是檢查無數(shù)據(jù)的時候是非阻塞的睦霎,在數(shù)據(jù)到達的時候依然要等待復(fù)制數(shù)據(jù)到用戶空間(等著水將水杯裝滿)梢卸,因此它還是同步IO。
IO復(fù)用模型
這里在調(diào)用recv前先調(diào)用select或者poll副女,這2個系統(tǒng)調(diào)用都可以在內(nèi)核準(zhǔn)備好數(shù)據(jù)(網(wǎng)絡(luò)數(shù)據(jù)到達內(nèi)核)時告知用戶進程蛤高,這個時候再調(diào)用recv一定是有數(shù)據(jù)的。因此這一過程中它是阻塞于select或poll碑幅,而沒有阻塞于recv戴陡,有人將非阻塞IO定義成在讀寫操作時沒有阻塞于系統(tǒng)調(diào)用的IO操作(不包括數(shù)據(jù)從內(nèi)核復(fù)制到用戶空間時的阻塞,因為這相對于網(wǎng)絡(luò)IO來說確實很短暫)沟涨,如果按這樣理解恤批,這種IO模型也能稱之為非阻塞IO模型,但是按POSIX來看裹赴,它也是同步IO喜庞,那么也和樓上一樣稱之為同步非阻塞IO吧。
這種IO模型比較特別棋返,分個段延都。因為它能同時監(jiān)聽多個文件描述符(fd)。這個時候C同學(xué)來裝水睛竣,發(fā)現(xiàn)有一排水龍頭晰房,舍管阿姨告訴他這些水龍頭都還沒有水,等有水了告訴他射沟。于是等啊等(select調(diào)用中)嫉你,過了一會阿姨告訴他有水了,但不知道是哪個水龍頭有水躏惋,自己看吧幽污。于是C同學(xué)一個個打開,往杯子里裝水(recv)簿姨。這里再順便說說鼎鼎大名的epoll(高性能的代名詞啊)距误,epoll也屬于IO復(fù)用模型,主要區(qū)別在于舍管阿姨會告訴C同學(xué)哪幾個水龍頭有水了扁位,不需要一個個打開看(當(dāng)然還有其它區(qū)別)准潭。
信號驅(qū)動IO模型
通過調(diào)用sigaction注冊信號函數(shù),等內(nèi)核數(shù)據(jù)準(zhǔn)備好的時候系統(tǒng)中斷當(dāng)前程序域仇,執(zhí)行信號函數(shù)(在這里面調(diào)用recv)刑然。D同學(xué)讓舍管阿姨等有水的時候通知他(注冊信號函數(shù)),沒多久D同學(xué)得知有水了暇务,跑去裝水泼掠。是不是很像異步IO怔软?很遺憾,它還是同步IO(省不了裝水的時間啊)择镇。
異步IO模型
調(diào)用aio_read挡逼,讓內(nèi)核等數(shù)據(jù)準(zhǔn)備好,并且復(fù)制到用戶進程空間后執(zhí)行事先指定好的函數(shù)腻豌。E同學(xué)讓舍管阿姨將杯子裝滿水后通知他家坎。整個過程E同學(xué)都可以做別的事情(沒有recv),這才是真正的異步IO吝梅。
總結(jié)
IO分兩階段:
1.數(shù)據(jù)準(zhǔn)備階段
2.內(nèi)核空間復(fù)制回用戶進程緩沖區(qū)階段
一般來講:阻塞IO模型虱疏、非阻塞IO模型、IO復(fù)用模型(select/poll/epoll)苏携、信號驅(qū)動IO模型都屬于同步IO订框,因為階段2是阻塞的(盡管時間很短)。只有異步IO模型是符合POSIX異步IO操作含義的兜叨,不管在階段1還是階段2都可以干別的事穿扳。