天天看點

【Linux】Linux/Unix五種I/O模型

Linux/Unix五種I/O模型

  • 内容來源,侵删。
  • 遊雙-《Linux高性能伺服器程式設計》
  • 牛客網-​​Linux高并發伺服器開發​​

阻塞-blocking

  • 調用者調用了某個函數,然後等待這個函數傳回,在這期間​

    ​什麼都不做​

    ​​,​

    ​不停的去檢查這個函數有沒有傳回​

    ​,應用程式必須等這個函數傳回才能進行下一步的動作。
  • 即,針對阻塞I/O執行的系統調用可能因為無法立即完成而被作業系統​

    ​挂起​

    ​,直到等待的時間發生為止,才可以繼續執行下一步的操作。
  • 可能被阻塞的系統調用包括accept、send、recv、connect。
【Linux】Linux/Unix五種I/O模型

非阻塞-non blocking (NIO)

  • ​非阻塞I/O執行系統調用總是立即傳回,不管事件是否已經發生​

    ​​,若事件沒有發生,則傳回-1,此時可以根據errno區分這兩種情況,對于accept、recv和send、事件未發生時,errno通常被設定成​

    ​EAGAIN​

    ​。
  • 我們隻有在事件已經發生的情況下操作非阻塞I/O,才能提高程式的效率。是以,​

    ​非阻塞I/O通常要和其它I/O通知機制一起使用​

    ​,比如I/O多路複用和SIGIO信号。
【Linux】Linux/Unix五種I/O模型

I/O複用-IO multiplexing

  • ​I/O多路複用是最常用的I/O通知機制​

    ​。
  • 它指的是: ​

    ​應用程式通過I/O複用函數向核心注冊一組事件,核心通過I/O複用函數把其中就緒的事件通知給應用程式​

    ​。
  • 在單程序/線程的情況下,可以檢測多個客戶的事件是否發生。
  • I/O複用函數本身也是阻塞的,它們能提高程式效率的原因在于它們​

    ​可以同時監聽多個I/O事件​

    ​。
  • 單單使用I/O多路複用并不能處理高并發,而要處理高并發還是需要結合多程序/線程。
【Linux】Linux/Unix五種I/O模型

信号驅動-signal driven

  • 為某一程序安裝一個信号處理函數,程序運作,當I/O事件就緒,該程序收到SIGIO信号,然後開始處理I/O事件。
  • 我們可以為目标檔案描述符指定宿主程序,被指定的宿主程序将捕獲到SIGIO信号,當目标問檔案名描述符上有事件發生時,SIGIO信号的信号處理函數将被觸發,我們可​

    ​在該信号處理函數中對目标檔案描述符執行非阻塞I/O操作​

    ​。
  • 核心在第一個階段是​

    ​異步​

    ​​,在第二個階段是​

    ​同步​

    ​​;信号驅動I/O與非阻塞I/O的差別在于它提供了​

    ​消息通知機制​

    ​,不需要使用者程序不斷的輪詢檢查,減少了系統調用的次數,提高了效率。
  • 補充:
  • 同步與異步: ​

    ​同步是執行或調用一個方法時,每次都需要拿到對應的結果才會繼續往後執行;異步與同步相反,它會在執行或調用一個方法後就繼續往後執行,不會等待擷取執行結果。二者的差別就是處理請求發出後,是否需要等待請求結果,再去繼續執行其他操作。​

    ​——來源​​線程與同步異步​​

異步I/O-asynchronous

  • 從理論上來講,阻塞I/O、I/O複用和信号驅動I/O都是​

    ​同步I/O​

    ​模型,因為在這三種I/O模型中,I/O的讀寫操作,都是在I/O事件發生之後,由應用程式來完成的。
  • 對異步I/O而言,使用者可以​

    ​直接對I/O執行讀寫操作​

    ​,這些操作告訴核心使用者讀寫緩沖區的位置,以及I/O操作完成之後核心通知應用程式的方式。(POSIX規範)
  • 在Linux中,每次調用aio_read函數告訴核心描數字緩沖區指針和緩沖區的大小、檔案偏移及通知的方式,然後立即傳回,當核心将資料拷貝到緩沖區後,再通知應用程式。
  • 異步I/O的讀寫操作總是立即傳回,無論I/O是否阻塞,因為​

    ​真正的讀寫操作已由核心接管​

    ​。
  • 對比:
  • 同步I/O模型要求​

    ​使用者代碼自行執行I/O操作​

    ​(将資料從使用者緩沖區拷貝到核心緩沖區,從核心緩沖區拷貝到使用者緩沖區)。
  • 異步I/O則是由​

    ​核心來執行I/O操作​

    ​(即資料在使用者緩沖區域核心緩沖區的移動是由核心在"背景"完成的)。
  • 可以這樣了解:
  • 同步I/O向應用程式通知的是I/O​

    ​就緒事件​

    ​。
  • 異步I/O向應用程式通知的是I/O​

    ​完成事件​

    ​。

繼續閱讀