啟動 skynet 使用的指令 ./skynet example/config 實際上就是調用 skynet-src/skynet_main.c main 函數
//skynet_main.c
int main(int argc, char *argv[]) {
//保存config文件地址的變量
const char * config_file = NULL ;
if (argc > 1) {
//讀取配置文件config的地址,保存在config_file變量中
config_file = argv[1];
} else {
//不傳入config文件地址會提示錯誤并結束程序
fprintf(stderr, "Need a config file. Please read skynet wiki : https://github.com/cloudwu/skynet/wiki/Config\n"
"usage: skynet configfilename\n");
return 1;
}
//初始化操作
luaS_initshr();
luaS_initshr()
初始化靜態(tài)結構體SSM,SSM有個65536大小的數組結構體,對數組中的每個值調用rwlock_init賦值. rwlock.h中:
如果定義了USE_PTHREAD_LOCK: 則引用pthread.h,使用linux系統(tǒng)自帶的線程庫里的pthread_mutex_xxxx互斥API。
如果未定義USE_PTHREAD_LOCK:則利用原子操__sync_lock_test_and_set等來實現。
#define SHRSTR_SLOT 0x10000
#define HASH_NODE(h) ((h) % SHRSTR_SLOT)
#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString))
struct shrmap_slot {
struct rwlock lock;
TString *str;
};
struct shrmap {
struct shrmap_slot h[SHRSTR_SLOT];
int n;
};
static struct shrmap SSM;
LUA_API void
luaS_initshr() {
struct shrmap * s = &SSM;
int i;
for (i=0;i<SHRSTR_SLOT;i++) {
rwlock_init(&s->h[i].lock);
}
}
skynet_globalinit()
全局初始化,為線程特有數據使用pthread_key_create()函數創(chuàng)建一個key,然后使用pthread_setspecific()函數為這個key設置value值
void skynet_globalinit(void) {
G_NODE.total = 0;
G_NODE.monitor_exit = 0;
G_NODE.init = 1;
if (pthread_key_create(&G_NODE.handle_key, NULL)) {
fprintf(stderr, "pthread_key_create failed");
exit(1);
}
// set mainthread's key
skynet_initthread(THREAD_MAIN);
}
sigign() 設置信號處理函數,SIG_IGN表示忽略SIGPIPE那個注冊的信號。
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, 0);
return 0;
必要的數據被定義在一個 skynet-src/skynet_imp.h 中的 skynet_config 結構體內:
//skynet_imp.h
struct skynet_config {
int thread; //啟動工作線程數量,不要配置超過實際擁有的CPU核心數
int harbor; //skynet網絡節(jié)點的唯一編號,可以是 1-255 間的任意整數。一個 skynet 網絡最多支持 255 個節(jié)點。每個節(jié)點有必須有一個唯一的編號。如果 harbor 為 0 ,skynet 工作在單節(jié)點模式下。此時 master 和 address 以及 standalone 都不必設置。
int profile; //是否開啟統(tǒng)計功能,統(tǒng)計每個服務使用了多少cpu時間,默認開啟
const char * daemon; //后臺模式:daemon = "./skynet.pid"可以以后臺模式啟動skynet(注意,同時請配置logger 項輸出log)
const char * module_path; //用 C 編寫的服務模塊的位置,通常指 cservice 下那些 .so 文件
const char * bootstrap; //skynet 啟動的第一個服務以及其啟動參數。默認配置為 snlua bootstrap ,即啟動一個名為 bootstrap 的 lua 服務。通常指的是 service/bootstrap.lua 這段代碼。
const char * logger; //它決定了 skynet 內建的 skynet_error 這個 C API 將信息輸出到什么文件中。如果 logger 配置為 nil ,將輸出到標準輸出。你可以配置一個文件名來將信息記錄在特定文件中。
const char * logservice; //默認為 "logger" ,你可以配置為你定制的 log 服務(比如加上時間戳等更多信息)。可以參考 service_logger.c 來實現它。注:如果你希望用 lua 來編寫這個服務,可以在這里填寫 snlua ,然后在 logger 配置具體的 lua 服務的名字。在 examples 目錄下,有 config.userlog 這個范例可供參考。
};
完成環(huán)境設置 和 配置信息加載 之后調用skynet_start(&config)
參考資料