作者:shihuaping0918@163.com,转载请注明作者
skynet中的源码已经分析得差不多了,还有启动过程没有分析。skynet的配置文件是以lua格式来写的。使用过skynet的都清楚skynet的启动命令是skynet config_file_name。配置文件名是作为命令行参数传给skynet进程的。
skynet进程启动以后,会读取config文件,然后解析这个lua文件。然后把相关的配置信息设置到lua的环境变量里。
C层读取配置的话是要从lua环境变量里去取的。所以C的配置数据结构的填充,对于某些人来说,是一团迷雾,不直观,而且难懂。
先看看配置文件路径的读取,skynet是用C写的,所以它的入口是main函数,在skynet_main.c中:
int
main(int argc, char *argv[]) {
const char * config_file = NULL ; //配置文件路径
if (argc > 1) {
config_file = argv[1]; //注意写死了,它就是第一个参数
} else {
fprintf(stderr, "Need a config file. Please read skynet wiki : https://github.com/cloudwu/skynet/wiki/Config\n"
"usage: skynet configfilename\n");
return 1;
}
这个配置文件的路径保存在config_file指针上,那么它是怎么加载的呢,这个又要涉及lua c api了。首先,云风写了一段lua代码,硬编码在skynet_main.c文件里,然后调用lua c api的函数去执行这段代码。这段lua代码会加载配置文件。先看一下这段lua代码:
static const char * load_config = "\
local result = {
}\n\
--函数 getenv
--这个getenv是取进程的环境变量,比如$PATH
local function getenv(name) return assert(os.getenv(name), [[os.getenv() failed: ]] .. name) end\n\
--取文件路径分隔符
local sep = package.config:sub(1,1)\n\
--当前路径,linux下就是./
local current_path = [[.]]..sep\n\
--函数 include
local function include(filename)\n\
local last_path = current_path\n\
local path, name = filename:match([[(.*]]..sep..[[)(.*)$]])\n\
if path then\n\
if path:sub(1,1) == sep then -- root\n\
current_path = path\n\
else\n\
current_path = current_path .. path\n\
end\n\
else\n\
name = filename\n