Skynet's earthshaking-handing control over to Lua
Http://www.outsky.org/code/skynet-lua.html
Sep 7, 2014
In my opinion, an important advantage of Skynet is the high degree of integration with LUA and the ability to write services in Lua. The principle of writing a service in C is simple: by providing the create, init, and release interfaces in the form of a dynamic link library, the main process loads the service as needed, and injects the callback function that handles the message into the main process, so that when the main process sends a message to the service, the message goes into this callback Function.
thus, the most important part of the service is this callback function, if you want to use LUA to write services, how to register the message callback function? and listen to me:-)
Look from Skynet.newservice
From the Skynet example program entry, it is so starting a LUA service:
skynet.newservice("simpledb")
Trace discovery, It finally calls a C export function:
--destination: ". launcher" -- Type:ptype_lua--session:0--message:pack ("LAUNCH", "snlua", "simpledb") c. Send (skynet.ptype_luanilskynet pack ( "snlua" )
The C source of this function is called in the above, meaning that the packet is lualib-src/lua-skynet.c:_send
encapsulated as a message sent to the .launcher
service Processing.
Halfway to kill A. Launcher
next, you'll Find the .launcher
service and see how it handles the Message.
After searching, the Discovery .launcher
Service is service/bootstrap.lua
registered In:
local launcher = skynet.launch("snlua", "launcher")skynet.name(".launcher", launcher)
.launcher
The original service is also written in lua, we do not panic, do not care about these details, keep the mind clear (egg) awake (pain).
Although I do not understand what this skynet.launch
is, but feel very bad look. OK, Take a look inside.
Do not see, a look startled!
originally, It loaded the LUA service and returned the handle of the registered Service.
Looks like it's the key. what are you waiting for?:-)
It calls the C interface skynet-src/skynet_server.c:cmd_launch
:
cmd_launch(ctx, "snlua launcher")
This function is parsed, called by skynet_context_new
:
skynet_context_new("snlua", "launcher")
skynet_context_new
It's simple:
- Get/load Dynamic Library for C service (snlua.so)
- Call the CREATE function () of the dynamic library
snlua_create
to get an instance of the service ( snlua*
)
- Call the init function () of the dynamic library
snlua_init
and pass in the parameter ( "launcher"
)
- Assign to the service
skynet_context
and generate a uniquehandle
- Assigns a message queue to a service and
skynet_context
handle
binds it
- To press Message Queuing into the global message queue
thus, the service Snlua is written in c, and its create and INIT functions are called successively, and the two functions do the initialization of the Service.
structSnlua*Snlua_create(void){struct snlua * l = skynet_malloc (sizeof (* lmemset (l,0,< Span class= "k" >sizeof (*l->l = lua_newstate ( skynet_lallocnull); l;}
It is important to note that the snlua_create
creation of a new lua_State
one ensures that each LUA service has its own independent LUA virtual machine, which does not affect each other.
In our tracking, args is "launcher"IntSnlua_init(structSnlua*L,structSkynet_context*CTx,ConstChar*args) { ... skynet_callback (ctxl _launch); //it must be first Message//handle_id is its own handleskynet_send (ctx0handle_id< Span class= "p", ptype_tag_dontcopy,0, tmpsz); 0;}
Like other C services, snlua_init
it sets its message callback function ( _launch
) so that messages sent to it will be handed over to the _launch
Processing.
It then sends a message to Itself: "launcher"
This message will be _launch
processed:
In our tracking process, args is "launcher"StaticInt_launch(structSkynet_context*Context,void*Ud,IntType,IntSession,uint32_tSourceconst void * msg size_t sz) { struct snlua *l = ud skynet_callback (contextNULL< Span class= "p", null); (lcontextmsgsz); /span>
The callback value of the Snlua service is empty here, so the next message sent to this service will not enter _launch
, what happens after that? Just throw it away? YOU'LL know if you keep up.
StaticInt_init(structSnlua*L,structSkynet_context*CTx,ConstChar*Args,size_tSz){Lua_state*L=L-L;...Lua_pushlightuserdata(L,CTx);Lua_setfield(L,Lua_registryindex,"skynet_context");...ConstChar*Loader=Optstring(CTx, "lualoader" "./lualib/loader.lua" ); r = lual_loadfile (l ,loader) (largssz); //in Our tracking process args for "launcher" r = lua_pcall (l,1,0 ,1) /span>
_init
Make the necessary settings for the new build lua_State
, such as finding the path. And will be skynet_context
pressed into the registry (registry) for later use (in fact, it is required for skynet.so to provide the interface for lua).
It then loads loader.lua
and passes the parameter ( "launcher"
) over.
loader.lua
function is simple: Locate the specified LUA file for the parameter ( "launcher"
) and run it.
well, finally come out, find it now launcher.lua
, and see what It's doing.
It mainly calls these three functions: skynet.register_protocol
, skynet.dispatch
and skynet.start
.
skynet.register_protocol
Records the specified protocol into a single table, which can be found in subsequent names (such as: "lua"
) or ID (e.g.:) of the Protocol skynet.PTYPE_LUA
.
skynet.dispatch
Sets the method for specifying the protocol dispatch
.
skynet.start
The comparison has meaning:
function skynet start (start_func) c callback (dispatch_message) Skynet. Timeout (0function () init_service (start_func) end< Span class= "p" >) end
Before the value of the snlua
callback function is empty, it is now re-assigned, and subsequent messages will be dispatch_message
Processed.
The incoming function is then called skynet.start
. ( skynet.lua
more complicated, It seems necessary to study the study and write a study report, now skip it--)
At this point, the .launcher
service we have followed the end:
- Generate a set of data (skynet_context, handle, message queue, callback, etc.) for yourself through Snlua (c service) and register yourself in the main process to accept message scheduling
- Rescue Snlua's callback into his own Lua Version.
skynet.register_protocol
skynet.dispatch
handling functions for passing and registering some kind of message
Don't forget Beginner's mind
Although the above trace, already can see Skynet earthshaking process, but we start from example skynet.newservice("simpledb")
, so, still have to go back to See.
c.send(".launcher", skynet.PTYPE_LUA, nil, skynet.pack("LAUNCH", "snlua", "simpledb"))
This sentence will be crammed into .launcher
the message queue, which is then dispatch to its skynet.PTYPE_LUA
protocol handler:
--cmd: "LAUNCH"--...: "snlua", "simpledb"Skynet.Dispatch("lua",function(Session,Address,Cmd,...)...LocalF=Command[Cmd]...LocalRet=F(Address,...)...End)--service: "snlua"--...: "simpledb"functionCommand.LAUNCH(_,Service) launch_service (service ) end--service: "snlua" --...: "simpledb" local Span class= "k" >function launch_service (service ) local inst = skynet. Launch (serviceparam) end
see, eventually returned to the above followed skynet.launch
, but the last pass is the "launcher"
biography is "simpledb"
.
The result is the same, through the snlua, register themselves to the main process, and then secretly the message callback function for their own.
Summarize
- By
skynet.newservice
loading a LUA service
- Snlua helps the LUA service do some of the underlying work
- Generate a separate
lua_State
- Generates a
skynet_context
- Assign a
handle
- To generate a private message queue
skynet_context
and Message Queuing by handle
associating
- Transferring message callbacks from Snlua to the LUA layer (
skynet.lua:dispatch_message
)
Related reading
- Skynet message queuing-storage and distribution of messages
[turn]skynet earthshaking-give control to Lua