关闭

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

744人阅读 评论(0) 收藏 举报
分类:

服务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
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:74871次
    • 积分:1692
    • 等级:
    • 排名:千里之外
    • 原创:80篇
    • 转载:13篇
    • 译文:3篇
    • 评论:13条
    最新评论