skynet源代碼閱讀(1)

啟動 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)
參考資料

  1. pthread_key_t http://www.itdecent.cn/p/d52c1ebf808a
  2. http://blog.csdn.net/linshuhe1/article/details/70174698
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容