跳至主要内容

libuv 非阻塞 I/O 概念與面試題解析

📌 1. 基本概念

libuv 是一個 C 語言實作的跨平台非同步 I/O 函式庫,最初為 Node.js 而生,支援 Linux / Windows / macOS。其功能包含事件迴圈(Event Loop)、非同步檔案 I/O、TCP/UDP socket、子行程控制、Thread pool 等。

✅ Node.js 核心將 JavaScript 的執行交給 V8,系統層的非同步操作交給 libuv。

📌 2. libuv 的角色

層級技術功能
JS 執行層V8 引擎執行 JS、處理微任務
非同步層libuv管理非同步任務與事件迴圈
系統層OS真正執行系統呼叫(如 I/O)

📌 3. libuv 如何處理非同步?

✅ 原理說明:

  • JS 呼叫如 fs.readFile() 時,會託管給 libuv
  • libuv 把任務加入其內部事件迴圈
  • 若是檔案/壓縮等耗時操作,會委託 thread pool 執行
  • 結果完成後加入 callback queue,等待事件迴圈處理

📌 4. libuv Thread Pool 機制

預設有 4 個 threads(可透過環境變數 UV_THREADPOOL_SIZE 設定上限為 128)。

常用於:

  • fs.*
  • crypto.*
  • dns.lookup()

❗ 非 I/O 的 JS 運算(如排序)不會自動使用 thread pool。

📌 5. 事件循環(Event Loop)與 libuv 的整合流程

Node.js 事件迴圈分為以下階段(與 libuv 密切關聯):

階段名稱處理對象
timerssetTimeout / setInterval
pending callbacks某些系統操作的回呼
idle, prepare內部使用
pollI/O 事件發生與回應
checksetImmediate
close callbackssocket.on('close')

✅ 每一輪事件循環稱為一個 tick。

Microtasks(如 Promise.then)在每個階段後立即清空。

📌 6. 常見面試題與解析

🧠 Q1:Node.js 是非同步的,那誰在背後幫忙處理?

✅ 建議答法:

是由 libuv 負責抽象出跨平台的非同步執行模型,整合 thread pool 和事件循環,讓 JavaScript 層可以維持非同步的寫法而不阻塞主執行緒。


🧠 Q2:哪些內建模組會使用 libuv 的 thread pool?

類別使用 Thread Pool
檔案系統 fs✅ 是
DNS lookup✅ 是
加解密 crypto✅ 是
網路 socket❌ 否(使用 OS 非同步 API,如 epoll/kqueue)

🧠 Q3:為什麼 setTimeout(fn, 0) 不會立即執行?

✅ 建議答法:

它會排入事件循環的 timers phase,而不是 microtask。真正的執行會等到目前 call stack 清空與 microtask queue 處理完後,才會在下一輪事件迴圈中執行。


🧠 Q4:libuv 如何處理高併發?

✅ 建議答法:

對於 I/O 密集任務,libuv 採非阻塞設計,讓多個任務可同時註冊並在完成後回傳 callback,不需同步等待。對於 CPU 密集任務,則可透過 thread pool 處理,避免阻塞主執行緒。

📘 延伸學習資源