美文网首页
skynet源代码阅读(1)

skynet源代码阅读(1)

作者: 嘴里叼着棒棒糖 | 来源:发表于2017-11-15 12:02 被阅读0次

    启动 skynet 使用的指令 ./skynet example/config 实际上就是调用 skynet-src/skynet_main.c main 函数

    //skynet_main.c
    
    int main(int argc, char *argv[]) {
        //保存config文件地址的变量
        const char * config_file = NULL ;
        if (argc > 1) {
            //读取配置文件config的地址,保存在config_file变量中
            config_file = argv[1];
        } else {
            //不传入config文件地址会提示错误并结束程序
            fprintf(stderr, "Need a config file. Please read skynet wiki : https://github.com/cloudwu/skynet/wiki/Config\n"
                "usage: skynet configfilename\n");
            return 1;
        }
        //初始化操作
        luaS_initshr();
    

    luaS_initshr()
    初始化静态结构体SSM,SSM有个65536大小的数组结构体,对数组中的每个值调用rwlock_init赋值. rwlock.h中:
    如果定义了USE_PTHREAD_LOCK: 则引用pthread.h,使用linux系统自带的线程库里的pthread_mutex_xxxx互斥API。
    如果未定义USE_PTHREAD_LOCK:则利用原子操__sync_lock_test_and_set等来实现。

    #define SHRSTR_SLOT 0x10000
    #define HASH_NODE(h) ((h) % SHRSTR_SLOT)
    #define getaddrstr(ts)  (cast(char *, (ts)) + sizeof(UTString))
    
    struct shrmap_slot {
        struct rwlock lock;
        TString *str;
    };
    
    struct shrmap {
        struct shrmap_slot h[SHRSTR_SLOT];
        int n;
    };
    
    static struct shrmap SSM;
    
    LUA_API void
    luaS_initshr() {
        struct shrmap * s = &SSM;
        int i;
        for (i=0;i<SHRSTR_SLOT;i++) {
            rwlock_init(&s->h[i].lock);
        }
    }
    

    skynet_globalinit()
    全局初始化,为线程特有数据使用pthread_key_create()函数创建一个key,然后使用pthread_setspecific()函数为这个key设置value值

    void skynet_globalinit(void) {
        G_NODE.total = 0;
        G_NODE.monitor_exit = 0;
        G_NODE.init = 1;
        if (pthread_key_create(&G_NODE.handle_key, NULL)) {
            fprintf(stderr, "pthread_key_create failed");
            exit(1);
        }
        // set mainthread's key
        skynet_initthread(THREAD_MAIN);
    }
    

    sigign() 设置信号处理函数,SIG_IGN表示忽略SIGPIPE那个注册的信号。

        struct sigaction sa;
        sa.sa_handler = SIG_IGN;
        sigaction(SIGPIPE, &sa, 0);
        return 0;
    

    必要的数据被定义在一个 skynet-src/skynet_imp.h 中的 skynet_config 结构体内:

    //skynet_imp.h
    
    struct skynet_config {
        int thread;                 //启动工作线程数量,不要配置超过实际拥有的CPU核心数
        int harbor;                 //skynet网络节点的唯一编号,可以是 1-255 间的任意整数。一个 skynet 网络最多支持 255 个节点。每个节点有必须有一个唯一的编号。如果 harbor 为 0 ,skynet 工作在单节点模式下。此时 master 和 address 以及 standalone 都不必设置。
        int profile;                //是否开启统计功能,统计每个服务使用了多少cpu时间,默认开启
        const char * daemon;        //后台模式:daemon = "./skynet.pid"可以以后台模式启动skynet(注意,同时请配置logger 项输出log)
        const char * module_path;   //用 C 编写的服务模块的位置,通常指 cservice 下那些 .so 文件
        const char * bootstrap;     //skynet 启动的第一个服务以及其启动参数。默认配置为 snlua bootstrap ,即启动一个名为 bootstrap 的 lua 服务。通常指的是 service/bootstrap.lua 这段代码。
        const char * logger;        //它决定了 skynet 内建的 skynet_error 这个 C API 将信息输出到什么文件中。如果 logger 配置为 nil ,将输出到标准输出。你可以配置一个文件名来将信息记录在特定文件中。
        const char * logservice;    //默认为 "logger" ,你可以配置为你定制的 log 服务(比如加上时间戳等更多信息)。可以参考 service_logger.c 来实现它。注:如果你希望用 lua 来编写这个服务,可以在这里填写 snlua ,然后在 logger 配置具体的 lua 服务的名字。在 examples 目录下,有 config.userlog 这个范例可供参考。
    };   
    

    完成环境设置 和 配置信息加载 之后调用skynet_start(&config)
    参考资料

    1. pthread_key_t http://www.jianshu.com/p/d52c1ebf808a
    2. http://blog.csdn.net/linshuhe1/article/details/70174698

    相关文章

      网友评论

          本文标题:skynet源代码阅读(1)

          本文链接:https://www.haomeiwen.com/subject/lmucvxtx.html