bootstrap(..); 之前的代码没看懂
bootstrap()代码如下
一开始以为 skynet_context_new() 只是malloc()之类的调用而已
后来再看看 skynet_context_new() 的源码
大概是进行了模块的初始化,并为这个模块创建消息队列, 并放到全局的队列里(注:模块初始化时会将 param 传进去)
之后开启线程,进行消息处理
_start(config->thread);
用GDB调试,看下堆栈
为何会调用到 _launch? 回到前面
调用的流程是这样的
skynet_context_new 会先去 cservice目录下 查找 snlua.so , 然后分别找
snlua_create ---> skynet_module->create
snlua_init ---> skynet_module->init
snlua_release ---> skynet_module->release
这三个函数然后分别赋值给 skynet_module 的 create / init / release
snlua.so 的代码在 service_snlua.c
看 snlua_init() 函数代码就知道它将 skynet_context 的 cb 赋值为 _launch
再看回下面的消息分派 dispatch_message() 里有以下代码, 实际上就是调用了 _launch()
if (!ctx->cb(ctx, ctx->cb_ud, type, msg->session, msg->source, msg->data, sz)) {
skynet_free(msg->data);
}
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 );
}
}
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()之类的调用而已
后来再看看 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;
}
}
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;
}
}
大概是进行了模块的初始化,并为这个模块创建消息队列, 并放到全局的队列里(注:模块初始化时会将 param 传进去)
之后开启线程,进行消息处理
_start(config->thread);
用GDB调试,看下堆栈
#
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
# 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
为何会调用到 _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); // 这里传的参数分别为 snlua bootstrap
if (ctx == NULL) {
skynet_error(NULL, " Bootstrap error : %s\n " , cmdline);
skynet_context_dispatchall(logger);
exit( 1 );
}
}
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); // 这里传的参数分别为 snlua bootstrap
if (ctx == NULL) {
skynet_error(NULL, " Bootstrap error : %s\n " , cmdline);
skynet_context_dispatchall(logger);
exit( 1 );
}
}
调用的流程是这样的
#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
#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 会先去 cservice目录下 查找 snlua.so , 然后分别找
snlua_create ---> skynet_module->create
snlua_init ---> skynet_module->init
snlua_release ---> skynet_module->release
这三个函数然后分别赋值给 skynet_module 的 create / init / release
snlua.so 的代码在 service_snlua.c
看 snlua_init() 函数代码就知道它将 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 ;
}
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() 里有以下代码, 实际上就是调用了 _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
# 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