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 去判斷,
這個 fd 來自哪裡,接下來等待資料,因為 kernel space 跟 user space 本身就是 isolated,
這樣在 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 不代表是真的錯誤,再試一次可能就可以,


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)
      • 只要有資料就一直通知

Asynchronous I/O 如果要發揮的很有效率,一定要 kernel 參與才可以!
Non-blocking 要一直去問,一直去監聽
Asynchronous 則是完成後有人會通知你!




Application  -- 發出request (enqueue) --> ↓
                               Request list (queue) ←
                                | request 1 (fd1) |
                                | request 2 (fd2)|
                                | request 3 (fd3)|

剩下的就是等 worker 處理完畢之後,發出 signal 通知
AIO 可以想像成就是寄信, send and forget
把要求 enqueue 到 kernel

io_uring (liburing)


Submission Queue (SQ)
  • 提交
Completion Queue (CQ)
  • 完成

Reference:

留言

這個網誌中的熱門文章

Grafana K6

[翻譯] 介紹現代網路負載平衡與代理伺服器