文前导读
skynet 是一个由云风所写的轻量级在线游戏服务器框架。本文为 skynet 框架源码剖析系列的第三篇文章,主要探讨 skynet 的配置文件加载机制,包含了以下内容:
- main 函数是如何启动配置文件加载的?
- 让代码描述自身:使用 lua 作为配置语言,并利用 lua 的解释器来解析配置文件
- main 函数是如何解析配置文件的?
skynet 中 main 函数的流程
skynet 的 main 函数位于 skynet_main.c 文件当中,其定义如下:
1 | int main(int argc, char *argv[]) { |
使用过 skynet 的人都知道,skynet 在启动时相应的配置文件作为参数传递给 skynet 进程,例如 skynet example/config
。从代码上可以看出,skynet 的 main
函数主要流程可以分为 3 个部分:
- 初始化运行环境,并通过 C API 调用相应的 lua 脚本解析配置文件,然后结果保存在 config 结构体中
- 以 config 为参数启动 skynet 进入事件循环
- 执行 skynet_globalexit() 完成 skynet 的退出准备
使用 lua 语言描述配置文件
在了解 skynet 是如何加载配置文件前,我们先来看看配置文件究竟长什么样?skynet 在 example 目录下提供了示范的 config.path
文件以及 config
文件
1 | --config.path 文件 |
skynet 的配置文件本身使用了 lua 语言来描述对应的选项,而 skynet 也是通过 C API 来调用对应的 lua 脚本对配置文件进行解析。使用 lua 语言来描述配置选项,相较于以普通的文本来描述配置文件有以下几个好处:
- lua 作为一门脚本语言,本身提供了解析器及灵活丰富的语法,不仅表达能力强于文本语言,而且 C/C++ 都为其提供了良好的支持,简单易用
- 使用 lua 语言描述配置文件,则配置文件本身也可以运行。你可以在配置文件中定义并调用函数,要求用户输入数据或者访问系统的环境变量等,这些都是文本语言所难以实现的。
- lua 实现的配置文件可以扩展性强,当需要向配置文件中添加新的配置机制会更加方便。
配置文件解析脚本
这个解析配置文件的脚本的内容则是以 C 字符串的形式保存在 load_config
变量当中。我们将其以 lua 代码的形式展示在下方:
1 | -- load_config 的内容: |
main 函数中解析脚本的流程
在了解了配置文件的内容及 load_config 的解析流程后,我们就可以来分析一下 main
函数加载配置文件的详细过程了
1 | //skynet_env.c |
从上述代码中可以看出,skynet 读取配置文件的大致流程为:先调用 skynet_env_init
函数初始化一个全局的 lua 环境,接着创建一个新的 lua 环境,并在该环境中使用 luaL_loadbufferx
将 load_config 加载进来,然后使用 lua_pushstring
将配置文件 config_file 压入 lua 的虚拟栈中。最后使用 lua_pcall
调用 load_config 脚本完成配置文件的解析。解析完毕后,调用 _init_env
将解析结果保存为环境变量。在需要时调用相关类型的 opt
函数读取相应的配置项。
最后我们来看看 skynet_env
的定义及相应函数的实现:
1 | //skynet_env.c |
- 本文作者: Phoenix
- 本文链接: http://hacker-cube.com/2020/11/04/skynet-源码阅读笔记-——-配置文件的加载/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!