1. 程式人生 > >libuv之事件迴圈loop

libuv之事件迴圈loop

libuv強制使用非同步的,事件驅動的程式設計風格。它的核心工作是提供一個event-loop,還有基於I/O和其它事件通知的回撥函式。libuv還提供了一些核心工具,例如定時器,非阻塞的網路支援,非同步檔案系統訪問,子程序等。

在事件驅動程式設計中,程式會關注每一個事件,並且對每一個事件的發生做出反應。libuv會負責將來自作業系統的事件收集起來,或者監視其他來源的事件。這樣,使用者就可以註冊回撥函式,回撥函式會在事件發生的時候被呼叫。event-loop會一直保持執行狀態。用虛擬碼描述如下:

while there are still events to process:
    e = get the next event
    if
there is a callback associated with e: call the callback

系統程式設計中最經常處理的一般是輸入和輸出,而不是一大堆的資料處理。問題在於傳統的輸入/輸出函式(例如readfprintf)都是阻塞式的。實際上,向檔案寫入資料,從網路讀取資料所花的時間,對比cpu的處理速度差得太多。任務沒有完成,函式是不會返回的,所以你的程式在這段時間內什麼也做不了。對於需要高效能的的程式來說,這是一個主要的障礙。

其中一個標準的解決方案是使用多執行緒。每一個阻塞的I/O操作都會被分配到各個執行緒中(或者是使用執行緒池)。當某個執行緒一旦阻塞,處理器就可以排程處理其他需要cpu資源的執行緒。

但是libuv使用了另外一個解決方案,那就是非同步,非阻塞。大多數的現代作業系統提供了基於事件通知的子系統。例如,一個正常的socket上的read呼叫會發生阻塞,直到傳送方把資訊傳送過來。但是,實際上程式可以請求作業系統監視socket事件的到來,並將這個事件通知放到事件佇列中。這樣,程式就可以很簡單地檢查事件是否到來(可能此時正在使用cpu做數值處理的運算),並及時地獲取資料。說libuv是非同步的,是因為程式可以在一頭表達對某一事件的興趣,並在另一頭獲取到資料(對於時間或是空間來說)。它是非阻塞是因為應用程式無需在請求資料後等待,可以自由地做其他的事。libuv的事件迴圈方式很好地與該模型匹配, 因為作業系統事件可以視為另外一種libuv事件. 非阻塞方式可以保證在其他事件到來時被儘快處理(當然還要考慮硬體的能力)。

Note:

我們不需要關心I/O在後臺是如何工作的,但是由於我們的計算機硬體的工作方式,執行緒是處理器最基本的執行單元,libuv和作業系統通常會執行後臺/工作者執行緒, 或者採用非阻塞方式來輪流執行任務。

Bert Belder,一個libuv的核心開發者,通過一個短視訊向我們解釋了libuv的架構和它的後臺工作方式。如果你之前沒有接觸過類似libuv,libev,這個視訊會非常有用。視訊的網址是https://youtu.be/nGn60vDSxQ4

包含了libuv的event-loop的更多詳細資訊:

http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop