开源C语言库Melon:多线程治理

问题描述

不知你是否有过类似如下的需求:

有一些功能,它们足够单一,但又需要后台持续运行,以容器实现感觉太重了,以进程实现又太琐碎了,以线程实现可以接受但是又不好管理。

这类程序诸如:数据采集程序、可观测性程序、中间件、代理等等。

这一需求乍看之下倒是有点类似supervisor在做的事情,每个功能一个单一后台进程。诚然进程是一个选择,但是实际使用中则会面临是大量的可执行程序和因人而异的开发风格。

当然,选择多线程还有另一个重要原因,这里先卖个关子,我们往下看。

解决方案

因此,笔者将介绍一个开源C语言库——Melon。
在这里插入图片描述

它实现了一套多线程框架。在这套框架之下,每一个线程是一个独立的功能模块,并且可以接受来自主线程的管理。

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

Github repo

对于上述的问题,我们可以使用这一框架来解决。除此之外,Melon还支持了另一个功能,这也是选择多线程的原因之一,谜底将在示例中揭晓。

示例

在Melon的多线程框架中,有两种方式可以启动不同的线程模块,下面的示例将以动态创建和杀掉线程的方式进行演示。

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include "mln_core.h"
#include "mln_log.h"
#include "mln_thread.h"
#include "mln_trace.h"int sw = 0; //开关switch缩写
char name[] = "hello";
static void thread_create(mln_event_t *ev);static int hello_entrance(int argc, char *argv[])
{printf("%s\n", __FUNCTION__);while (1) {mln_trace("s", "Hello");usleep(10);}return 0;
}static void timer_handler(mln_event_t *ev, void *data)
{if (!sw) {mln_string_t alias = mln_string("hello");mln_thread_kill(&alias);mln_event_timer_set(ev, 1000, NULL, timer_handler);} else {thread_create(ev);}sw = !sw;
}static void thread_create(mln_event_t *ev)
{char **argv = (char **)calloc(3, sizeof(char *));if (argv != NULL) {argv[0] = name;argv[1] = NULL;argv[2] = NULL;mln_thread_create(ev, "hello", THREAD_DEFAULT, hello_entrance, 1, argv);mln_event_timer_set(ev, 1000, NULL, timer_handler);}
}int main(int argc, char *argv[])
{struct mln_core_attr cattr;cattr.argc = argc;cattr.argv = argv;cattr.global_init = NULL;cattr.main_thread = thread_create;cattr.worker_process = NULL;cattr.master_process = NULL;if (mln_core_init(&cattr) < 0) {fprintf(stderr, "Melon init failed.\n");return -1;}return 0;
}

可以看到,main函数中只初始化了Melon库。而多线程框架也正是在库初始化时启动的。

我们先对程序做大致的描述,然后给出Melon的配置文件内容。

整个程序流程大致如下:

  1. 初始化Melon库并运行多线程框架
  2. 调用thread_create函数对主线程做部分初始化操作,其中:
    1. 构建子线程入口参数的字符指针数组
    2. 调用mln_thread_create创建子线程hello
    3. 设置定时器事件timer_handler,这个函数将每秒钟被调用一次
  3. 子线程hello被拉起,并printf输出函数名后,进入死循环调用mln_trace函数(我们后面马上说到这个函数)
  4. 主线程每秒钟进入一次timer_handler并执行如下事项:
    1. 如果sw为0,则杀掉hello线程,并再次设置定时器事件
    2. 如果sw为1,则调用thread_create创建hello线程,并再次设置定时器事件
    3. 反转sw的值,保持每秒关闭和启动hello线程

我们可以看到,通过mln_thread_createmln_thread_kill我们可以让主线程动态的拉起和杀掉子线程。

为何使用多线程

因为我们使用了mln_trace,这个宏函数是将C代码中数据投递到脚本层。这么做的好处是,这些数据不需要被写入日志文件,然后再启动另一个程序处理日志文件。也不需要手写C代码来将这些数据发送给远端。脚本层有内置的库函数可以轻松完成这些数据的处理、传输、入库等操作。

配置

说了很多关于程序功能的问题,但想要正常启动这个程序还需要正确配置Melon,配置文件内容如下:

log_level "none";
//user "root";
daemon off;
core_file_size "unlimited";
//max_nofile 1024;
worker_proc 1;
thread_mode on;
framework "multithread";
log_path "/usr/local/melon/logs/melon.log";
trace_mode "trace/trace.m"; /* path or off */

