首先看skynet的启动,函数入口在 skynet_main.c 的main(),其中最重要的是:

        skynet_start(&config);

在skynet_start中做了两个启动:

        //启动了snlau服务,然后加载launch服务
bootstrap(ctx, config->bootstrap);
//创建monitor,timer,socket,worker线程等
start(config->thread);

下面我们逐步跟进函数

    static void
bootstrap(struct skynet_context * logger, const char * cmdline) {
...
sscanf(cmdline, "%s %s", name, args);
struct skynet_context *ctx = skynet_context_new(name, args);
...
}

这里的cmdline就是 config配置里面的bootstrap那行,默认是为 "snlua bootstrap"

所以实际执行的是 skynet_context_new("snlua","bootstrap")
这里的skynet_context_new是很重要的一个函数,skynet每个lua服务创建,都是使用它来执行的。

    skynet_context_new(const char * name="snlua", const char *param="bootstrap") {
//查询mod对象是否已存在,不存在就根据name查找文件加载创建
struct skynet_module * mod = skynet_module_query(name="snlua");
...
//调用mod的create()方法,这里调用了 snlua_create
void *inst = skynet_module_instance_create(mod);
//为lua服务new一个skynet_context的c对象
struct skynet_context * ctx = skynet_malloc(sizeof(*ctx));
...
//为服务的ctx创建一个message_queue
struct message_queue * queue = ctx->queue = skynet_mq_create(ctx->handle);
//调用对象的init方法,这里是 snlua_init(snlua_create(),ctx,"bootstrap")
int r = skynet_module_instance_init(mod, inst, ctx, param);
if(r==){ //0表示成功
//成功以后,把服务的message_queue放入global_queue全局队列中
skynet_globalmq_push(queue);
}
}

就是说,bootstrap的启动请求 现在交到service_snlua.c的snlua_init里面了,所以接着我们来看snlua_init的实现

    snlua_init(struct snlua *l,struct skynet_context *ctx,args="bootstrap"){
...
//把ctx->cb=_launch, ctx->cb是worker线程取出skynet_message时的处理函数
skynet_callback(ctx, l , _launch);
//查询自己的handle id
const char * self = skynet_command(ctx, "REG", NULL);
uint32_t handle_id = strtoul(self+, NULL, );
...
memcpy(tmp, args, sz);
// it must be first message ,然后在这里立即投递第一个请求
skynet_send(ctx, ... , tmp="bootstrap", sz);
...
}

这里需要注意的是,skynet_command这里,实际上通过遍历查找,最终调用了cmd_reg,由于传入的param是NULL,实际是

     skynet_command(ctx, "REG", NULL){
sprintf(context->result, ":%x", context->handle);
return context->result;
}

//返回的是自己的ctx的handle id.

也就是下面的skynet_send:

        skynet_send(ctx, ... , tmp="bootstrap", sz);

是往自己的队列中投递了一个消息,worker线程拿到这个消息后,根据ctx->cb,调用callback函数: _launch

跟进 _launch:

    _launch(..., const void* msg="bootstrap"){
//把context->cb设为NULL了
skynet_callback(context, NULL, NULL);
//_init这里面实际上就是找到要加载的lua文件,然后加载到lua虚拟机中
//在这里就是把 bootstrap.lua文件加在进来
_init(l, context, msg, sz);
...
}

那我们来看看 bootstrap.lua 这个文件

local skynet = require "skynet"
local harbor = require "skynet.harbor"
require "skynet.manager" -- import skynet.launch, ...
local memory = require "memory" skynet.start(function()
...
-- 这里面,使用skynet.newservice 启动了很多个服务 local launcher = assert(skynet.launch("snlua","launcher"))
skynet.name(".launcher", launcher) ... if harbor_id == then
local ok, slave = pcall(skynet.newservice, "cdummy")
skynet.name(".cslave", slave)
else
local ok, slave = pcall(skynet.newservice, "cslave")
skynet.name(".cslave", slave)
end
... if standalone then
local datacenter = skynet.newservice "datacenterd"
skynet.name("DATACENTER", datacenter)
end
...
end)

这里有两点要注意:
1. skynet.start 的function里面,用snlua启动了launcher服务,并用skynet.name把自己注册名字为".launcher"的服务
".launcher" 的调用 skynet.call(".launcher",...)
在后面将经常看到。".launcher"服务就是在这里注册的。
以.开头的名字,是表示这个服务只在当前skynet节点下有效,如果不带点,需要支持跨节点的额外开销,没必要都会带上它。

