当前位置: 首页 > news >正文

开源C语言库Melon:用户态动态追踪与控制反馈

前言

本文根据开源C语言库Melon的最新特性,讲述使用该库做用户态动态追踪,以及根据追踪内容进行计算,并将结果用于反馈给程序,同时对程序的处理流程进行影响。

说到动态追踪,大家可能第一印象是bpf、dtrace、systemtap等等,但是本文介绍的动态追踪不依赖于这些内容。Melon中提供的功能更加倾向于让程序在用户态内完成对自身的动态追踪,而不依赖于内核态,也不依赖于uprobe和usdt等内容

关于 Melon 库,这是一个开源的 C 语言库,它具有:开箱即用、无第三方依赖、安装部署简单、中英文文档齐全等优势。

Github: https://github.com/Water-Melon/Melon

原理

简单来说,Melon库的动态追踪也是在程序中加入跟踪点。只是在Melon中,一个应用程序被划分为两个层面(但都运行在同一个进程中):

  • C代码层
  • Melang脚本代码层

两个代码层面可以运行在同一线程,也可以运行在不同线程中,但需要运行于同一进程下。

换言之:跟踪点信息会在C层被抛出,传入给指定的脚本任务,然后脚本任务接收信息并进行处理。

这么看,似乎和在程序中记录日志,然后额外写一个程序来读取日志进行处理没有什么区别,那么这么做的好处是什么呢?

优势

  • 不需要对日志的格式进行解析,即可直接拿到对应类型的数据
  • 脚本侧运算后可进行远程传输或者入库(脚本库函数保证)
  • 即使在同一线程下,脚本任务执行也不会长期中断C层逻辑,脚本和C逻辑是自动分时处理的
  • 利用脚本侧的反馈机制,可以将运算结果传回C层,让C代码层的执行逻辑根据结果进行变更,例如:服务降级

示例

下面来看一个非常简单的例子:

#include <stdio.h>
#include "mln_log.h"
#include "mln_core.h"
#include "mln_trace.h"
#include "mln_conf.h"
#include "mln_event.h"int timeout = 100;static void timeout_handler(mln_event_t *ev, void *data)
{mln_trace("sir", "Hello", getpid(), 3.1);mln_event_timer_set(ev, timeout, NULL, timeout_handler);
}static int recv_handler(mln_lang_ctx_t *ctx, mln_lang_val_t *val)
{timeout += val->data.i;return 0;
}int main(int argc, char *argv[])
{mln_event_t *ev;struct mln_core_attr cattr;cattr.argc = argc;cattr.argv = argv;cattr.global_init = NULL;cattr.main_thread = NULL;cattr.master_process = NULL;cattr.worker_process = NULL;if (mln_core_init(&cattr) < 0) {fprintf(stderr, "Melon init failed.\n");return -1;}if ((ev = mln_event_new()) == NULL) {mln_log(error, "event new error\n");return -1;}if (mln_trace_init(ev, mln_trace_path()) < 0) {mln_log(error, "trace init error\n");return -1;}mln_trace_recv_handler_set(recv_handler);mln_event_timer_set(ev, 1000, NULL, timeout_handler);mln_event_dispatch(ev);return 0;
}

简单来描述下程序流程:

  1. 对Melon库进行全局初始化(mln_core_init)
  2. 初始化事件对象
  3. 初始化跟踪脚本
  4. 设置用于处理脚本层发来数据的函数
  5. 设置超时事件
  6. 事件分发,超时事件会被触发

在超时处理函数timeout_handler中,我们利用mln_trace向脚本任务发送了三个不同类型的数据,然后继续设置超时事件。

超时时长是一个全局变量timeout,初始为100,即100毫秒。

当脚本层发来数据时,这里我们约定脚本层一定发来的是一个整数,那么在接收函数recv_handler中,我们将这一数值与timeout进行累加,作为随后的超时时长。

由此,可以猜测,程序中每秒向脚本层投递的数据量会越来越少。

下面给出脚本层代码:

sys = Import('sys');
if (MASTER)sys.print('master process');
elsesys.print('worker process');Pipe('subscribe');
while (1) {ret = Pipe('recv');if (ret) {for (i = 0; i < sys.size(ret); ++i) {sys.print(ret[i]);}Pipe('send', 100);} fisys.msleep(1000);
}
Pipe('unsubscribe');

简单描述下脚本层逻辑就是,每秒钟从C层接收一批数据,然后向终端输出,且在输出后,向C层发送一个整数100

下面来看下程序运行结果:

...
[Hello, 72173, 3.100000, ]
[Hello, 72173, 3.100000, ]
[Hello, 72173, 3.100000, ]
...

会看到很多上述输出,但是读者若自己运行则会发现,每秒钟的输出行数会越来越少,这与我们的程序逻辑是相符合的。

结语

从这一例子中,我们可以看到,我们既可以在脚本侧做跟踪统计,也可以向C层施加影响。而最关键的三点是:

  1. C层中不需要增加额外的统计变量和结构
  2. C层与脚本层在代码管理层面上是分离的,互不干扰
  3. 两个层面的代码运行在同一个线程下

为了简化演示代码,上面的例子中没有给出在脚本层做网络通信和数据入库,但这些功能Melang脚本全部支持,感兴趣的读者可以参考Melang官网。

最后,对于Melon库感兴趣的读者可以访问其Github仓库获取更多信息。

感谢阅读!

相关文章:

  • 简单易懂的PyTorch 损失函数:优化机器学习模型的关键
  • C++ 模板
  • pythroch abaconda 安装 cuda、版本确定、pytorch 安装
  • Java多线程并发篇----第七篇
  • 【期末不挂科-考前速过系列P4】单片机[接口与总线]——经典例题盘点(带图解析)(第四章:32题搞定基本指令例题))
  • 具备闭环思维的测试才更充分
  • 深入了解网络流量清洗--使用免费的雷池社区版进行防护
  • TortoiseSVN·文件锁定与清理
  • 20240110-Python实现读取当前文件夹下所有视频名称和时长并生成一张表
  • 达梦数据库 模式 研究
  • 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图
  • 【WinForms 窗体】常见的“陷阱”
  • SqueezeNet:通过紧凑架构彻底改变深度学习
  • MySQL之数据类型建表以及约束
  • JQuery异步加载表格选择记录
  • [nginx文档翻译系列] 控制nginx
  • Java编程基础24——递归练习
  • Lsb图片隐写
  • Vue 动态创建 component
  • webgl (原生)基础入门指南【一】
  • Zepto.js源码学习之二
  • 入口文件开始,分析Vue源码实现
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 责任链模式的两种实现
  • 数据库巡检项
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​如何在iOS手机上查看应用日志
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #Z0458. 树的中心2
  • (007)XHTML文档之标题——h1~h6
  • (3)nginx 配置(nginx.conf)
  • (LeetCode C++)盛最多水的容器
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (三十五)大数据实战——Superset可视化平台搭建
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .NET : 在VS2008中计算代码度量值
  • .Net MVC + EF搭建学生管理系统
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .net 程序发生了一个不可捕获的异常
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET 依赖注入和配置系统
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET文档生成工具ADB使用图文教程
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @hook扩展分析
  • @Transactional 竟也能解决分布式事务?
  • [ C++ ] STL_list 使用及其模拟实现
  • [04] Android逐帧动画(一)