skynet中服务器启动需要使用config配置,这其中设计到了环境变量的设置 和 环境变量的值的获取
在skynet.lua 中的代码
function skynet.getenv(key)
return (c.command("GETENV",key))
end
function skynet.setenv(key, value)
assert(c.command("GETENV",key) == nil, "Can't setenv exist key : " .. key)
c.command("SETENV",key .. " " ..value)
end
从lua代码看,函数接口实际是调用的 c.command 接口, 查看 skynet.lua 文件头定义:
local c = require "skynet.core"
接口来源于 skynet.core 模块中,代码路径: lualib-src/lua-skynet.c
static int
lcommand(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
const char * cmd = luaL_checkstring(L,1);
const char * result;
const char * parm = NULL;
if (lua_gettop(L) == 2) {
parm = luaL_checkstring(L,2);
}
result = skynet_command(context, cmd, parm);
if (result) {
lua_pushstring(L, result);
return 1;
}
return 0;
}
接下来内容主要是分析 lcommand 函数的调用过程。(以 skynet.setenv 为例子)
- cmd = ’GETENV‘
- parm = '我们需要查询的key'
static struct command_func cmd_funcs[] = {
{ "TIMEOUT", cmd_timeout },
{ "REG", cmd_reg },
{ "QUERY", cmd_query },
{ "NAME", cmd_name },
{ "EXIT", cmd_exit },
{ "KILL", cmd_kill },
{ "LAUNCH", cmd_launch },
{ "GETENV", cmd_getenv },
{ "SETENV", cmd_setenv },
{ "STARTTIME", cmd_starttime },
{ "ABORT", cmd_abort },
{ "MONITOR", cmd_monitor },
{ "STAT", cmd_stat },
{ "LOGON", cmd_logon },
{ "LOGOFF", cmd_logoff },
{ "SIGNAL", cmd_signal },
{ NULL, NULL },
};
const char *
skynet_command(struct skynet_context * context, const char * cmd , const char * param) {
struct command_func * method = &cmd_funcs[0];
while(method->name) {
if (strcmp(cmd, method->name) == 0) {
return method->func(context, param);
}
++method;
}
return NULL;
}
在代码中能看到 { “GETENV”, cmd_getenv }, { “SETENV”, cmd_setenv },就是本文讨论的 skynet.getenv 和 skynet.setenv 的底层接口了。
在 skynet_command 函数中,循环查找我们需要执行的命令。找到命令后就调用定义好的函数接口 cmd_getenv 或则 cmd_setenv。
代码路径:skynet-src/skynet_env.c
#include "skynet.h"
#include "skynet_env.h"
#include "spinlock.h"
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <assert.h>
struct skynet_env {
struct spinlock lock;
lua_State *L;
};
static struct skynet_env *E = NULL;
const char *
skynet_getenv(const char *key) {
SPIN_LOCK(E)
lua_State *L = E->L;
lua_getglobal(L, key);
const char * result = lua_tostring(L, -1);
lua_pop(L, 1);
SPIN_UNLOCK(E)
return result;
}
void
skynet_setenv(const char *key, const char *value) {
SPIN_LOCK(E)
lua_State *L = E->L;
lua_getglobal(L, key);
assert(lua_isnil(L, -1));
lua_pop(L,1);
lua_pushstring(L,value);
lua_setglobal(L,key);
SPIN_UNLOCK(E)
}
void
skynet_env_init() {
E = skynet_malloc(sizeof(*E));
SPIN_INIT(E)
E->L = luaL_newstate();
}
这里面代码就比较简单了,就是在lua虚拟机里面设置 和 获取变量。
但这里需要注意的是:
struct skynet_env {
struct spinlock lock;
lua_State *L;
};
skynet中,环境变量是单独使用一个虚拟机保存的环境变量数据。