同步和異步、阻塞和非阻塞


首先說明我對這些概念也不是很清楚,以下內容是我做的一些理事。

同步和異步、阻塞和非阻塞這是兩組概念,說的是不同的事情,同步和阻塞沒有必然的聯系,異步和非阻塞也沒有必然的聯系。同步和異步是只跟IO操作過程中進程的狀態變化有關。阻塞和非阻塞就是進程的兩種狀態。比如你去銀行,排除的話就是一種同步的方式,叫號的話就是異步的方式。排隊必須自己看着什么時候輪到自己,而叫號則不必,輪到你的時候會觸發一個事件,或者說你會收到一個信號,別人會叫你。不管是排除還是叫號,如果你在等待的過程中不能做其他事情,那就是阻塞模式,否則就是非阻塞模式。同步的時候可以有阻塞和非阻塞,異步的時候也可以有阻塞和非阻塞。

阻塞 I/O

Linux下的I/O操作默認是阻塞I/O,即open和socket創建的I/O都是阻塞I/O。當讀寫操作沒有完成時,函數就不會返回,進程一直阻塞在那里。

非阻塞I/O    

非阻塞模式的使用並不普遍,因為非阻塞模式會浪費大量的CPU資源。

網絡編程時listen,recvfrom,connect都會引起阻塞。非阻塞IO通常應用於網絡編程中,IO請求時加上O_NONBLOCK一類的標志位,函數立刻返回,IO沒有就緒會返回錯誤,需要請求進程主動輪詢不斷發IO請求直到返回正確
比如調用recvfrom時,如果系統還沒有接收到網絡數據,內核馬上返回一個 EWOULDBLOCK的錯誤。

 當一個應用程序使用了非阻塞模式的套接字,它需要使用一個循環來不停地測試是否一個文件描述符有數據可讀(稱做 polling(輪詢))。應用程序不停的 polling 內核來檢查是否 I/O操作已經就緒。這將是一個極浪費 CPU資源的操作。這種模式使用中不是很普遍。

I/O多路復用

針對批量IP操作時,使用I/O多路復用,非常有好。

在使用 I/O 多路技術的時候,我們調用 select()函數和 poll()函數或epoll函數(2.6內核開始支持),在調用它們的時候阻塞。
當我們調用 select函數阻塞的時候,select 函數等待數據報套接字進入讀就緒狀態。當select函數返回的時候, 也就是套接字可以讀取數據的時候。 這時候我們就可以調用 recvfrom函數來將數據拷貝到我們的程序緩沖區中。
IO復用同非阻塞IO本質一樣,不過利用了新的select系統調用,由內核來負責本來是請求進程該做的輪詢操作。看似比非阻塞IO還多了一個系統調用開銷,不過因為可以支持多路IO,才算提高了效率。 多路復用的高級之處在於: 它能同時等待多個文件描述符,而這些文件描述符(套接字描述符)其中的任意一個進入讀就緒狀態,select()函數就可以返回。

異步I/O

      當我們運行在異步 I/O 模式下時,我們如果想進行 I/O 操作,只需要告訴內核我們要進行 I/O 操作,然后內核會馬上返回。具體的 I/O 和數據的拷貝全部由內核來完成,我們的程序可以繼續向下執行。當內核完成所有的 I/O 操作和數據拷貝后,內核將通知我們的程序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM