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

Contiki 核心源碼剖析:process 結構體與協程調度機制

     編輯:關於C語言

process 結構體定義

struct process {
    struct process *next;                    // 鏈表指針,串聯所有進程
#if PROCESS_CONF_NO_PROCESS_NAMES
#define PROCESS_NAME_STRING(process) ""
#else
    const char *name;                        // 進程名稱(調試用)
#define PROCESS_NAME_STRING(process) ((process)->name)
#endif
    PT_THREAD((* thread)(struct pt *,       // 協程入口函數指針
                         process_event_t,
                         process_data_t));
    struct pt pt;                            // Protothread 控制塊
    unsigned char state;                     // 狀態:NONE/RUNNING/CALLED
    unsigned char needspoll;                 // 輪詢標誌(優先級提示)
};

關鍵字段深度解讀

1. 鏈表管理

`next` 指針將所有進程串聯為單向鏈表,內核遍歷鏈表進行調度。`PROCESS_CONF_NO_PROCESS_NAMES` 宏可裁剪名稱字段以節省 RAM(極受限平台關鍵)。

2. Protothread 協程機制

PT_THREAD 展開為 `char (* thread)(struct pt *, process_event_t, process_data_t)`:

  • 返回 `char` 而非 `void`:協程通過 **LC(行計數器)跳轉** 實現狀態保持,返回值指示是否繼續調度
  • `struct pt` 僅含 `lc_t lc`(`unsigned short` 行號標記),極輕量
  • **無棧協程**:不保存完整寄存器上下文,**僅保存執行位置**,局部變量**不跨 yield 保持**(除非聲明 `static`)

3. 狀態機

#define PROCESS_STATE_NONE     0  // 未運行/已結束
#define PROCESS_STATE_RUNNING  1  // 正在執行
#define PROCESS_STATE_CALLED   2  // 被調用中(避免重入)

`needspoll`:置 1 表示該進程有事件待處理,調度器優先輪詢,實現**事件驅動**而非純時間片輪轉。

協程寫法範例

PROCESS_THREAD(my_process, ev, data) {
    PROCESS_BEGIN();  // 展開為 switch(pt->lc) { case 0:;

    static struct etimer timer;
    etimer_set(&timer, CLOCK_SECOND*2);

    while(1) {
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
        printf("Hello every 2 seconds\n");
        etimer_reset(&timer);
    }

    PROCESS_END();  // 展開為 return 0; } }
}

關鍵宏:

  • `PROCESS_WAIT_EVENT_UNTIL(cond)` → `do { PT_YIELD(&pt); } while(!(cond))`
  • `PT_YIELD` → 保存 `lc` 返回,下次調度從此處恢復

調度器核心邏輯

void process_run(void) {
    struct process *p = process_list;
    while(p) {
        if (p->state == PROCESS_STATE_RUNNING ||
            (p->needspoll && process_needevents(p))) {
            p->state = PROCESS_STATE_CALLED;
            p->thread(&p->pt, PROCESS_EVENT_POLL, NULL);  // 驅動協程
            p->state = PROCESS_STATE_RUNNING;
        }
        p = p->next;
    }
}

極簡調度:無優先級隊列、無時間片、無搶佔,**協作式輪詢**,適合極低功耗、單棧嵌入式場景。

設計權衡總結

優勢劣勢
極低 RAM 佔用(無獨立棧)無法在阻塞調用中 yield(如 socket 讀寫)
代碼簡潔,無竞態條件長計算任務會阻塞整個系統
天然適合事件驅動模型局部變量不跨 yield 保持,易犯錯

Contiki 的 process 機制是**針對嚴重資源受限設備的優雅妥協**,理解其協程本質與局限,是編寫正確 Contiki 應用的前提。

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