【skynet源码阅读系列】03_skynet_context_new

上一节看了skynet_start() 的一部分代码,那部分代码主要做了下面几件事。

  • 如果当前进程收到 SIGHUP 信号,则调用 handle_hup 函数,将 SIG 设为 1
  • 检查配置文件内的 deamon 配置,这个配置对应一个文件路径,文件内的记录进程的pid号,防止重复启动skynet进程,第一次启动将自动将进程号写入文件。
  • 重定向了文件描述符,把文件描述符0,1,2 重定向到了 /dev/null,相当于当前进程忽略了标准输入,标准输出,标准错误。
  • 初始化了 HARBOR 的值,HARBOR的值为配置文件内 harbor 配置的值左移 24位。
  • 初始化了一个 handle_storage 结构体,结构体内包含一个 harbor 成员,其中限定了 harbor 最高为 0xff, 也就是 (2^8)-1, 所以 harbor 的取值在 1-255 之间,之后再左移 24 位,和 HARBOR 保持一致。
  • 初始化了一个全局消息队列,全局消息队列里的每一个元素都是一个子消息队列,其中子消息队列的元素内包含具体的消息。
  • 初始化了一个 modules 结构体 M,结构体内包含一个 path 成员,保存着配置文件内的 cpath 配置,一个 skynet_module 类型的数组 m, 数组长度为 32。
  • 初始化了定时器模块,暂时不细节功能实现,但是我们知道模块里定时器的时间单位是 1 / 100 秒。
  • 初始化了 socket 模块,暂时不细节,不影响我们捋顺框架。
  • 把配置文件的 profile 配置保存在 G_NODE 中。

以上就是 skynet_start() 前半段代码做的一些事了。

今天的内容主要梳理了一下 skynet_context_new 这个函数都做了什么。

接着 skynet_start() 的内容看:

struct skynet_context *ctx = skynet_context_new(config->logservice, config->logger);
if (ctx == NULL) {
   
    fprintf(stderr, "Can't launch %s service\n", config->logservice);
    exit(1);
}

可以看到,这段代码无非是尝试去创建一个 skynet_context 结构体。

如果创建失败了,整个进程就退出了。

下面我们看看 skynet_context_new() 函数。

struct skynet_context * 
skynet_context_new(const char * name, const char *param) {
   
    struct skynet_module * mod = skynet_module_query(name);

    if (mod == NULL)
        return NULL;

    void *inst = skynet_module_instance_create(mod);
    if (inst == NULL)
        return NULL;
    struct skynet_context * ctx = skynet_malloc(sizeof(*ctx));
    CHECKCALLING_INIT(ctx)

    ctx->mod = mod;
    ctx->instance = inst;
    ATOM_INIT(&ctx->ref , 2);
    ctx->cb = NULL;
    ctx->cb_ud = NULL;
    ctx->session_id = 0;
    ATOM_INIT(&ctx->logfile, (uintptr_t)NULL);

    ctx->init = false;
    ctx->endless = false;

    ctx->cpu_cost = 0;
    ctx->cpu_start = 0;
    ctx->message_count = 0;
    ctx->profile = G_NODE.profile;
    // Should set to 0 first to avoid skynet_handle_retireall get an uninitialized handle
    ctx->handle = 0;    
    ctx->handle = skynet_handle_register(ctx);
    struct message_queue * queue = ctx->queue = skynet_mq_create(ctx->handle);
    // init function maybe use ctx->handle, so it must init at last
    context_inc();

    CHECKCALLING_BEGIN(ctx)
    int r = skynet_module_instance_init(mod, inst, ctx, param);
    CHECKCALLING_END(ctx)
    if (r == 0) {
   
        struct skynet_context * ret = skynet_context_release(ctx);
        if (ret) {
   
            ctx->init = true;
        }
        skynet_globalmq_push(queue);
        if (ret) {
   
            skynet_error(ret, "LAUNCH %s %s", name, param ? param : "");
        }
        return ret;
    } else {
   
        skynet_error(ctx, "FAILED launch %s", name);
        uint32_t handle = ctx->handle;
        skynet_context_release(ctx);
        skynet_handle_retire(handle);
        struct drop_t d = {
    handle };
        skynet_mq_release(queue, drop_message, &d);
        return NULL;
    }
}

好长…

不急,我们一点点看。

struct skynet_module * mod = skynet_module_query(name);
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值