skynet主体流程

1 初始化工作
    锁,线程,信号的处理。


2 加载配置
    skynet会开启一个全局专门用来加载配置的lua虚拟机, 虚拟机加载配置文件,将配置项填充到一个配置数据结构skynet_config中,具体过程请看下篇skynet加载配置文件

3 调用skynet_start(skynet_config*)启动日志模块
a) 根据skynet_config初始化模块路径,time,socket,harbor等。
b) 根据日志配置启动一个logger服务,这是skynet进程创建的第一个服务。

    加载服务的过程是:skynet_module_query('mod_name'),先查找该模块是否已经存在,不存在就根据路径和名字加载该模块,并确定所有的函数地址,放入modules这个全局变量中,他来管理所有的模块加载,调用事宜。

    加载了模块就需要通过skynet_module_instance_create创建一个模块的实例,他会调用模块的create函数,对应各个模块一般就是创建相应的结构体。例如日志模块log结构体有文件句柄,slua模块有lua虚拟机实例等。

    一个服务对应一个skynet_context,一般模块创建时也会创建一个skynet_context,然后进行关联。skynet_context结构体有模块和其实例字段。通过skynet_handle_register为每个skynet_context生成一个全局唯一的handle。然后就是为这个skynet_context创建并关联一个消息队列。

    接下来就是模块实例进行初始化:skynet_module_instance_init(mod, inst, ctx, param)。初始化时带上ctx是为了给他设置回调函数,以及在用skynet_command把全局handle_storage中的ctx.handler绑定一个名字。

    最后就是把生成的消息队列加入到全局队列中,这样消息泵才能一直从里面获取消息。以上就是创建一个服务的过程,代码如下:

struct skynet_context * 
skynet_context_new(const char * name, const char *param) {
	struct skynet_module * mod = skynet_module_query(name);

	if (mod == NULL)
		return NULL;

	void *inst = skynet_module_instance_create(mod);
	if (inst == NULL)
		return NULL;
	struct skynet_context * ctx = skynet_malloc(sizeof(*ctx));
	CHECKCALLING_INIT(ctx)

	ctx->mod = mod;
	ctx->instance = inst;
	ctx->ref = 2;
	ctx->cb = NULL;
	ctx->cb_ud = NULL;
	ctx->session_id = 0;
	ctx->logfile = NULL;

	ctx->init = false;
	ctx->endless = false;
	// Should set to 0 first to avoid skynet_handle_retireall get an uninitialized handle
	ctx->handle = 0;	
	ctx->handle = skynet_handle_register(ctx);
	struct message_queue * queue = ctx->queue = skynet_mq_create(ctx->handle);
	// init function maybe use ctx->handle, so it must init at last
	context_inc();

	CHECKCALLING_BEGIN(ctx)
	int r = skynet_module_instance_init(mod, inst, ctx, param);
	CHECKCALLING_END(ctx)
	if (r == 0) {
		struct skynet_context * ret = skynet_context_release(ctx);
		if (ret) {
			ctx->init = true;
		}
		skynet_globalmq_push(queue);
		if (ret) {
			skynet_error(ret, "LAUNCH %s %s", name, param ? param : "");
		}
		return ret;
	} else {
		skynet_error(ctx, "FAILED launch %s", name);
		uint32_t handle = ctx->handle;
		skynet_context_release(ctx);
		skynet_handle_retire(handle);
		struct drop_t d = { handle };
		skynet_mq_release(queue, drop_message, &d);
		return NULL;
	}
}

 

4 调用bootstrap启动slua模块

bootstrap函数中创建了一个新的服务--slua,过程与上面的一致,只是在初始化slua服务的时候,给他的消息队列中发送了一条消息,参数为'bootstrap',是bootstrap函数传入的。关于这条消息的作用,我们下篇再讲。

5 根据配置线程数开启一系列线程,包括工作线程,监控线程,socket线程等等。工作线程一直不停的抓取消息并执行消息。

6 清理释放工作

 

欢迎加入QQ群 858791125 讨论skynet,游戏后台开发,lua脚本语言等问题。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值