日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux网络编程学习】阻塞、非阻塞、同步、异步以及五种I/O模型

發布時間:2023/11/30 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux网络编程学习】阻塞、非阻塞、同步、异步以及五种I/O模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1. 基本概念
    • 1.1 阻塞與非阻塞
    • 1.2 同步與異步
    • 1.3 為什么沒有“異步阻塞”
  • 2. 五種IO模型
    • 2.1 阻塞 blocking
    • 2.2 非阻塞 non-blocking
    • 2.3. IO復用(IO multiplexing)
    • 2.4 信號驅動(signal-driven)
    • 2.5 異步(asynchronous)

1. 基本概念

首先回顧并理解一下網絡IO中阻塞、非阻塞;同步、異步的概念。

首先我們要知道:一個典型的網絡IO接口調用,分為兩個階段,分別是“數據就緒”和“數據讀寫”。
阻塞與非阻塞是“數據就緒”階段的概念,同步與異步是“數據讀寫”階段的概念。

1.1 阻塞與非阻塞

所謂阻塞,就是IO在沒有準備好數據的時候,調用IO方法的線程會被阻塞,直至收到數據時解除阻塞;而非阻塞IO在沒有準備好數據的時候IO方法一樣會返回,線程不會被阻塞。以recv方法為例,我們一般這樣調用:

int size = recv(sockfd, buf, 1024, 0);

我們創建的sockfd默認是阻塞的,那么當執行這個函數時,如果sockfd對應的socket上數據沒有就緒(即TCP接收緩存區中無數據),則該線程會阻塞,再往下的代碼不會執行;但如果我們使用fcntl設置sockfd對應的socket為非阻塞,該socket工作在非阻塞狀態下,那么執行該函數時,無論是否有數據準備好,該函數都會返回,然后我們可以通過返回的size值和errno來判斷是否讀到數據:

size == -1 && errno == EAGAIN: 表示沒有讀到數據,是因為非阻塞才返回;
size == 0:表示對端斷開連接;
size > 0 : 表示讀到數據,size為數據的長度;

1.2 同步與異步

再來說網絡IO的同步和異步。剛才我們討論阻塞和非阻塞時,關注的是數據準備階段且數據沒有準備好的情況,現在我們討論同步和異步,關注的是數據已經準備好(TCP接收緩存區中有數據),進入數據讀寫階段時的情況。

同步:同步表示A向B請求調用一個網絡IO接口時,數據的讀寫都是由請求方A自己來完成的(不管是阻塞還是非阻塞)
比如調用recv方法(recv是同步IO方法)的時候其檢測到數據已經準備好,然后把數據從內核的TCP接受緩存區拷貝到我們傳入的buf(recv方法的第二個參數)中,這一拷貝過程耗費的是調用recv的線程的時間,直至拷貝結束,recv才返回;

異步:異步表示A向B請求調用一個網絡IO接口時,向B傳入請求的事件以及事件發生時通知的方式,A就可以處理其它邏輯了,當B監聽到事件處理完成后,會用事先約定好的通知方式,通知A處理結果。
比如某個應用程序調用了一個異步IO的API來處理數據讀入(如aio_read),那么應用程序只需把需要監聽的sockfd給內核傳入,內核來負責數據的準備和讀入。在此期間,應用程序可以做自己的事情。數據讀入完畢以后,再通過信號等方式來通知應用程序。

1.3 為什么沒有“異步阻塞”

把阻塞、非阻塞,同步、異步兩兩組合有:

  • 同步阻塞
  • 同步非阻塞
  • 異步阻塞
  • 異步非阻塞

其中,所有平時使用的Linux網絡IO的API都是同步的(如write、read、recv等等),我們可以通過設置其關注的socket為阻塞或者非阻塞,這樣就有了同步阻塞和同步非阻塞的API。

但是異步的API一定是非阻塞的,因為異步IO是要讓內核幫我們完成數據的讀寫,讓調用它的應用程序可以去做自己的事情,如果異步的同時又阻塞,那么應用程序無法做自己的事情,異步就失去了意義。

2. 五種IO模型

有了以上的知識鋪墊,再學習Linux的五種IO模型就通暢很多。

2.1 阻塞 blocking

調用者調用了某個函數,等待這個函數返回,期間什么也不做,不停的去檢查這個函數有沒有返回,必須等這個函數返回才能進行下一步動作。下圖以read為例。

2.2 非阻塞 non-blocking

非阻塞等待,每隔一段時間就去檢測IO事件是否就緒。沒有就緒就可以做其他事。非阻塞I/O執行系統調用總是立即返回,不管事件是否已經發生,若事件沒有發生,則返回-1,此時可以根據 errno 區分這兩種情況,對于accept,recv 和 send,事件未發生時,errno 通常被設置成 EAGAIN。

2.3. IO復用(IO multiplexing)

Linux 用 select/poll/epoll 函數實現 IO 復用模型,這些函數也會使進程阻塞,但是和阻塞IO所不同的是這些函數可以同時阻塞多個IO操作。而且可以同時對多個讀操作、寫操作的IO函數進行檢測。直到有數據可讀或可寫時,才真正調用IO操作函數。

2.4 信號驅動(signal-driven)

Linux 用套接口進行信號驅動 IO,安裝一個信號處理函數,進程繼續運行并不阻塞,當IO事件就緒,進程收到SIGIO 信號,然后處理 IO 事件。

注意區分信號驅動和異步IO的區別:信號驅動中,內核在數據準備階段是異步,但在數據讀寫階段是同步,仍然要花費應用程序自己的時間;與非阻塞IO的區別在于它提供了消息通知機制,不需要用戶進程不斷的輪詢檢查,減少了系統API的調用次數,提高了效率。

2.5 異步(asynchronous)

Linux中,可以調用 aio_read 函數告訴內核描述字緩沖區指針和緩沖區的大小、文件偏移及通知的方式,然后立即返回,當內核將數據拷貝到緩沖區后,再通知應用程序。從圖中可以看出,異步IO是內核負責把數據從內核空間拷貝到用戶空間,不耗費應用程序自己的時間,而前面四種IO方式在數據讀寫階段都需要應用程序自己負責。

總結

以上是生活随笔為你收集整理的【Linux网络编程学习】阻塞、非阻塞、同步、异步以及五种I/O模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。