skynet源码学习-skynet_env守护进程
skynet源码学习-skynet_env守护进程
- 核心设计目标
- 核心数据结构分析
- 接口详解
- 设计优势分析
- 在Skynet框架中的作用
核心设计目标
提供线程安全的全局配置存储,支持在C层和Lua层之间共享配置信息
核心数据结构分析
struct skynet_env
struct skynet_env {struct spinlock lock; // 自旋锁,保证线程安全lua_State *L; // 专用的Lua状态机,用于存储环境变量
};
接口详解
- void skynet_env_init()
void
skynet_env_init() {E = skynet_malloc(sizeof(*E));SPIN_INIT(E)E->L = luaL_newstate();
}
-
功能:初始化环境变量系统
-
工作流程:
-
关键特性:
- 创建轻量级Lua VM(无标准库)
- 全局单例模式(static struct skynet_env *E = NULL;)指向skynet_env结构体。在模块初始化时创建
- 线程安全初始化
- void skynet_setenv(const char *key, const char *value)
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) // 解锁
}
- 功能:设置环境变量
- 设计特点:
- 键唯一性:不允许覆盖已存在键,断言当前键的值必须为nil(即不允许重复设置,若已经存在则报错)
- 线程安全:自旋锁保护
- 轻量存储:使用Lua全局变量表
- const char * skynet_getenv(const char *key)
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;
}
-
功能:获取环境变量值
-
工作流程:
-
注意事项:
- 返回的字符串指针生命周期由Lua VM管理
- 非线程安全指针(调用者应复制使用)
- 键不存在时返回NULL
设计优势分析
- 线程安全设计
SPIN_LOCK(E)
// 临界区操作
SPIN_UNLOCK(E)
- 优势:
- 支持多线程并发访问
- 自旋锁替代互斥锁(适合短临界区)
- 避免配置读取冲突
- 轻量级Lua VM集成
- VM配置:
- luaL_newstate() 创建纯净状态机
- 不加载任何标准库(最小开销)
- 跨层共享
- 架构设计:
+-----------------+ +-----------------+
| C层服务 | <--> | skynet_env |
+-----------------+ +--------+--------+^
+-----------------+ |
| Lua层服务 +---------------+
+-----------------+ (通过C-API)
- 优势:
- 统一配置入口
- 避免重复存储
- 支持C/Lua服务共享配置
- 安全断言机制
lua_getglobal(L, key);
assert(lua_isnil(L, -1)); // 确保键不存在
- 优势:
- 防止配置被意外覆盖
- 早期发现重复设置错误
- 保证配置一致性
在Skynet框架中的作用
-
服务间共享数据
-
启动流程关键组件