天天看點

zebra線程管理源碼簡析

==========================================================

1 zebra線程機制概述

zebra這個軟體包整體結構大緻可分為兩大塊:協定子產品和守護程序子產品。協定子產品實作各協定的功能,各協定以子子產品的形式加載到zebra中;守護程序子產品的功能主要是管理各協定的信令傳輸、表項操作、系統操作調用等事務,為各協定提供底層資訊以及相關的硬體處理等功能支援。Zebra與各協定的互動采用的是C-S模式,在每個協定子子產品中均有一個Client端與守護程序子產品中的Server端互動,它們所使用的socket為zebra内部使用的socket,不與外部互動。

zebra中的線程是分隊列排程的,每個隊列以一個連結清單的方式實作。線程隊列可以分成五個隊列:event、timer、ready、read、write。隊列的優先級由高到低排列。但是,read和write隊列并不參與到優先級的排列中,實際操作時,如果read和write隊列中的線程就緒,就加入ready隊列中,等待排程。排程時,首先進行event隊列中線程的排程,其次是timer和ready。

實際上,zebra中的線程是“假線程”,它并沒有實作線程中的優先級搶占問題。在zebra的線程管理中,有個虛拟的時間軸,必須等前一時間的線程處理完,才看下一時間的線程是否觸發。由于電腦處理速度較快且處理每個線程的時間間隔較小,是以處理其多線程來可以打到類似“并行處理”的效果。

zebra源碼中有關線程管理的各個函數放置于zebra-0.95a\lib檔案夾的thread.h和thread.c兩個檔案中。

連結位址2 線程管理源碼分析

連結位址2.1 重要結構體介紹

連結位址2.1.1 thread

這是線程隊列中每一個單個線程的代碼描述,線程隊列被描述成雙向連結清單的形式,thread結構體是雙向連結清單的元素。共有六種線程:read、write、timer、event、ready、unused。是以,線程隊列也有六種。

struct thread

{

unsigned char type;        /* thread類型,共有六種 */

struct thread *next;        /* 指向下一thread的指針,雙向連結清單 */

struct thread *prev;        /*指向前一thread的指針*/

struct thread_master *master;      /* 指向該thread所屬thread_master結構體的指針 */

int (*func) (struct thread *); /* event類型thread的函數指針 */

void *arg;               /* event類型thread的參數 */

union {

    int val;                /* event類型thread的第二個參數*/

    int fd;                  /* read/write類型thread相應的檔案描述符 */

    struct timeval sands;   /* 該thread的剩餘時間,timeval類型,此結構體定義在time.h中,有兩個元素,秒和微秒 */

} u;

RUSAGE_T ru;                    /* 詳細用法資訊,RUSAGE這個宏在該thread有用法描述時定義為rusage類型,描述其詳細程序資源資訊,沒有用法描述時定義為timeval類型 */

};

連結位址2.1.2 thread_list

一個thread_list結構體描述一個thread雙向連結清單,也即一個程序隊列。

struct thread_list

{

struct thread *head;/* 該線程隊列頭指針 */

struct thread *tail; /* 該線程隊列尾指針 */

int count; /* 該線程隊列元素數目 */

};

連結位址2.1.3 thread_master

總的線程管理結構體,裡面存有六種線程隊列,三種檔案描述符以及占用空間資訊。

struct thread_master

{

//六種線程隊列

struct thread_list read;

struct thread_list write;

struct thread_list timer;

struct thread_list event;

struct thread_list ready;

struct thread_list unuse;

//三種檔案描述符

fd_set readfd;

fd_set writefd;

fd_set exceptfd;

//該thread_master所占空間大小

unsigned long alloc;

};

1.1 相關函數簡介

下面給出了zebra關于線程管理的相關函數的簡要功能介紹。

連結位址1.1.1 thread_master_create

()

為建立一個新的thread_master結構體動态開辟一塊記憶體空間。

連結位址1.1.2 thread_list_add

()

在list雙向連結清單尾部插入一個新的thread。

連結位址1.1.3 thread_list_add_before

()

在函數參數point所指向的thread前面插入一個新的thread。

連結位址1.1.4 thread_list_delete

()

删除參數中指定的thread。

連結位址1.1.5 thread_add_unuse

()

向指定thead_master中的unused連結清單尾部插入新thread。

連結位址1.1.6 thread_list_free

()

從記憶體中釋放掉指定thread_master中的指定thread連結清單所占空間。

連結位址1.1.7 thread_master_free

()

徹底釋放指定thread_master所占記憶體空間。

連結位址1.1.8 thread_trim_head

()

若指定thread連結清單中非空,删除該連結清單頭指針所指thread,并将其傳回,即從線程隊列中取出一個線程。

連結位址1.1.9 thread_empty

()

判斷指定thread連結清單是否為空。

連結位址1.1.10 thread_timer_remain_second

()

得到指定線程的剩餘時間。

連結位址1.1.11 thread_get

()

若指定thread_master中的unuse連結清單非空,從該隊列中取出一個thread,根據參數初始化并傳回之。否則,給該thread_master多開辟一塊空間給新的thread,根據參數初始化該thread并傳回之。

連結位址1.1.12 thread_add_read

()

根據所給參數在指定thread_master中添加并初始化一個read類型的thread并傳回之。

連結位址1.1.13 thread_add_write

()

根據所給參數在指定thread_master中添加并初始化一個write類型的thread并傳回之。

連結位址1.1.14 thread_add_timer

()

根據所給參數在指定thread_master中添加并初始化一個timer類型的thread。若timer連結清單不要求排序,則直接傳回新thread,若要求排序,則将新thread插入到隊列的相應位置後再傳回之。

連結位址1.1.15 thread_add_event

()

根據所給參數在指定thread_master中添加并初始化一個event類型的thread并傳回之。

連結位址1.1.16 thread_cancel

()

删除指定thread,删除後将其類型置為THREAD_UNUSED,并将其插入到該thread_master的unuse連結清單中。

連結位址1.1.17 thread_cancel_event

()

将指定thread_master的event連結清單中與參數中arg相比對的thread删除。

連結位址1.1.18 thread_timer_wait

()

找出指定thread_master的timer連結清單中最小的剩餘時間并将其傳回。

連結位址1.1.19 thread_run

()

将指定thread的值賦給thread類型的fetch,然後将其類型置為THREAD_UNUSED,并将其插入unuse連結清單,傳回fetch。

連結位址1.1.20 thread_process_fd

()

将指定thread連結清單中的元素取出插入到該thread_master的ready連結清單中,傳回該連結清單中插入元素的個數。

連結位址1.1.21 thread_fetch

()

若指定thread_master的event隊列非空取出其頭元素并用run函數處理。取出并用run函數處理timer隊列中每一個之前建立的線程。若指定thread_master的ready隊列非空取出其頭元素并用run函數處理。拷貝該thread_master的檔案描述符。将read和write連結清單插到ready連結清單中,再從ready連結清單取頭元素用run函數處理。如此無限循環下去直到所有程序都處理完。

連結位址1.1.22 thread_consumed_time

()

得到該程序所耗費的時間。

連結位址1.1.23 thread_call

()

連結位址1.1.24 thread_execute

()

繼續閱讀