skynet snlua服務(wù)啟動(dòng)流程

snlua_init

skynet前面啟動(dòng)流程類似logger,我們就不贅述了

int
snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
    int sz = strlen(args);
    char * tmp = skynet_malloc(sz);
    memcpy(tmp, args, sz);
    skynet_callback(ctx, l , launch_cb);//注冊(cè)回調(diào)launch_cb
    const char * self = skynet_command(ctx, "REG", NULL);
    uint32_t handle_id = strtoul(self+1, NULL, 16);
    // it must be first message
    skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY,0, tmp, sz);//這里給自己發(fā)了個(gè)消息,用于觸發(fā)第一次的launch_cb
    return 0;
}

然后是第一次launch_cb的時(shí)候可以看到把注冊(cè)的cb取消掉了

static int
launch_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz) {
    assert(type == 0 && session == 0);
    struct snlua *l = ud;
    skynet_callback(context, NULL, NULL);
    int err = init_cb(l, context, msg, sz);
    if (err) {
        skynet_command(context, "EXIT", NULL);
    }

    return 0;
}

那么這時(shí)候就會(huì)產(chǎn)生疑問(wèn)了,那么真相就是skynet.start的時(shí)候調(diào)用了c.callback,我們來(lái)看看 這個(gè)callback做了什么

function skynet.start(start_func)
    c.callback(skynet.dispatch_message)
    init_thread = skynet.timeout(0, function()
        skynet.init_service(start_func)
        init_thread = nil
    end)
end

代碼位置在lua-skynet.c:lcallback

static int
lcallback(lua_State *L) {
    struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
    int forward = lua_toboolean(L, 2);
    luaL_checktype(L,1,LUA_TFUNCTION);
    lua_settop(L,1);// 設(shè)置棧頂大小為1
    struct callback_context * cb_ctx = (struct callback_context *)lua_newuserdatauv(L, sizeof(*cb_ctx), 2);// 創(chuàng)建一個(gè)cb_ctx并壓棧此時(shí)棧大小為2
    cb_ctx->L = lua_newthread(L); //創(chuàng)建一個(gè)協(xié)程并壓棧,此時(shí)棧大小為3
    lua_pushcfunction(cb_ctx->L, traceback);//在協(xié)程中壓入一個(gè)c函數(shù)traceback 此時(shí)cb_ctx->L中的堆棧大小為1
    lua_setiuservalue(L, -2, 1);//設(shè)置第一個(gè)關(guān)聯(lián)uservalue cb_ctx[1] = newthread,此時(shí)L中堆棧大小為2
    lua_getfield(L, LUA_REGISTRYINDEX, "callback_context");//把lua寄存器中 "callback_context"中的值壓入堆棧,此時(shí)L中堆棧大小為3
    lua_setiuservalue(L, -2, 2);//設(shè)置cb_ctx[2] = LUA_REGISTRYINDEX["callback_context"], 此時(shí)堆棧大小為2
    lua_setfield(L, LUA_REGISTRYINDEX, "callback_context");//把cb_ctx存放到LUA_REGISTRYINDEX["callback_context"],此時(shí)L堆棧大小為1
    lua_xmove(L, cb_ctx->L, 1);//把L中第一個(gè)數(shù)據(jù)出棧(也就是入?yún)unction),壓入cb_ctx->L中,此時(shí)L堆棧大小為為0,cb_ctx->L中堆棧大小為2

    skynet_callback(context, cb_ctx, (forward)?(_forward_pre):(_cb_pre));
    return 0;
}

只挑一個(gè)_cb_pre看看
這里首先獲取cb_ctx,然后把 LUA_REGISTRYINDEX["callback_context"]置空,并把_cb設(shè)置為新的cb

static int
_cb_pre(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
    struct callback_context *cb_ctx = (struct callback_context *)ud;
    clear_last_context(cb_ctx->L);
    skynet_callback(context, ud, _cb);
    return _cb(context, cb_ctx, type, session, source, msg, sz);
}

下面來(lái)看看_cb的實(shí)現(xiàn)
還記得之前的最后cb_ctx->L中的堆棧情況嗎
第一層:traceback
第二層:從lua層傳入的回調(diào)function

