Nonblocking and Asynchronous I/O

Basic Concept

I/O device 的實際動作通常是 asynchronous 的:disk、network、keyboard 都不會保證在 CPU 要求的那一瞬間立刻完成。但 OS 對 application 提供的 system call 可以設計成 blocking、nonblocking、或 asynchronous

這三者都在處理同一個問題:I/O 很慢或不可預測,application 要不要停下來等?

Blocking I/O

Blocking I/O 是最直覺的模型。Application 呼叫 read()write() 後,如果資料還沒 ready,calling thread 會被 OS suspend:

  1. Thread 發出 I/O system call。
  2. Kernel 發現 I/O 不能立即完成。
  3. Thread 從 run queue 移到 wait queue。
  4. Device 完成 I/O 後,interrupt handler / kernel I/O subsystem 喚醒 thread。
  5. Thread 回到 ready queue,之後被 scheduler 選上 CPU 才繼續執行。

Blocking I/O 容易寫,因為程式碼看起來像順序執行;但缺點是 thread 在等待 I/O 期間不能做其他工作。

Nonblocking I/O

Nonblocking I/O 的 system call 不會讓 thread 長時間睡眠。它會立即回傳,並告訴 application 目前能完成多少 I/O。

以 nonblocking read() 為例:

  • 如果 requested bytes 都 available,就回傳全部。
  • 如果只有部分 data available,就回傳部分 bytes。
  • 如果完全沒有 data available,就立即回傳「目前沒有資料」的結果。

Nonblocking I/O 適合不想被單一 I/O request 卡住的程式,例如 GUI 程式同時要處理 keyboard/mouse input 和畫面更新。

Asynchronous I/O

Asynchronous I/O 比 nonblocking I/O 更進一步。Application 發出 request 後 system call 立即回傳,但這個 request 不是只問「現在有多少資料」,而是要求 OS 在未來完整完成一個 I/O operation。完成時,OS 會用某種方式通知 application

也就是說,asynchronous I/O 把「發出 request」和「取得 completion」拆成兩個時間點。

Nonblocking vs Asynchronous

Typesystem call 回傳時 I/O 狀態application 拿到什麼
Blocking I/OI/O 已完成完整結果或 error
Nonblocking I/O不一定完成,只回報目前可做多少目前 available 的資料量
Asynchronous I/O尚未完成也可以回傳未來透過 notification 得知 completion

關鍵差異是:nonblocking read 是「現在有多少給多少」;asynchronous read 是「這個完整 request 之後完成再通知我」。