天天看點

一個了解同步異步阻塞非阻塞非常好的解釋

作者:知乎使用者

連結:https://www.zhihu.com/question/19732473/answer/51734090

來源:知乎

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

以linux下 tcp socket程式設計為例:

阻塞就是 recv/read的時候 socket接收緩沖區要是有資料就讀, 沒資料我就一直睡覺賴着不走,直到有資料來了讀完我才走。send/write的時候,要是發送緩沖區滿了,沒有空間繼續發送了我也一直睡覺賴着不走,直到發送緩沖區騰出足夠的空間讓我把資料全部塞到發送緩沖區裡我才走。(當然如果你通過setsockopt設定了讀寫逾時,逾時時間到了還是會傳回-1和EAGAIN,不再睡覺等待)

非阻塞就是recv/read的時候,要是接收緩沖區有資料我就讀完,沒有資料我直接帶着傳回的-1和EGAIN走人,絕不睡覺等待耽誤時間。write/send的時候, 要是發送緩沖區有足夠的空間,就立刻把資料塞到發送緩沖區去,然後走人,如果發送緩存區滿了,空間不足,那直接帶着傳回的-1和EAGAIN走人。

至于IO多路複用,首先要了解的是,作業系統為你提供了一個功能,當你的某個socket接收緩存區有資料可讀,或者發送緩沖區有空間可寫的時候,它可以給你一個通知。這樣當配合非阻塞的socket使用時,隻有當系統通知我哪個描述符可讀了,我才去執行read操作,可以保證每次read都能讀到有效資料而不做純傳回-1和EAGAIN的無用功。寫操作類似。作業系統的這個功能通過select/poll/epoll之類的系統調用函數來使用,這些函數都可以同時監視多個描述符的讀寫就緒狀況,這樣,多個描述符的I/O操作都能在一個線程内完成,這就叫I/O多路複用,這裡的“複用”指的是複用同一個線程。

至于事件驅動,其實是I/O多路複用的一個另外的稱呼。

至于異步同步,我們常見的linux下的網絡程式設計模型大部分都是同步io,以讀操作為例,本質上都是需要使用者調用read/recv去從核心緩沖區把資料讀完再處理業務邏輯。異步io則是核心已經把資料讀好了,使用者直接處理邏輯。異步IO在linux下一般是用aio庫。

繼續閱讀