skynet源码学习-skynet_main入口

  • 核心功能与启动流程
  • Shell脚本启动示例
  • main函数参数处理
  • 其他相关联函数解析
    • 1. 配置加载器解析
    • 2. 环境变量设置
    • 3. 配置解析函数
  • 核心配置项解析
  • 典型配置文件分析
  • 服务启动与运行
    • 核心服务启动流程
    • 完整启动时序图

核心功能与启动流程

Skynet 的启动入口负责整个框架的初始化和配置加载,其工作流程如下:
在这里插入图片描述

Shell脚本启动示例

#!/bin/bash
./skynet /path/to/config.lua

main函数参数处理

int main(int argc, char *argv[]) {const char * config_file = NULL ;// 检查参数if (argc > 1) {config_file = argv[1]; // 使用第一个参数作为配置文件} else {// 无配置文件时报错fprintf(stderr, "Need a config file. Please read skynet wiki : https://github.com/cloudwu/skynet/wiki/Config\n""usage: skynet configfilename\n");return 1;}// 全局初始化skynet_globalinit(); // 初始化全局资源skynet_env_init();   // 初始化环境变量系统//信号处理sigign(); // 忽略SIGPIPE信号,防止网络断开导致进程退出struct skynet_config config;#ifdef LUA_CACHELIB// init the lock of code cacheluaL_initcodecache();
#endif// 创建Lua虚拟机struct lua_State *L = luaL_newstate();luaL_openlibs(L); // 加载Lua标准库// 加载并执行配置加载器int err =  luaL_loadbufferx(L, load_config, strlen(load_config), "=[skynet config]", "t");assert(err == LUA_OK);lua_pushstring(L, config_file);err = lua_pcall(L, 1, 1, 0); // 执行配置加载if (err) {fprintf(stderr,"%s\n",lua_tostring(L,-1));lua_close(L);return 1;}// 这里处理将lua配置加载并设置到env环境变量中_init_env(L);lua_close(L);// 配置解析处理config.thread = optint("thread",8); // 默认8线程config.module_path = optstring("cpath","./cservice/?.so");config.harbor = optint("harbor", 1); // 默认节点ID=1config.bootstrap = optstring("bootstrap","snlua bootstrap");config.daemon = optstring("daemon", NULL); // 守护进程配置config.logger = optstring("logger", NULL); // 日志文件config.logservice = optstring("logservice", "logger"); // 日志服务config.profile = optboolean("profile", 1); // 默认开启性能分析skynet_start(&config); // 启动skynet核心skynet_globalexit(); // 释放全局资源
}

其他相关联函数解析

1. 配置加载器解析

static const char * load_config = "\local result = {}\n\local function getenv(name) return assert(os.getenv(name), [[os.getenv() failed: ]] .. name) end\n\local sep = package.config:sub(1,1)\n\local current_path = [[.]]..sep\n\local function include(filename)\n\local last_path = current_path\n\local path, name = filename:match([[(.*]]..sep..[[)(.*)$]])\n\if path then\n\if path:sub(1,1) == sep then    -- root\n\current_path = path\n\else\n\current_path = current_path .. path\n\end\n\else\n\name = filename\n\end\n\local f = assert(io.open(current_path .. name))\n\local code = assert(f:read [[*a]])\n\code = string.gsub(code, [[%$([%w_%d]+)]], getenv)\n\f:close()\n\assert(load(code,[[@]]..filename,[[t]],result))()\n\current_path = last_path\n\end\n\setmetatable(result, { __index = { include = include } })\n\local config_name = ...\n\include(config_name)\n\  -- 加载主配置文件setmetatable(result, nil)\n\return result\n\
";

配置加载器是一个Lua代码字符串,核心功能:

  • 支持include指令嵌套配置文件
  • 支持$VAR形式的环境变量替换
  • 构建配置表并返回

2. 环境变量设置

