最近几周粗略看了 skynet 代码的 C 部分。遇到很多知识点以前只是知道,但并不十分了解,所以这是一个学习的过程。
从 main 函数开始,闷头一阵看下来,着实蛋疼。
当看了 skynet_mq.c 和 skynet_module.c 之后才终于有了头绪。
C 代码通篇下来并没有什么特别的难点。看 Lua 代码的时候,我的头开始大了,我了个擦擦擦,神乎其技啊。
一开始读 Lua 代码时,C 层的东西我也才刚读完,还没有消化好,所以读起来很吃力。
于是,停下来不再继续看代码,而是去云风的博客上看关于 skynet 的文章,并反复思考。那段时间几乎做梦的时候都在想 skynet 的设计。
今天再次捡起 Lua 代码开始读,终于感觉顺畅了很多。
根据默认的配置文件 config,bootstrap.lua 是 skynet 起的第一个 Lua 服务。在这个服务中,skynet 把真正需要的服务开起来,然后这个服务的任务就算完成了,调用 skynet.exit() 结束这个服务。
1 local skynet = require "skynet" 2 local harbor = require "skynet.harbor" 3 require "skynet.manager" -- import skynet.launch, ... 4 local memory = require "memory" 5 6 skynet.start(function() 7 local sharestring = tonumber(skynet.getenv "sharestring" or 4096) 8 memory.ssexpand(sharestring) 9 10 local standalone = skynet.getenv "standalone" 11 12 local launcher = assert(skynet.launch("snlua","launcher")) -- skynet_context_new("snlua","launcher"); 13 skynet.name(".launcher", launcher) 14 15 local harbor_id = tonumber(skynet.getenv "harbor" or 0) 16 if harbor_id == 0 then 17 assert(standalone == nil) 18 standalone = true 19 skynet.setenv("standalone", "true") 20 -- skynet_send(context, 0, ".launcher", 'lua', PTYPE_TAG_ALLOCSESSION, "LAUNCH snlua cdummy", 20) 21 local ok, slave = pcall(skynet.newservice, "cdummy") 22 if not ok then 23 skynet.abort() 24 end 25 skynet.name(".cslave", slave) 26 27 else 28 if standalone then 29 if not pcall(skynet.newservice,"cmaster") then 30 skynet.abort() 31 end 32 end 33 34 local ok, slave = pcall(skynet.newservice, "cslave") 35 if not ok then 36 skynet.abort() 37 end 38 skynet.name(".cslave", slave) 39 end 40 41 if standalone then 42 local datacenter = skynet.newservice "datacenterd" 43 skynet.name("DATACENTER", datacenter) 44 end 45 skynet.newservice "service_mgr" 46 pcall(skynet.newservice,skynet.getenv "start" or "main") 47 skynet.exit() 48 end)
第 12 行,skynet.launch 启动一个 launcher 服务。
第 21/29/34/42/45/46 行,skynet.newservice 其实是发消息给 launcher 服务,这些个服务都是由 launcher 真正启动的。
接下来要好好看看 skynet 中对 Lua 的协程是怎样调度的。