当从终端输入命令“./skynet examples/config”命令时,启动程序skynet,首先调用skynet_main.c文件中的main函数,examples/config将作为argv[1]参数传入。在main函数中主要的工作为:初始化全局信息,加载配置文件,调用skynet_start.c中的skynet_start函数。skynet_start函数的主要的工作为:根据加载的配置信息初始化全局信息,创建一个logger服务,调用bootstrap函数创建一个snlua服务,调用start函数创建一个监测线程、一个定时器线程、一个套接字线程以及配置配的相应数量的工作线程。
skynet_main.c文件中的main函数源码注释
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;
}
luaS_initshr(); //初始化读写锁
skynet_globalinit(); //初始化主线程
skynet_env_init(); //初始化一个全局的Lua环境
sigign(); //忽略SIGPIPE信号
struct skynet_config config;
struct lua_State *L = luaL_newstate(); //新建一个lua状态机
luaL_openlibs(L); // link lua lib
int err = luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t"); //加载load_config中的代码块
assert(err == LUA_OK);
lua_pushstring(L, config_file); //将配置文件的路径压入栈
err = lua_pcall(L, 1, 1, 0); //运行加载的代码块,并将配置文件路径作为参数传入
if (err) {
fprintf(stderr,"%s\n",lua_tostring(L,-1));
lua_close(L);
return 1;
}
_init_env(L); //将配置文件的键值对添加到lua全局信息内
config.thread = optint("thread",8);
config.module_path = optstring("cpath","./cservice/?.so");
config.harbor = optint("harbor", 1);
config.bootstrap = optstring("bootstrap","snlua bootstrap");
config.daemon = optstring("daemon", NULL);
config.logger = optstring("logger", NULL);
config.logservice = optstring("logservice", "logger");
config.profile = optboolean("profile", 1);
lua_close(L); //消耗上面创建的lua状态机
skynet_start(&config); //skynet开始
skynet_globalexit();
luaS_exitshr();
return 0;
}
skynet_start.c文件中的skynet_start函数源码注释
void skynet_start(struct skynet_config * config) {
// register SIGHUP for log file reopen
//log默认是输出到终端的,如果终端关闭则将log输出到文件
struct sigaction sa;
sa.sa_handler = &handle_hup;
sa.sa_flags = SA_RESTART;