static void
_init_env(lua_State *L) {lua_pushnil(L);  /* first key */while (lua_next(L, -2) != 0) {int keyt = lua_type(L, -2);if (keyt != LUA_TSTRING) {fprintf(stderr, "Invalid config table\n");exit(1);}const char * key = lua_tostring(L,-2);// 根据类型设置环境变量if (lua_type(L,-1) == LUA_TBOOLEAN) {int b = lua_toboolean(L,-1);skynet_setenv(key,b ? "true" : "false" );} else {const char * value = lua_tostring(L,-1);if (value == NULL) {fprintf(stderr, "Invalid config table key = %s\n", key);exit(1);}skynet_setenv(key,value);}lua_pop(L,1);}lua_pop(L,1);
}

3. 配置解析函数

  1. optint - 解析整数配置
static int optint(const char *key, int opt) {const char * str = skynet_getenv(key);if (str == NULL) {// 设置默认值char tmp[20];sprintf(tmp,"%d",opt);skynet_setenv(key, tmp);return opt;}return strtol(str, NULL, 10); // 转换字符串为整数
}
  1. optboolean - 解析布尔配置
static int optboolean(const char *key, int opt) {const char * str = skynet_getenv(key);if (str == NULL) {// 设置默认值skynet_setenv(key, opt ? "true" : "false");return opt;}return strcmp(str,"true")==0; // 检查是否为"true"
}
  1. optstring - 解析字符串配置
static const char * optstring(const char *key,const char * opt) {const char * str = skynet_getenv(key);if (str == NULL) {if (opt) {skynet_setenv(key, opt); // 设置默认值opt = skynet_getenv(key);}return opt;}return str;
}

核心配置项解析

skynet_config结构

struct skynet_config {int thread;         // 工作线程数const char *module_path; // C服务模块路径int harbor;         // 节点IDconst char *bootstrap; // 引导服务const char *daemon; // 守护进程配置const char *logger; // 日志文件const char *logservice; // 日志服务int profile;        // 性能分析开关
};

典型配置文件分析

config.lua示例

-- 基础配置
thread = 8
harbor = 1
daemon = "./skynet.pid"  -- 守护进程模式
logger = "logs/error.log" -- 错误日志-- 服务路径配置
cpath = "./cservice/?.so" -- C服务路径
lualoader = "./lualib/loader.lua" -- Lua加载器-- 引导服务
bootstrap = "snlua bootstrap" -- 启动引导服务
start = "main"  -- 主入口脚本-- 自定义配置
mysql_host = "$DB_HOST" -- 使用环境变量
cluster_nodes = {"node1","node2",include "nodes.lua" -- 包含子配置
}

服务启动与运行

核心服务启动流程

在这里插入图片描述

完整启动时序图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87673.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87673.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87673.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端图文混排页面一键导出PDF最佳实践 —— 以Vue3+html2pdf.js为例

前言 在现代管理系统中,数据的归档、分享和线下流转需求日益增长。如何将前端页面的图文内容高质量导出为PDF,成为许多企业和开发者关注的技术点。本文以实际项目为例,系统梳理前端导出PDF的完整实现思路与优化经验。 一、项目背景与需求分析 1.1 背景故事 在某管理系统的…

19|Whisper+ChatGPT:请AI代你听播客

今天,我们的课程开始进入一个新的主题了,那就是语音识别。过去几周我们介绍的ChatGPT虽然很强大,但是只能接受文本的输入。而在现实生活中,很多时候我们并不方便停下来打字。很多内容比如像播客也没有文字版,所以这个时…

linux常用设置

1,ubuntu设置ssh-agent进入shell时自动加载 一,添加自动加载脚本,vim /etc/profile.d/keychain.sh # /etc/profile.d/keychain.sh # 自动启动 ssh-agent 并加载多个私钥 export KEYCHAIN_HOME"/root/.keychain" # 多个key&#xf…

电子电气架构 --- 软件供应商如何进入OEM体系

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

破解数据可视化难题:带轴断裂的柱状图绘制全指南

引言:当数据跨度让图表失真时,轴断裂技术如何力挽狂澜? 在数据可视化的世界里,我们常常会遇到这样的困境:一组数据中既有 "巨无霸" 般的极端值,又有需要精细展示的小数据。比如在财务报表中&…

以太网基础①以太网相关通信接口

1. 今日摸鱼任务 需要学习使用ZYNQ的以太网传输SCPI指令 需要把PL PS两侧的都用起来(加油鸭!) 呐呐呐 今天就先学一下基础知识呗 02_【逻辑教程】基于HDL的FPGA逻辑设计与验证教程V3.5.2.pdf 51 以太网相关通信接口详解 52 以太网&#xff…

FPGA基础 -- Verilog 共享任务(task)和函数(function)

Verilog 中共享任务(task)和函数(function) 的详细专业培训,适合具有一定 RTL 编程经验的工程师深入掌握。 一、任务(task)与函数(function)的基本区别 特性taskfunctio…

学习大模型---需要掌握的数学知识

1. 线性代数:乐高积木的世界 想象你有很多乐高积木块。线性代数就是研究怎么用这些积木块搭建东西,以及这些搭建好的东西有什么特性的学问。 向量: 就像一个有方向的箭头,或者一组排好队的数字。比如: 一个箭头&…

明远智睿RK3506开发板:多核异构架构赋能高可靠性工业与商业应用

在工业4.0与物联网(IoT)技术快速发展的背景下,嵌入式系统对性能、功耗、可靠性和实时性的要求日益严苛。针对这一趋势,瑞芯微推出的RK3506开发板凭借其创新的三核A7单核M0多核异构架构、高能低耗设计以及丰富的外设资源&#xff0…

【AI时代速通QT】第二节:Qt SDK 的目录介绍和第一个Qt Creator项目

目录 一、认识 Qt SDK 的目录结构 二、第一个 Qt 程序 2.1 Qt Creator 创建项目 2.2 介绍项目各文件 三、揭秘 Qt 的构建过程 四、运行项目与总结 🎬 攻城狮7号:个人主页 🔥 个人专栏:CQT跨平台界面编程 ⛺️ 君子慎独! &#x1f308…

CDH部署Hive详细指南

CDH部署Hive详细指南 本文将详细介绍如何使用Cloudera Manager Web界面部署Hive组件,包括安装、配置、优化和运维管理等内容。 1. 环境准备 1.1 系统要求 1.1.1 硬件要求 服务器配置 CPU:建议8核以上内存:建议32GB以上磁盘:建议使用企业级SAS或SSD网络:建议万兆网络集…

党建赋能 医校协同|广州附医华南医院与湖南中医药高等专科学校签约携手共育英才

为深入贯彻落实党中央、国务院关于高校毕业生就业创业工作决策部署,教育部印发《职业学校校企合作促进办法》,对深化医教协同提供了政策指引。在医学教育领域,鼓励医学院校与医疗机构开展深度合作,根据医疗行业需求调整专业设置与…

【RTSP从零实践】2、使用RTP协议封装并传输H264

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

行业热点丨手机中框设计如何体现增材思维?

编者荐语: 通过增材设计思维在金属边框设计晶格结构,既能减轻重量,同时也有助于散热,针对不同位置设计不同类型的晶格结构还能起到缓冲效果,提高手机抗冲击能力。 以下文章来源于Inspire增材创新设计,作者…

鸿蒙案例实战——添加水印

本示例为开发者展示常用的水印添加能力,包括两种方式给页面添加水印、保存图片添加水印、拍照图片添加水印和pdf文件添加水印。 案例效果截图 首页 页面水印 图片水印 pdf水印 案例运用到的知识点 核心知识点 页面添加水印:封装Canv…

Qt工作总结07 <qBound和std::clamp>

一、qBound简介 1. 定义 是 Qt 框架中一个非常实用的边界限制函数&#xff08;也称为 "clamp" 函数&#xff09;&#xff0c;用于将一个值限制在指定的最小值和最大值之间。头文件&#xff1a;#include <QtGlobal> 2. 函数原型 template <typename T>…

53-Oracle sqlhc多版本实操含(23 ai)

SQLHC&#xff08;SQL Health Check&#xff09;作为 Oracle 数据库性能诊断的核心工具&#xff0c;其设计理念和核心功能在 Oracle 各版本中保持高度一致&#xff0c;但在技术实现和周边生态上存在渐进式优化。定期对关键业务 SQL 执行健康检查&#xff0c;特别是在版本升级或…

math.pow()和pow()的区别

math.pow() 和 pow() 的区别 ✅ 1. math.pow() 来自 math 模块参数&#xff1a;两个数&#xff08;底数&#xff0c;指数&#xff09;结果类型&#xff1a; 始终返回 float 类型 示例&#xff1a; import math print(math.pow(2, 3)) # 输出&#xff1a;8.0 &#xff08;…

邮科OEM摄像头POE供电技术的核心优势

安防监控中&#xff0c;供电方式影响系统稳定性、安装效率与维护成本。邮科摄像头采用POE技术&#xff0c;通过网线同时传输数据与电力&#xff0c;革新传统部署模式。本文解析其六大核心优势&#xff0c;展现其作为现代安防优选方案的价值。 一、布线简化&#xff0c;效率提升…

微信小程序-数据加密

npm install crypto-js utils/aes.js const CryptoJS require(crypto-js);// 默认的 KEY 与 iv 如果没有给 const KEY CryptoJS.enc.Utf8.parse(KrQ4KAYOEyAz66RS); // 十六位十六进制数作为密钥 const IV CryptoJS.enc.Utf8.parse(ep1YCmxXuxKe4eH1); // 十六位十六进制…