==========================================================
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
()