static int
_cb(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
    struct callback_context *cb_ctx = (struct callback_context *)ud;
    lua_State *L = cb_ctx->L;
    int trace = 1;
    int r;
    lua_pushvalue(L,2);//把lua傳入function壓棧

    lua_pushinteger(L, type);
    lua_pushlightuserdata(L, (void *)msg);
    lua_pushinteger(L,sz);
    lua_pushinteger(L, session);
    lua_pushinteger(L, source);//總共push了5個(gè)參數(shù)

    r = lua_pcall(L, 5, 0 , trace);//執(zhí)行pcall,異常情況下調(diào)用棧第一層的traceback

    if (r == LUA_OK) {
        return 0;
    }
    const char * self = skynet_command(context, "REG", NULL);
    switch (r) {
    case LUA_ERRRUN:
        skynet_error(context, "lua call [%x to %s : %d msgsz = %d] error : " KRED "%s" KNRM, source , self, session, sz, lua_tostring(L,-1));
        break;
    case LUA_ERRMEM:
        skynet_error(context, "lua memory error : [%x to %s : %d]", source , self, session);
        break;
    case LUA_ERRERR:
        skynet_error(context, "lua error in error : [%x to %s : %d]", source , self, session);
        break;
    };

    lua_pop(L,1);

    return 0;
}

skynet 相關(guān)分析完畢

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末艰亮,一起剝皮案震驚了整個(gè)濱河市意述,隨后出現(xiàn)的幾起案子幸冻,更是在濱河造成了極大的恐慌务傲,老刑警劉巖舔株,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件首启,死亡現(xiàn)場(chǎng)離奇詭異房铭,居然都是意外死亡驻龟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門缸匪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)翁狐,“玉大人,你說(shuō)我怎么就攤上這事凌蔬÷独粒” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵龟梦,是天一觀的道長(zhǎng)隐锭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)计贰,這世上最難降的妖魔是什么钦睡? 我笑而不...
    開(kāi)封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮躁倒,結(jié)果婚禮上荞怒,老公的妹妹穿的比我還像新娘。我一直安慰自己秧秉,他們只是感情好褐桌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著象迎,像睡著了一般荧嵌。 火紅的嫁衣襯著肌膚如雪呛踊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天啦撮,我揣著相機(jī)與錄音谭网,去河邊找鬼。 笑死赃春,一個(gè)胖子當(dāng)著我的面吹牛愉择,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播织中,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锥涕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了狭吼?” 一聲冷哼從身側(cè)響起层坠,我...
    開(kāi)封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搏嗡,沒(méi)想到半個(gè)月后窿春,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡采盒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年旧乞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磅氨。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尺栖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烦租,到底是詐尸還是另有隱情延赌,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布叉橱,位于F島的核電站挫以,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏窃祝。R本人自食惡果不足惜掐松,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粪小。 院中可真熱鬧大磺,春花似錦、人聲如沸探膊。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)逞壁。三九已至流济,卻和暖如春锐锣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袭灯。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工刺下, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稽荧。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像工腋,于是被迫代替她去往敵國(guó)和親姨丈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 寫在前面 這篇文章是分析skynet框架擅腰,自己“用”skynet已經(jīng)有一年蟋恬,項(xiàng)目中是以它為底層框架,上層使用lua...
    fooboo閱讀 13,089評(píng)論 1 14
  • Skynet的日志輸出是由service_src/service_logger.c文件實(shí)現(xiàn)的趁冈,用于運(yùn)行Lua腳本的...
    JunChow520閱讀 3,032評(píng)論 0 1
  • skynet內(nèi)部服務(wù)都是由一個(gè)一個(gè)的消息所驅(qū)動(dòng)歼争,每個(gè)服務(wù)的上下文結(jié)構(gòu)體struct skynet_context有...
    Tao_Liang閱讀 1,838評(píng)論 0 0
  • 引言: 一直都是從事客戶端的開(kāi)發(fā)工作,最近抽了點(diǎn)時(shí)間想了解一下服務(wù)器開(kāi)發(fā)的相關(guān)知識(shí)渗勘,一番博客瞎逛之后沐绒,發(fā)現(xiàn)了一個(gè)不...
    linshuhe1閱讀 5,280評(píng)論 0 10
  • skynet 節(jié)點(diǎn)通過(guò)運(yùn)行 skynet 主程序啟動(dòng),必須在啟動(dòng)命令行傳入一個(gè) Config 文件名作為啟動(dòng)參數(shù)旺坠。...
    EternalSunLhx閱讀 2,126評(píng)論 0 1