2.skynet.start 函数

    function skynet.start(start_func)
//把回调函数注册为 skynet.dispatch_message
c.callback(skynet.dispatch_message)
//调用 skynet.init_service 调用了外面定义的 function 进行启动
skynet.timeout(, function()
skynet.init_service(start_func)
end)
end

到这里,就能明白,通过skynet_context_new 中的 snlua_init 和
_launch,skynet把请求的处理权从 c交到了 lua手上。

skynet1.0阅读笔记_skynet的启动的更多相关文章

  1. skynet1.0阅读笔记2_skynet的消息投递skynet.call

    为了了解 skynet.call 的调用过程,需要先看看 skynet的队列是如何把包分到不同工作线程的.看下图 查看 global_queue 的skynet_globalmq_push和skyne ...

  2. The Implementation of Lua 5.0 阅读笔记(一)

    没想到Lua的作者理论水平这么高,这篇文章读的我顿生高屋建瓴之感.云风分享了一篇中译:http://www.codingnow.com/2000/download/The%20Implementati ...

  3. Effective objective-c 2.0阅读笔记

    这本书非常的好,看完后,感触挺深,总结纪录一下,针对ios开发的备忘: 注:分类和原著有些不同,自己总结学习用的,仅供参考.   系统篇: 了解oc起源:继承c,由Smalltalk演化而来.动态语言 ...

  4. The implementation of Lua 5.0 阅读笔记(二)

    6 线程和协程 读完这篇文章我才意识到python的协程到底缺了什么,这个就是coroutine和semi-coroutine的区别了.区别就是,semi-coroutine只能返回(yield)到调 ...

  5. 《C# 6.0 本质论》 阅读笔记

    <C# 6.0 本质论> 阅读笔记   阅读笔记不是讲述这本书的内容,只是提取了其中一部分我认为比较重要或者还没有掌握的知识,所以如果有错误或者模糊之处,请指正,谢谢! 对于C# 6.0才 ...

  6. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...

  7. Linux 0.11源码阅读笔记-中断过程

    Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...

  8. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  9. Mongodb Manual阅读笔记:CH8 复制集

    8 复制 Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mongodb Manual阅读笔 ...

随机推荐

  1. 数组插件----linq.js

    优点 1.支持jQuery插件的方式.jquery.linq.min.js. 2.也可以像普通js方法一样使用.linq.min.js. 3.当然用习惯VS的童鞋肯定希望有个良好的智能感知,是的,它支 ...

  2. 利用腾讯云免费证书打造全https站

    什么是https? 超文本传输安全协议(Hypertext Transfer Protocol Secure,缩写为HTTPS)是一种网络安全传输协议http是HTTP协议运行在TCP之上,所有传输的 ...

  3. 转 web前端性能分析--原理篇

    转自http://blog.csdn.net/five3/article/details/7686715 web前端性能: 即是web用户在访问一个页面时所要花费的时间总和.即一个完全意义上的用户响应 ...

  4. POJ 2299:Ultra-QuickSort

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 39397   Accepted: 14204 ...

  5. APP三种开发模式

    目前主流应用程序大体分为三种:Web App(网页应用).Hybrid Ap(混合应用)p. Native App(原生应用). nativeapp是一个原生程序,一般运行在机器操作系统上,有很强的交 ...

  6. 腾讯 OCR 情况

    OCR技术之检测篇 https://cloud.tencent.com/developer/article/1101342 OCR技术之数据篇 https://cloud.tencent.com/de ...

  7. [转]Hspice 语法手册

    一.HSPICE基础知识Avant! Start-Hspice(现在属于Synopsys公司)是IC设计中最常使用的电路仿真工具,是目前业界使用最为广泛的IC设计工具,甚至可以说是事实上的标准.目前, ...

  8. linux分享一:进程全攻略--守护进程(服务)

    概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...

  9. controller与requestmapping

    使用@controller定义controllersSpring mvc将特定url的请求分发到controller类来进行处理在spring 3.0中,通过@controller标注即可将class ...

  10. C++ 链接Mysql 函数介绍

    通过MySQL自己的API函数进行连接 1.使用API的方式连接,需要加载mysql的头文件和lib文件.在VS2010的附加包含目录中添加\MySQL\MySQL Server 5.1\includ ...