这里主要关注三个配置:

  • framework必须是"multithread"
  • trace_mode如果想启用mln_trace的功能,这里要给出脚本代码路径,否则给出off表示关闭该功能
  • worker_proc是工作进程数,我们的多线程都是跑在工作进程上的,这样一旦线程有bug造成工作进程崩溃,主进程依旧可以拉起新的工作进程继续运行

脚本代码

本例的脚本代码使用的就是Melon库中自带的默认脚本trace/trace.m

/** Copyright (C) Niklaus F.Schen.*/
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]);}} fisys.msleep(1000);
}
Pipe('unsubscribe');

脚本主要工作就是死循环调用Pipe函数接收mln_trace投递来的数据,并向终端输出。

运行结果

...
[Hello, ]
[Hello, ]
[Hello, ]
01/29/2023 07:38:23 GMT REPORT: PID:15708 Child thread 'hello' exit.
01/29/2023 07:38:23 GMT REPORT: PID:15708 child thread pthread_join's exit code: 1
hello_entrance
[Hello, ]
[Hello, ]
[Hello, ]
...

可以看到终端上会输出大量[Hello, ],这是脚本层输出的mln_trace投递来的数据。中间会穿插着一些线程退出和启动的打印信息。

感谢阅读!欢迎各位对Melon感兴趣的读者访问其Github仓库。

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

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

相关文章

详解c++移动构造函数和移动赋值运算符在代码性能中起的作用

对象移动 对象移动&#xff0c;就是把一个不想用了的对象A中的一些有用的数据提取出来&#xff0c;在构建新对象B的时候就不需要重新构建对象中的所有数据——从不想用了的对象A中提取出来的有用数据在构建对象B时都可以拿来使用。 我们知道&#xff0c;拷贝构造函数、拷贝赋…

Java中什么是多线程?

Java是一种支持多线程编程的编程语言&#xff0c;它提供了内置的多线程支持&#xff0c;使得开发者能够创建并发执行的程序。多线程是一种在同一程序中同时执行多个线程的机制&#xff0c;每个线程都是独立运行的&#xff0c;并且可以共享相同的资源。在Java中&#xff0c;多线…

设计模式之观察者模式【行为型模式】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某…

把图表题注编号由“0.1”改为“1.1“ (方法二)

前置设置&#xff1a; 手打章节标题&#xff0c;“第一章 绪论”&#xff0c;“第二章 相关理论和技术方法”。给章节标题设置样式 “标题一”&#xff0c;设置为一级标题。打开导航窗格&#xff0c;可以不开&#xff0c;我纯粹是为了操作方便。直接先给图片插入题注&#xff…

cpolar 内网穿透 使用

cpolar 内网穿透 使用 官网地址&#xff1a;https://www.cpolar.com/ 官网文档&#xff1a;https://www.cpolar.com/blog/cpolar-quick-start-tutorial-centos-series 获取隧道Authtoken&#xff1a;https://dashboard.cpolar.com/auth 步骤 1、先去注册 在这个地方注册&…

重磅2023年度openGauss标杆应用实践案例正式揭晓

12月28日&#xff0c;在openGauss Summit 2023峰会上&#xff0c;正式揭晓了“2023年度openGauss标杆应用实践案例”。 数据库作为企业IT系统的核心组成部分&#xff0c;是数字基础设施建设的关键&#xff0c;也是实现数据安全稳定的保障。为更好地推动产业技术创新&#xff0…

使用Linux防火墙管理HTTP流量

在Linux系统中&#xff0c;防火墙是用于控制网络流量的重要工具。通过防火墙&#xff0c;你可以根据需要限制、过滤或允许特定的网络流量&#xff0c;从而提高系统的安全性。在处理HTTP流量时&#xff0c;防火墙可以帮助你实施访问控制、流量监控和其他安全策略。 iptables i…

PPT插件-大珩助手-免费功能-特殊格式介绍

上、下标切换 直接切换选中的字符为上、下标。 大小金额 支持超大金额的大写金额转换 当前日期 本次打开文件的时间 转二维码 将当前选中的文字&#xff0c;转为二维码图片&#xff0c;并插入到PPT当前位置 特殊字符 内置常用的特殊字符&#xff0c;点击使用 软件介绍 …

Java多线程并发篇----第五篇

系列文章目录 文章目录 系列文章目录前言一、Java中interrupted 和 isInterruptedd方法的区别?二、Java中synchronized 和 ReentrantLock 有什么不同?三、有三个线程T1,T2,T3,如何保证顺序执行?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分…

