スカイネットを1年半使っています。私は断続的に多くのソースコードを読み、いくつかのスカイネットソースコード分析を読みました。彼らは皆とてもよく言った。しかし、分析はコードを理解するためのポイントを与えるためだけのものだと思いますが、他の理解方法を持っている人は誰もいません。私自身の理解も書いています。
以下のトピックを入力してください。
まず第一に、私たちはまだアイデアを持っている必要があります、スカイネットは何をするのか、ユンフェンの前任者によるスカイネットのデザインの概要、そしてウィキはすべて読まれるべきです。次に、トピックを入力します。
私の研究の初めから、私が理解しているC / 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;
}
//这里做一些初始化
luaS_initshr();
skynet_globalinit();
skynet_env_init();
sigign();
struct skynet_config config;
//打开一个lua虚拟机用于解析传入的配置
struct lua_State *L = luaL_newstate();
luaL_openlibs(L); // link lua lib
int err = luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");
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); //这里看函数就知道是初始化环境
//记录配置
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虚拟机
lua_close(L);
//通过配置启动调用skynet_start
skynet_start(&config);
skynet_globalexit();
luaS_exitshr();
return 0;
}
skynet_start.c
skynet_startが行うことは、初期化を継続することです。ここで注意する必要があるのは、ブートストラップです。ここでは、構成を通じて知ることができます。実際、snlua(Cで記述されたモジュール)が開始されます。その後、すべてのluaサービスがsnlua(snlua)を介して開始されます。 luaファイルをロードします)))最初に覚えてから分析します。
void
skynet_start(struct skynet_config * config) {
// register SIGHUP for log file reopen
// 这里处理一些信号的问题。
struct sigaction sa;
sa.sa_handler = &handle_hup;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
sigaction(SIGHUP, &sa, NULL);
//看看是否配置了守护进程
if (config->daemon) {
if (daemon_init(config->daemon)) {
exit(1);
}
}
skynet_harbor_init(config->harbor); // harbor(港口)初始化
skynet_handle_init(config->harbor); // handler初始化,存贮全部的服务句柄
skynet_mq_init(); // 全局队列初始化
skynet_module_init(config->module_path); // C模块初始化
skynet_timer_init(); // 定时器初始化
skynet_socket_init(); // socket初始化
skynet_profile_enable(config->profile);
//启动logger服务
struct skynet_context *ctx = skynet_context_new(config->logservice, config->logger);
if (ctx == NULL) {
fprintf(stderr, "Can't launch %s service\n", config->logservice);
exit(1);
}
skynet_handle_namehandle(skynet_context_handle(ctx), "logger");
//启动配置中的bootstrap服务
bootstrap(ctx, config->bootstrap);
//调用start传入配置线程数量
start(config->thread);
// harbor_exit may call socket send, so it should exit before socket_free
skynet_harbor_exit();
skynet_socket_free();
if (config->daemon) {
daemon_exit(config->daemon);
}
}
次に、ロジック全体の始まりであるstartを呼び出します。次の記事では、最初にブートストラップを分析します。