首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Lighttpd 1.4.20 源碼分析:狀態機(一)核心架構總覽

     編輯:關於.NET

狀態機是 Lighttpd 最核心的部分。它將一個連接在不同時刻劃分為不同狀態,根據當前狀態決定處理邏輯與下一狀態轉換。本文為系列首篇,建立整體認知框架。

狀態機圖譜

Lighttpd 狀態機圖

(源碼 doc/state.dot 可用 dot -Tpng state.dot -o state.png 生成)

狀態枚舉定義

typedef enum {
    CON_STATE_CONNECT,         // 連接建立
    CON_STATE_REQUEST_START,   // 開始讀取請求
    CON_STATE_READ,            // 讀取並解析請求
    CON_STATE_REQUEST_END,     // 讀取請求結束
    CON_STATE_READ_POST,       // 讀取 POST 數據
    CON_STATE_HANDLE_REQUEST,  // 處理請求(核心)
    CON_STATE_RESPONSE_START,  // 開始響應
    CON_STATE_WRITE,           // 寫入響應數據
    CON_STATE_RESPONSE_END,    // 響應結束
    CON_STATE_ERROR,           // 錯誤
    CON_STATE_CLOSE            // 連接關閉
} connection_state_t;

每個 connection 結構體首個成員即此枚舉變量,表示當前狀態。

核心函數:connection_state_machine

int connection_state_machine(server *srv, connection *con) {
    int done = 0, r;
    while (done == 0) {
        size_t ostate = con->state;
        // 大 switch 根據當前狀態執行處理與轉換
        switch (con->state) {
            case CON_STATE_REQUEST_START: /* transient */
            case CON_STATE_REQUEST_END:   /* transient */
            case CON_STATE_HANDLE_REQUEST:
            case CON_STATE_RESPONSE_START:
            case CON_STATE_RESPONSE_END:  /* transient */
            case CON_STATE_CONNECT:
            case CON_STATE_CLOSE:
            case CON_STATE_READ_POST:
            case CON_STATE_READ:
            case CON_STATE_WRITE:
            case CON_STATE_ERROR:         /* transient */
            default: break;
        }
        if (done == -1) { done = 0; }
        else if (ostate == con->state) { done = 1; } // 狀態未變,需等待 I/O
    }
    return 0;
}

關鍵機制:狀態改變則繼續循環處理;狀態不變(需等待 I/O)則 done=1 跳出循環。done==-1 為 HANDLE_REQUEST 特殊情況。

事件驅動與 Joblist 調度

  1. 新連接建立 → connection_set_state(CON_STATE_REQUEST_START) → 呼叫一次 connection_state_machine(首次 READ 幾乎無操作,保持狀態跳出)。
  2. 循環後 switch 將 fd 加入 fdevent 系統監聽 FDEVENT_IN。
  3. 有數據可讀 → connection_handle_fdevent 標記並加入 joblist(作業隊列)。
  4. 主循環遍歷 joblist,對每個連接呼叫 connection_state_machine 真正處理讀取。
  5. 讀完進入 REQUEST_END 解析,有 POST 進 READ_POST,無則進 HANDLE_REQUEST(核心邏輯)。
  6. 處理完 → RESPONSE_START → WRITE(多次寫入,配合 fdevent 監聽 FDEVENT_OUT)。
  7. 寫完 → RESPONSE_END:清理、判斷 keep-alive(是→REQUEST_START,否→CLOSE)。
  8. CLOSE 等待客戶端斷開,執行關閉操作(fd 默認監聽錯誤與掛斷事件)。

連接複用與 Joblist 潛在問題

  • 連接關閉後 connection 結構體不銷毀,留在 server->connections 供下次複用。
  • Joblist 缺陷:in_joblist 標記始終為 0,導致重複加入;處理完未從 joblist 移除指針,造成輕微記憶體洩漏(最新 1.4.26 仍未修復)。

後續文章將詳細剖析各狀態具體處理邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved