Skynet 源码学习 -- 服务ID skynet_handle.c , 服务模块skynet_module.c

服务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);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值