关于CodeReview的一些实践和思考

在日常开发中&#xff0c;Code Review 的重要性日益凸显。它不仅有助于提升代码质量&#xff0c;还促进了团队成员之间的知识共享和技能提升。本文将主要聚焦于 Code Review&#xff0c;分享在这个过程中的一些心得和思考。 CodeReview常用到的一些术语 之前看到公司的大佬经…

autoxjs 安卓爬虫自动化

autoxjs 安卓爬虫自动化 我这里只是测试请勿用于违法的 我这里是小红书 文章目录 autoxjs 安卓爬虫自动化前言一、自动刷直播间并且抓取商品已经粉丝数量等&#xff1f;总结 前言 欢迎来到AutoXJS的世界&#xff0c;这是一个充满创新、挑战和技术探索的领域。在这个引领未来的…

基于Springboot+vue高校宿舍管理系统(前后端分离)

该项目完全免费 高校宿舍管理系统采用前后端分离的架构方式&#xff0c;是为学校宿舍管理打造的一套系统,可以让管理者更为便捷地处理学生公寓问题,从而大大提高管理效率,让学生公寓的资源合理分配,事半功倍,进而改善了学生公寓管理。 系统分为三种角色&#xff0c;分别是系统…

小巧且兼具高性能的小模型 TinyLlama 等

TinyLlama-1.1B 小模型在边缘设备上有着广泛的应用&#xff0c;如智能手机、物联网设备和嵌入式系统&#xff0c;这些边缘设备通常具有有限的计算能力和存储空间&#xff0c;它们无法有效地运行大型语言模型。因此&#xff0c;深入探究小型模型显得尤为重要。 来自新加坡科技…

[ 机器学习 ] 关于Jupyter Notebook中pytorch模块import失败的问题

0x01、问题描述 在使用WSL搭建Jupyter进行代码测试的时候 发现Miniconda&#xff08;虚拟环境均适用&#xff09;中安装的pytorch在Jupyter里面import失败 但在python解释器的命令模式里可以测试import成功 并且torch.cuda_available()打印True 以前用的是IDEA没怎么用Jup…

Navicat迁移局域网内其他PC机的MySQL数据库

迁移局域网内其他PC机的MySQL数据库到本机 查看局域网IP 设置可远程连接的账号 开放本机防火墙的3306端口 连接PC机的MySQL 利用Navicat迁移数据库 刚换了个电脑&#xff0c;旧电脑的MySQL数据库太多了&#xff0c;转成.sql文件&#xff0c;再传输到新电脑上运行&#xff…

CSS3新增边框样式

边框样式 概念:在CSS3中&#xff0c;针对元素边框增加了丰富的修饰属性。 常见的边框样式属性有以下 属性说明border-radius圆角效果box-shadow边框阴影border-image边框背景 border-radius属性 概念&#xff1a;border-radius属性可以为元素添加圆角效果 语法&#xff1…

盘点五大设备巡检系统!内附巡检注意事项及巡检要点

在繁忙的工业生产现场&#xff0c;设备高效运行是保证生产顺利开展的关键。为了确保设备的稳定性和生产的安全性&#xff0c;设备巡检工作变得尤为重要。 举个通俗易懂的例子—— 你开了一家钢铁制造厂&#xff0c;工厂拥有多条自动化生产线&#xff0c;每天24小时不间断地运…

运用tomcat在浏览器中对数据库信息进行查询

在idea中创建好项目后&#xff0c;添加web项目 然后打开idea的setting&#xff0c;跳转到下面的页面&#xff0c;下载maven插件。 出现下面的选项&#xff0c;才正确。 添加好web项目后&#xff0c;打开pom文件&#xff0c;添加相应的依赖&#xff1a; <?xml version"…

golang中的循环依赖

作为 Golang 开发人员&#xff0c;您可能遇到过导入周期。Golang 不允许导入循环。如果 Go 检测到代码中的导入循环&#xff0c;则会抛出编译时错误。在这篇文章中&#xff0c;让我们了解导入周期是如何发生的以及如何处理它们。 导入周期 假设我们有两个包&#xff0c;p1并且…

【mysql】—— 用户管理

目录 &#xff08;一&#xff09;为什么要有用户管理&#xff1f; &#xff08;二&#xff09;用户 2.1 查看用户信息 2.2 创建用户 2.3 删除用户 2.4 修改用户密码 &#xff08;三&#xff09;数据库的权限 3.1 给用户授权 3.2 回收权限 &#xff08;一&#xff09;为…