启动服务流程分析.txt 2.67 KB
function skynet.launch(...)
	c.command("LAUNCH", table.concat({...}, " "))
	......
end

lua-skynet.c | _command | skynet_command
skynet_server.c | cmd_launch | skynet_context_new

====================================================================

function skynet.newservice(name, ...)
	return skynet.call(".launcher", "lua" , "LAUNCH", "snlua", name, ...)
end

service/launcher.lua

返回 "RESPONSE", skynet.pack

newservice 收到 "RESPONSE"

launch 服务就有所有服务的地址

可以统计所有服务,gc某个服务,stats某个服务

====================================================================

再来看 skynet_context_new

1. 获取 skynet_module
struct skynet_module {
	const char * name; 模块名
	void * module; 模块对应的动态库(snlua, 或者其他动态库)
	skynet_dl_create create; 创建函数
	skynet_dl_init init; 初始化函数
	skynet_dl_release release; 释放函数
	skynet_dl_signal signal; 信号函数
};

2. 调用 M->create() 函数
创建 lua vm
struct snlua {
	lua_State * L;
	struct skynet_context * ctx;
};
构建 snlua 结构

3. 创建并初始化 上下文
struct skynet_context {
	void * instance; snlua结构
	struct skynet_module * mod;
	void * cb_ud;
	skynet_cb cb; callback函数指针
	struct message_queue *queue; 消息队列
	FILE * logfile; 日志输出文件
	char result[32];
	uint32_t handle;
	int session_id;
	int ref;
	bool init;
	bool endless;
	CHECKCALLING_DECL
};
创建消息队列

4. 调用 M->init()函数
设置回调函数
skynet_callback(ctx, l , _launch);
ctx->cb 回调函数 _launch
ctx->cb_ud snlua结构

"REG" 注册
发送第一个消息
skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY, 0, tmp, sz);

调用 _launch 函数
skynet_callback(context, NULL, NULL);
将回调函数清空
接着调用 _init 函数

将 skynet_context 的指针地址 存入 lua 环境中 (通过轻量用户数据来实现)
加载常用库
将 LUA_PATH LUA_CPATH LUA_SERVICE LUA_PRELOAD 写入全局table中
通过 loader.lua 加载所有的lua库

5. 将次级消息队列压入全局消息队列
skynet_globalmq_push

6. 在服务主模块中调用
skynet.start 设置回调函数
c.callback 将 _cb作为键,值lua 回调函数 写入lua环境中
skynet_callback

lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
lua_State *gL = lua_tothread(L,-1);

cb_ud 保存 主线程,主线程不会被回收,生命周期同vm

主线程 栈上永远保存着两个值
traceback
回调函数

调用 回调函数
r = lua_pcall(L, 5, 0, 1);
栈上第一个函数作为 错误处理函数

主线程 调用回调函数 回调函数分配线程去处理 每条消息

7. 错误处理
在 发生错误的 服务 处理

回调函数发生在主线程