|
Posted on 2014-11-05 17:44 S.l.e!ep.¢% 閱讀(701) 評(píng)論(0) 編輯 收藏 引用 所屬分類: Skynet
bootstrap(..); 之前的代碼沒看懂
bootstrap()代碼如下
static?void bootstrap(struct?skynet_context?*?logger,?const?char?*?cmdline)?{ ????int?sz?=?strlen(cmdline); ????char?name[sz+1]; ????char?args[sz+1]; ????sscanf(cmdline,?"%s?%s",?name,?args); ????struct?skynet_context?*ctx?=?skynet_context_new(name,?args); ????if?(ctx?==?NULL)?{ ????????skynet_error(NULL,?"Bootstrap?error?:?%s\n",?cmdline); ????????skynet_context_dispatchall(logger); ????????exit(1); ????} }
一開始以為 skynet_context_new() 只是malloc()之類的調(diào)用而已 后來再看看 skynet_context_new() 的源碼
struct?skynet_context?*? skynet_context_new(const?char?*?name,?const?char?*param)?{ ????struct?skynet_module?*?mod?=?skynet_module_query(name);
????if?(mod?==?NULL) ????????return?NULL;
????void?*inst?=?skynet_module_instance_create(mod); ????if?(inst?==?NULL) ????????return?NULL; ????struct?skynet_context?*?ctx?=?skynet_malloc(sizeof(*ctx)); ????CHECKCALLING_INIT(ctx)
????ctx->mod?=?mod; ????ctx->instance?=?inst; ????ctx->ref?=?2; ????ctx->cb?=?NULL; ????ctx->cb_ud?=?NULL; ????ctx->session_id?=?0; ????ctx->logfile?=?NULL;
????ctx->init?=?false; ????ctx->endless?=?false; ????//?Should?set?to?0?first?to?avoid?skynet_handle_retireall?get?an?uninitialized?handle ????ctx->handle?=?0;???? ????ctx->handle?=?skynet_handle_register(ctx); ????struct?message_queue?*?queue?=?ctx->queue?=?skynet_mq_create(ctx->handle); ????//?init?function?maybe?use?ctx->handle,?so?it?must?init?at?last ????context_inc();
????CHECKCALLING_BEGIN(ctx) ????int?r?=?skynet_module_instance_init(mod,?inst,?ctx,?param); ????CHECKCALLING_END(ctx) ????if?(r?==?0)?{ ????????struct?skynet_context?*?ret?=?skynet_context_release(ctx); ????????if?(ret)?{ ????????????ctx->init?=?true; ????????} ????????skynet_globalmq_push(queue); ????????if?(ret)?{ ????????????skynet_error(ret,?"LAUNCH?%s?%s",?name,?param???param?:?""); ????????} ????????return?ret; ????}?else?{ ????????skynet_error(ctx,?"FAILED?launch?%s",?name); ????????uint32_t?handle?=?ctx->handle; ????????skynet_context_release(ctx); ????????skynet_handle_retire(handle); ????????struct?drop_t?d?=?{?handle?}; ????????skynet_mq_release(queue,?drop_message,?&d); ????????return?NULL; ????} }
大概是進(jìn)行了模塊的初始化,并為這個(gè)模塊創(chuàng)建消息隊(duì)列, 并放到全局的隊(duì)列里(注:模塊初始化時(shí)會(huì)將 param 傳進(jìn)去)
之后開啟線程,進(jìn)行消息處理 _start(config->thread);
用GDB調(diào)試,看下堆棧
#0??_init?(l=0x2b98570163a0,?ctx=0x2b98570540f0,?args=0x2b9857099070?"bootstrap",?sz=9)?at?service-src/service_snlua.c:71 #1??0x00002b9857d02469?in?_launch?(context=0x2b98570540f0,?ud=0x2b98570163a0,?type=0,?session=0,?source=16777218,?msg=0x2b9857099070,?sz=9)?at?service-src/service_snlua.c:125 #2??0x0000000000409546?in?dispatch_message?(ctx=0x2b98570540f0,?msg=0x420030e0)?at?skynet-src/skynet_server.c:254 #3??0x00000000004096c4?in?skynet_context_message_dispatch?(sm=0x2b9857016440,?q=0x2b98570530c0,?weight=-1)?at?skynet-src/skynet_server.c:308 #4??0x000000000040a98f?in?_worker?(p=0x7fff54a5f8d0)?at?skynet-src/skynet_start.c:128 為何會(huì)調(diào)用到 _launch? 回到前面
static?void bootstrap(struct?skynet_context?*?logger,?const?char?*?cmdline)?{ ????int?sz?=?strlen(cmdline); ????char?name[sz+1]; ????char?args[sz+1]; ????sscanf(cmdline,?"%s?%s",?name,?args); ????struct?skynet_context?*ctx?=?skynet_context_new(name,?args);?// 這里傳的參數(shù)分別為 snlua?bootstrap ????if?(ctx?==?NULL)?{ ????????skynet_error(NULL,?"Bootstrap?error?:?%s\n",?cmdline); ????????skynet_context_dispatchall(logger); ????????exit(1); ????} } 調(diào)用的流程是這樣的
#0? _open_sym (mod=0x2b9e0a032438) at skynet-src/skynet_module.c:76 #1? 0x0000000000408463 in skynet_module_query (name=0x7fffa16ae600 "snlua") at skynet-src/skynet_module.c:107 #2? 0x0000000000409099 in skynet_context_new (name=0x7fffa16ae600 "snlua", param=0x7fffa16ae5e0 "bootstrap") at skynet-src/skynet_server.c:117 #3? 0x000000000040adda in bootstrap (logger=0x2b9e0a054080, cmdline=0x2b9e0a0aa298 "snlua bootstrap") at skynet-src/skynet_start.c:204 #4? 0x000000000040aedb in skynet_start (config=0x7fffa16ae6d0) at skynet-src/skynet_start.c:232 #5? 0x000000000040751e in main (argc=2, argv=0x7fffa16ae7f8) at skynet-src/skynet_main.c:139
skynet_context_new 會(huì)先去 cservice目錄下 查找 snlua.so , 然后分別找 snlua_create? --->? skynet_module->create snlua_init??? --->? skynet_module->init snlua_release --->? skynet_module->release 這三個(gè)函數(shù)然后分別賦值給 skynet_module 的 create / init / release
snlua.so 的代碼在 service_snlua.c 看 snlua_init() 函數(shù)代碼就知道它將 skynet_context 的 cb 賦值為 _launch
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);? // 這句代碼將 skynet_context 的 cb 賦值為 _launch ??? 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); ????return?0; } 再看回下面的消息分派 dispatch_message() 里有以下代碼, 實(shí)際上就是調(diào)用了 _launch() ??? if (!ctx->cb(ctx, ctx->cb_ud, type, msg->session, msg->source, msg->data, sz)) { ??? ??? skynet_free(msg->data); ??? }
#0??_init?(l=0x2b98570163a0,?ctx=0x2b98570540f0,?args=0x2b9857099070?"bootstrap",?sz=9)?at?service-src/service_snlua.c:71 #1??0x00002b9857d02469?in?_launch?(context=0x2b98570540f0,?ud=0x2b98570163a0,?type=0,?session=0,?source=16777218,?msg=0x2b9857099070,?sz=9)?at?service-src/service_snlua.c:125 #2??0x0000000000409546?in?dispatch_message?(ctx=0x2b98570540f0,?msg=0x420030e0)?at?skynet-src/skynet_server.c:254 #3??0x00000000004096c4?in?skynet_context_message_dispatch?(sm=0x2b9857016440,?q=0x2b98570530c0,?weight=-1)?at?skynet-src/skynet_server.c:308 #4??0x000000000040a98f?in?_worker?(p=0x7fff54a5f8d0)?at?skynet-src/skynet_start.c:128
|