Linux 事件驅動筆記
I/O Model
- Synchronous I/O
- Blocking
- Non-Blocking
- I/O multiplexing
- Asynchronous I/O
Blocking 跟 Non-Blocking 差異只差在選擇!
Blocking 以 read (read from a file descriptor) 來舉例,
從 user space 發出 read (kernel提供的 system call) 之後,
這時候就會切換到 kernel mode,kernel 會依據給定的 file descriptor 去判斷,
這時候就會切換到 kernel mode,kernel 會依據給定的 file descriptor 去判斷,
這個 fd 來自哪裡,接下來等待資料,因為 kernel space 跟 user space 本身就是 isolated,
這樣在 user space 的 process crash,也不會影響到 kernel space,
所以 kernel space 拿到資料之後,因為 isolated 的關係,要將資料複製到 user space 去。
在這個過程中,user space 的 read 基本上就是一直在等結果。
read 如果失敗會有 err number
可以注意
這樣在 user space 的 process crash,也不會影響到 kernel space,
所以 kernel space 拿到資料之後,因為 isolated 的關係,要將資料複製到 user space 去。
在這個過程中,user space 的 read 基本上就是一直在等結果。
read 如果失敗會有 err number
可以注意
- EAGAIN
- EWOULDBLOCK
Non-blocking 就是類似一直來問 read 目前的狀態,
kernel 回到 user space 可能裝置還沒準備好,或是要等之後的操作才會生效,
這時候就會發出 EAGAIN 的錯誤,EAGAIN 不代表是真的錯誤,再試一次可能就可以,
kernel 回到 user space 可能裝置還沒準備好,或是要等之後的操作才會生效,
這時候就會發出 EAGAIN 的錯誤,EAGAIN 不代表是真的錯誤,再試一次可能就可以,
I/O Multiplexing (這個邏輯跟數位邏輯的 mux 很像,故取做 IO multiplexing)
multiplexing => 有多個輸入(input), 可以透過一個 select 去決定輸出
假設 Linux 要等待很多種資料, 就可以用這個概念,去監控哪個 fd 有資料,
有資料的話就挑選出來!
所以 I/O Multiplexing 本質還是 blocking,只是可以一次監聽多個
所以像網頁伺服器要監聽很多個 incoming request,就可以用這種方式處理
- select
- 單個 process 可以被監聽的 fd 數量有限制 (跟這個 /proc/sys/fs/file-max 有關)
- 因為是一個一個詢問(輪詢),所以監聽越多 fd,效能會越不好
- epoll
- 可以監聽的 fd 遠遠比 select or poll 多很多
- 因為不是輪詢的方式,效率會好很多
- 在ET模式下,有資料就會以類似 event 的方式通知
- Edge Trigger (ET)
- 監聽到 fd 從不可讀變成可讀這種狀態變化時馬上通知
- Level Trigger (LT)
- 只要有資料就一直通知
Non-blocking 要一直去問,一直去監聽
Asynchronous 則是完成後有人會通知你!
Application -- 發出request (enqueue) --> ↓
Request list (queue) ←
| request 1 (fd1) |
| request 2 (fd2)|
| request 3 (fd3)|
剩下的就是等 worker 處理完畢之後,發出 signal 通知
AIO 可以想像成就是寄信, send and forget
AIO 可以想像成就是寄信, send and forget
把要求 enqueue 到 kernel
io_uring (liburing)
Submission Queue (SQ)
- 提交
Completion Queue (CQ)
- 完成
Reference:
留言
張貼留言