skynet C模块

来源:互联网 发布:用sql语句删除数据文件 编辑:程序博客网 时间:2024/05/22 13:57

skynet核心概念为服务,一个服务可以由C或lua实现,服务之间的通信已由底层C框架保证。用户要做的只是注册服务,处理消息。如云风的skynet综述中所说:

作为核心功能,Skynet 仅解决一个问题:

把一个符合规范的 C 模块,从动态库(so 文件)中启动起来,绑定一个永不重复(即使模块退出)的数字 id 做为其 handle 。模块被称为服务(Service),服务间可以自由发送消息。每个模块可以向 Skynet 框架注册一个 callback 函数,用来接收发给它的消息。每个服务都是被一个个消息包驱动,当没有包到来的时候,它们就会处于挂起状态,对 CPU 资源零消耗。如果需要自主逻辑,则可以利用 Skynet 系统提供的 timeout 消息,定期触发。

Skynet 提供了名字服务,还可以给特定的服务起一个易读的名字,而不是用 id 来指代它。id 和运行时态相关,无法保证每次启动服务,都有一致的 id ,但名字可以。

在云风的这篇博客中更详细地介绍道:

这个系统是单进程多线程模型。

每个内部服务的实现,放在独立的动态库中。由动态库导出的三个接口 create init release 来创建出服务的实例。init 可以传递字符串参数来初始化实例。比如用 lua 实现的服务(这里叫 snlua ),可以在初始化时传递启动代码的 lua 文件名。

每个服务都是严格的被动的消息驱动的,以一个统一的 callback 函数的形式交给框架。框架从消息队列里取到消息,调度出接收的服务模块,找到 callback 函数入口,调用它。服务本身在没有被调度时,是不占用任何 CPU 的。框架做两个必要的保证。

一、一个服务的 callback 函数永远不会被并发。

二、一个服务向两一个服务发送的消息的次序是严格保证的。

我用多线程模型来实现它。底层有一个线程消息队列,消息由三部分构成:源地址、目的地址、以及数据块。框架启动固定的多条线程,每条工作线程不断的从消息队列取到消息。根据目的地址获得服务对象。当服务正在工作(被锁住)就把消息放到服务自己的私有队列中。否则调用服务的 callback 函数。当 callback 函数运行完后,检查私有队列,并处理完再解锁。

符合规范的C模块

skynet C服务均被编译为动态链接库so文件,由框架在需要时加载并使用。前面说的”符合规范的C模块”指的是一个能被框架正确加载使用的C服务模块应该导出如下三个接口:

12345678
// 服务创建接口 返回服务实例数据结构struct xyz* xyz_create(void);// 初始化服务 主要是根据param启动参数初始化服务 并注册回调函数int xyz_init(struct xyz * inst, struct skynet_context *ctx, const char * param);// 释放服务void xyz_release(struct xyz* inst);

其中”xyz”是C服务名,需要和最终编译的动态库名一致,skynet根据这个名字来查找”xyz.so”并加载。服务模块还需要导出 xyz_create xyz_init xyz_release三个函数用于服务的创建,初始化和释放。xyz_create返回服务自定义的数据结构,代表一个服务实例的具体数据。xyz_init中根据启动参数完成服务的初始化,并且注册回调函数:

1234567891011
typedef int (*skynet_cb)( struct skynet_context * context, void * ud, int type, int session,  uint32_t source , const void * msg, size_t sz);// 注册消息回调函数cb和回调数据udskynet_callback(struct skynet_context * context, void *ud, skynet_cb cb);

通过skynet_callback可以注册回调函数和回调自定义数据ud(一般就是模块create函数的返回值),之后每次调用回调函数都会传入ud。

在skynet/service-src/下,定义了四个C服务,其中最简单的是skynet_logger.c,它是C写的一个logger服务。关于C服务的写法一看便知。

C服务上下文skynet_context

skynet_context保存一个C服务相关的上下文。包括服务的消息队列,回调函数cb,回调数据ud,所在模块,以及服务的一些状态等。skynet核心层管理的每个C服务都需要对应一个skynet_context。skynet建立服务的唯一id(handle)到skynet_context的一一对应。

在向服务发送消息时,指定其handle即可。skynet根据该handle找到skynet_context,并将消息push到skynet_context的msgqueue中。skynet还为服务提供了全局名字注册,这样可以通过指定服务名向服务发送消息,skynet会根据name找到handle,最终仍通过handle来找到服务的消息队列。

msgqueue中也保存了其所属服务handle。这样消息调度器在处理到某个msgqueue时,可通过msgqueue中的handle找到skynet_context,并调用其回调函数。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 摩托车证扣12分怎么办 初中孩孑想扩展单词量怎么办 恒安保险倒闭了怎么办 小麦收割机卸粮筒总是转怎么办 非牛顿体结块了怎么办 非牛顿流体硬了怎么办 玩具枪子弹打到眼睛怎么办 杭州磨床7130噪音大怎么办 步兵太苦还有一年怎么办 检法事业编怎么办最新 河北省事业单位改企编制怎么办 梦飞去虎牙锐雯怎么办 蚂蚁借呗还款钱没到账怎么办 蚂蚁借呗没有按时还款怎么办 新装的win7没有网卡驱动怎么办 3d电影没眼睛怎么办 看vr手机发烫变卡怎么办 vr眼镜头晕想吐怎么办 程序员年龄大了失业怎么办 事业人员编制在机关任职改革怎么办 老公出轨死不承认怎么办 2017年军自考毕业证怎么办 大腿酸痛肌肉萎缩怎么办一 习惯不了军训一起洗澡怎么办 脚着凉了有点痛怎么办 腿着凉了膝盖疼怎么办 下雨了脚着凉了怎么办 军训中被教官训怎么办 命根子根部长豆豆很痒怎么办? 屁股坏了化脓了怎么办 貔貅屁股摔坏了怎么办 当兵身高差4厘米怎么办 查体戴眼镜视力达不到怎么办 公司福利体检查乙肝怎么办 有乙肝每年福利体检怎么办 国企有乙肝每年福利体检怎么办 单位福利体检查乙肝怎么办 事业单位每年福利体检有乙肝怎么办 高考失利后我该怎么办 初三了科学总是考不好怎么办 初三学生三模考的不好怎么办