skynet lua业务逻辑的启动--skynet.start()

上两篇skynet主体流程, skynet怎么启动lua文件介绍了skynet代码的主体流程,还有怎么启动lua逻辑.

我们知道skynet业务逻辑都是在lua里写的,这样大大提高了开发效率,而且使热更新成为可能,究竟lua层是怎么保证逻辑正常运行,一个服务在lua层的表现形式又是怎么样的呢?这篇将为您讲解.

一个服务在lua层的入口是skynet.start(),他的实现为:

function skynet.start(start_func)
	c.callback(skynet.dispatch_message)    --①
	skynet.timeout(0, function()           --②
		skynet.init_service(start_func)
	end)
end

①这里是在c接口里指定服务的lua层回调函数dispatch_message,上篇我们有讲到过.

②是通过timeout接口来间接执行服务的入口函数 

timeout的实现:

function skynet.timeout(ti, func)
	local session = c.intcommand("TIMEOUT",ti)    -- ①
	assert(session)
	local co = co_create(func)                    -- ②
	assert(session_id_coroutine[session] == nil)
	session_id_coroutine[session] = co
end

 

① 调用c的timeout接口,他会产生一个session id

② 启动协程池,关联func,session Id

c接口的timeout的实现:

1 根据context产生一个该context递增的session id

2 如果参数time==0,产生一条PTYPE_RESPONSE类型的消息压入队列;如果不为0,则增加时间节点

由于上面的参数是0,则产生一条PTYPE_RESPONSE类型的消息,包含了session id

当消息队列捕获并执行该消息的时候,就会调用lua层的回调函数skynet.dispatch_message了,最终调用raw_dispatch_message.它的实现:

local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
	-- skynet.PTYPE_RESPONSE = 1, read skynet.h
	if prototype == 1 then
		local co = session_id_coroutine[session]      ①
		if co == "BREAK" then
			session_id_coroutine[session] = nil
		elseif co == nil then
			unknown_response(session, source, msg, sz)
		else
			session_id_coroutine[session] = nil
			suspend(co, coroutine.resume(co, true, msg, sz))    --②
		end
	else
		local p = proto[prototype]
		if p == nil then
			if session ~= 0 then
				c.send(source, skynet.PTYPE_ERROR, session, "")
			else
				unknown_request(session, source, msg, sz, prototype)
			end
			return
		end
		local f = p.dispatch
		if f then
			local ref = watching_service[source]
			if ref then
				watching_service[source] = ref + 1
			else
				watching_service[source] = 1
			end
			local co = co_create(f)
			session_coroutine_id[co] = session
			session_coroutine_address[co] = source
			suspend(co, coroutine.resume(co, session,source, p.unpack(msg,sz, ...)))
		else
			unknown_request(session, source, msg, sz, proto[prototype].name)
		end
	end
end

timeout产生的消息执行时会走分支①,他的session关联了一个协程,他是在timeout中调用co_create()产生的. co_create()是为了复用协程而产生的,具体请参考这篇:lua协程池

找到session关联的协程后,②开始执行suspend(co, corutine.resume(co,...)),实际上是先执行了corutine.resume(co),启动协程,执行了协程里的函数,即timeout传入的函数.suspend函数用来对协程的调度和调配,为了突出主干,下篇再讲suspend函数.至此一个服务的入口函数就通skynet.start()调用起来了

 

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

 

 

 

 

你可能感兴趣的:(skynet,skynet源码剖析)