skynet源碼分析:運行與主要線程worker

skynet啓動流程

skynet程序只有skynet-src目錄,./skynet ./example/config啓動
skynet_main.c讀取配置文件,設置環境變量,調用skynet_start.c的skynet_start函數bootstrap

skynet_start函數初始基礎服務,調用_start函數啓動_timer線程、socket線程、_monitor線程以及配置的多個_worker線程開始工做api

 

skynet運行機制
skynet每一個服務最重要的是設置一個callback函數,服務向另外一個服務發消息都會壓入這個服務的消息隊列,等待_worker線程從全局隊列取出一個服務的消息隊列,而後再從這個消息隊列取出一個消息使用這個服務的callback處理
遊戲服務器通常會啓動一個socket服務教給gate.so管理,socket服務能夠接受外部msg傳遞到內部服務來處理。

 

monitor

 

skynet對服務的監控作得比較簡陋,從設計原則上來講,這樣作也是對的,由於框架層能作的,基本就是上報和打日誌,上層的業務是變化萬千的,不論怎麼寫,均可能知足不了上層的業務需求。skynet中對服務的監控實如今skynet_monitor.c和skynet_monitor.h中,當服務可能陷入死循環的時候,就打一條日誌。

 

每次消息派發,都會調用skynet_monitor_trigger,一共調兩次,第一次參數source和destination是真實的值,也就是不爲0。第二次調是在消息派發完成的時候,source和destination都賦0。數組

若是第一次trigger調用之後,消息派發遲遲不完成,monitor線程第一次檢查,會將check_version的值賦爲version。而後monitor線程第二次檢查,這個時候version和check_version就會相等,並且這時候destination也不爲0,就會進入釋放目標服務和打印報警的流程。服務器

timer

 

skynet的timer是作遊戲用得比較頻繁的一個功能,分析一下它的源碼仍是有意義的。並且核心的C源碼除了timer和網絡之外,已經基本分析得差很少了。其它都是跟lua c api相關,或者是跟lua交互比較多的。timer的源碼在skynet-timer.c和skynet-timer.h中。
skynet的外部定時器是分爲兩部分存的,一部分存在叫near的數組裏,另外一部分存在一個二維數組裏,分爲四個級別。

skynet中有一個timer線程,每2.5毫秒就更新一下timer中的時間。每次更新都會對一個叫time的計數器作加1操做,因此這個計數器其實能夠看成時間來看待,而後對near數組中的定時器進行觸發。網絡

 

 

1.main函數
main函數是skynet進程的入口點,它須要一個配置文件的路徑做爲參數。main函數先作一些內存分配工做,而後加載配置文件裏的內容。再把配置文件裏的內容設置到lua環境變量_ENV。而後從_ENV裏讀取配置到c配置中。最後調用skynet_start。數據結構

2.skynet_start函數
skynet_start函數根據配置肯定服務是否是之後臺方式啓動,而後初始化timer/socket/module/mq這些數據結構,給它們分配內存,填充一些必要的字段。下一步建立和註冊日誌logger服務,這個logger服務是C層實現的。而後建立註冊snax服務,作bootstrap操做。最後調用start函數。框架

3.start函數
這個函數會啓動timer/socket/monitor/worker線程,timer/socket/monitor線程都只有一個,惟獨worker線程是多個,在配置文件中以thread=num來配置的。若是配置文件中沒有配,就是8個。第個worker線程都有本身的權重值,權重值越大的,給單個服務的時間片越小。socket

線程都啓動完之後,就進入pthread_join,等待線程的終止。全部線程終止之後,skynet就會退出。函數



 

參考:源碼分析

《skynet_summary》

《Skynet框架之菜鳥手冊》

skynet源碼分析(2)--消息隊列mq

相關文章
相關標籤/搜索