服务ID skynet_handle.c
ID
- ID的定义是一个
uint32_t
。 - ID在一个独立的进程中是唯一的。
- ID在多个Harbor组成的Skynet网中是唯一的。
- ID的高8位是harbor ID 。
- ID的底24为是此服务模块在这个进程中的唯一id。
- 每个ID对应一个独立的服务模块,拥有在此进程中唯一的服务名字。
服务ID管理者
handle_storage 源码
struct handle_name {
char * name;
uint32_t handle;
};
struct handle_storage {
struct rwlock lock;
uint32_t harbor;
uint32_t handle_index;
int slot_size;
struct skynet_context ** slot;
int name_cap;
int name_count;
struct handle_name *name;
};
static struct handle_storage *H = NULL;
结构体解说
-
slot缓存
- slot成员指向一个保存服务上下文指针的缓存。实际上是一个数组,代码实现了数组大小不足的时候的自动扩容(X2)。
- slot_size 保存了slot缓存的当前大小。
- handle_index保存了slot数组的使用大小,slot中的每个服务按照他们install的顺序存放,如果有服务退出,后面的所有服务上下文自动前移。
- harbor 保持次进程的harbor ID。
-
name缓存
- name 指向一个服务名字–ID 组合的数组缓存。 同样具备自动扩容功能(X2)。按照name排序(利用strcmp作为排序函数)。
- name_cap 记录缓存大小
- name_count 记录当前缓存使用大小。
提供接口
// 注册一个服务,返回他的ID
uint32_t skynet_handle_register(struct skynet_context *ctx);
// 利用ID注销一个服务
int skynet_handle_retire(uint32_t handle);
// 注销全部服务
void skynet_handle_retireall();
// 利于ID获取服务上下文指针
struct skynet_context * skynet_handle_grab(uint32_t handle);
// 利用服务名字获取服务ID (二分法)
uint32_t skynet_handle_findname(const char * name);
// 赋予一个ID名字
const char * skynet_handle_namehandle(uint32_t handle, const char *name) ;
// 利用给点harbor id初始化
void skynet_handle_init(int harbor);
服务模块 skynet_module.c
一个可加载卸载的服务模块需要实现的接口
源码
typedef void * (*skynet_dl_create)(void);
typedef int (*skynet_dl_init)(void * inst, struct skynet_context *, const char * parm);
typedef void (*skynet_dl_release)(void * inst);
typedef void (*skynet_dl_signal)(void * inst, int signal);
struct skynet_module {
const char * name;
void * module;
skynet_dl_create create;
skynet_dl_init init;
skynet_dl_release release;
skynet_dl_signal signal;
};
结构体解析
任何一个(c编写并编译为动态链接的.so文件)模块,如果想要被Skynet识别, 需要实现以上四个接口。 假定这个库文件叫做“test_module.so ”则四个接口必须分别为命名为
test_module_create , test_module_init, test_module_release 和 test_module_signal
。一个接口被加载的时候,先调用create接口。返回指针被保存作为这个模块的唯一实例指针。
- init接口接着create调用。返回0意味着init成功。
- release 接口在模块卸载的时候调用。
模块管理者 modules
定义源码
#define MAX_MODULE_TYPE 32
struct modules {
int count;
struct spinlock lock;
const char * path;
struct skynet_module m[MAX_MODULE_TYPE];
};
static struct modules * M = NULL;
结构解析
- m 是一个保存动态加载的这些模块基本的信息的数组。固定大小。可以看到Skynet并不打算让我们大规模接入C服务模块。
- count是当前的使用大小。
- path是默认路径。
- lock是个自旋锁。
提供接口
// 从未被使用 : 插入一个构造好的模块
void skynet_module_insert(struct skynet_module *mod);
// 利用名字查询模块,如果没有加载就尝试加载
struct skynet_module * skynet_module_query(const char * name);
// 调用对应模块的接口
void * skynet_module_instance_create(struct skynet_module *);
int skynet_module_instance_init(struct skynet_module *, void * inst, struct skynet_context *ctx, const char * parm);
void skynet_module_instance_release(struct skynet_module *, void *inst);
void skynet_module_instance_signal(struct skynet_module *, void *inst, int signal);
// 给定路径初始化
void skynet_module_init(const char *path);