skynet源代码阅读(1)

2017-11-15  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读