zoukankan      html  css  js  c++  java
  • skynet源码分析之skynet_module

    skynet_module提供一个模板来实现各种不同类型的c服务,比如,snlua(最常见),logger,gate等。

    先说明两个linux系统函数:

    // dlopen函数用来获取so库的访问句柄。本质是将so库加载到内存中,并返回一个可以访问该内存块的句柄
    void *dlopen(const char *filename, int flags);
    
    //The function dlopen() loads the dynamic shared object (shared library) file named by the null-terminated string filename and returns an opaque "handle" for the loaded object.
    
    
    // dlsym函数,以dlopen返回的handle为第一个参数,获取so库中名称为symbol的函数指针,通过该指针可以获得so库里的函数地址
    void *dlsym(void *handle, const char *symbol);
    
    //The  function  dlsym()  takes a "handle" of a dynamic loaded shared object returned by dlopen(3) along with a
      null-terminated symbol name, and returns the address where that symbol is loaded into memory

    skynet_module的结构如下:

    struct modules {
        int count;
        struct spinlock lock;
        const char * path;// 用c编写的服务编译后so库路经,不配置默认是./cservice/?.so
        struct skynet_module m[MAX_MODULE_TYPE]; //存放服务模块的数组
    };
    
    static struct modules * M = NULL;
    
    
    struct skynet_module { //单个模块结构
        const char * name; //c服务名称,一般是指c服务的文件名
        void * module; //访问so库的dl句柄,通过dlopen获得该句柄
        skynet_dl_create create; //通过dlsym绑定so库中的xxx_create函数,调用create即调用xxx_create接口
        skynet_dl_init init; //绑定xxx_init接口
        skynet_dl_release release; //绑定xxx_release接口
        skynet_dl_signal signal; //绑定xxx_signal接口
    };

     M->path在初始化(skynet_module_init)时赋值,对应配置文件的cpath,不配置默认是./cservice/?.so。

    用c编写的服务编译成so库后放在cpath目录下,当创建一个ctx时(skynet_context_new),通过名称在skynet_module里找对应的module(skynet_module_query),如果M->m存有同名称的module,返回即可。

    如果第一次创建该名称的服务,先找到该名称对应的so库的路径,然后通过dlopen函数获取so库的访问句柄dl(try_open),再通过dlsym函数获取so库中xxx_create, xxx_init, xxx_release, xxx_signal4个函数地址(open_sym),将这些地址赋值给skynet_module->create, skynet_module->init, skynet_module->release, skynet_module->signal。通常一个c服务需要提供这4个接口,定义这些接口时一定要以服务名称为前缀,通过下划线和函数名称连接起来:

    xxx_create:创建ctx过程中调用,通常是申请内存。返回该服务的实例inst,设置ctx->instance=inst,之后init,release,signal都需要用到该实例

    xxx_init:创建ctx期间调用,除了初始化,最主要的工作是向ctx注册callback函数(skynet_callback),之后ctx才能正确的处理收到的消息(调用callback函数)

    xxx_release:释放ctx时调用(skynet_context_release)

    xxx_signal:ctx收到信号时调用

    最后将skynet_module保存到M->m里,之后创建同名称ctx就不用获取so库的访问句柄了。

  • 相关阅读:
    分享几个个人觉得挺漂亮的导航 Jquery
    C#程序打成 一键安装包InstallShield
    腾讯显IP的API
    C#综合揭秘——细说事务
    2012最新JQuery插件
    Flex各种用法及使用技巧一
    win7管理员账户的启用方法
    禁用win7休眠
    win7下移动文件夹
    win7下转移搜狗文件临时文件夹和IE临时文件夹的方法
  • 原文地址:https://www.cnblogs.com/RainRill/p/8270633.html
Copyright © 2011-2022 走看看