开发利器——C语言必备实用第三方库


对于广大C语言开发者来说,缺乏类似C++ STL和Boost的库会让开发受制于基础库的匮乏,也因此导致了开发效率的骤降。这也使得例如libevent这类事件库(基础组件库)一时间大红大紫。

今天,码哥给大家带来一款基础库,这套库不仅仅提供了常用的数据结构、算法,如红黑树、斐波那契堆、队列、KMP算法、RSA算法、各类哈希算法、数据恢复算法等等,还提供了多进程框架、多线程框架、跨平台高性能事件等实用内容。注意:这是一款不依赖第三方的库。

除此以外,它也是笔者之前文章(Melang脚本语言)中的核心库。这也就意味着,使用该库,不仅可以快速获得上述内容,还可以让开发者所构建的系统很方便地引入脚本语言的功能。

它就是——Melon
在这里插入图片描述

GitHub - Water-Melon/Melon: A generic cross-platform C library, including a lot of components, frameworks and a new coroutine script language Melang.

下面,码哥便带诸位一览这个库的功能。

数据结构

Melon中包含如下数据结构的实现:

  • 双向链表
  • 斐波那契堆
  • 哈希表
  • 队列
  • 红黑树
  • 数组

其中:

  • 双向链表使用宏实现,可以通过两行宏函数即可完成双向队列插入和删除操作的声明和定义。
  • 斐波那契堆是一个最小堆,在库中的事件功能中用于实现定时器的维护管理,当然,也可以单独使用。

以上结构几乎均可在其对应名称的头文件中找到数据结构定义以及函数定义。

一般情况下,数据结构的使用都是函数调用形式,因此也尽可能降低了不同组件间的耦合度。

算法

Melon中包含的算法如下:

  • 加密算法:AES、DES、3DES、RC4、RSA
  • 哈希算法:MD5、SHA1、SHA256
  • Base64
  • 大数计算
  • FEC
  • JSON
  • 矩阵运算
  • 里德所罗门编码
  • 正则匹配算法
  • KMP

如上算法基本都在其各自头文件中可以找到对应的函数声明以及必要的数据结构定义。

其中,FEC与里德所罗门编码均属于纠错码,FEC常用于RTP中做数据修复,而里德所罗门编码既可以用于实时语音中丢包恢复,也可以用于冗余阵列(RAID)和其他UDP丢包恢复的场景。关于里德所罗门编码,感兴趣的读者可以阅读码哥之前的文章:神奇的数据恢复算法。

其他组件

前面的都是常规操作,这里才是重头戏。

Melon中还包括如下实用组件:

  • 内存池
  • 数据链
  • TCP封装
  • 事件机制
  • 文件缓存
  • HTTP处理
  • 脚本语言
  • 词法分析器
  • websocket
  • 多进程框架
  • 多线程框架

因Melon作者Nginx中毒较深,所以Melon中部分机制与Nginx较为相似。

内存池:这里内存池不仅支持对从堆中分配的内存进行管理,还支持对共享内存的管理。

数据链与TCP封装:TCP封装中包含了阻塞与非阻塞下的收发逻辑,并利用数据链结构来存放发送数据与接收数据。

事件机制:事件机制中不仅支持epoll、select,还支持Kqueue,库在编译前会自行检测平台支持情况。事件包含了:

  • 句柄(文件描述符)事件:读、写、出错事件,以及超时事件(主要用于超时断开链接)
  • 定时事件(与句柄超时是两码事)

文件缓存:参考Nginx文件缓存,避免对同一文件的重复打开浪费文件描述符资源。

HTTP:包含了HTTP的接收解析和发送,该套接口依赖于数据链结构来进行处理,因此可配合TCP封装一同使用。

脚本语言:内容较多,可另行参考:Melang脚本语言。

词法分析器:之所以这个单独算一个功能组件,是因为在Melon中,配置文件解析就是使用该词法分析器处理的。仅通过三行C代码就可以实现一个最最基础的词法分析器,这也归功于C语言宏的强大。

websocket:该部分依赖于HTTP组件。

多进程:多进程采用一主多从模式,主进程做管理,从进程处理实际业务。主进程与从进程之间由socketpair相连,因此从进程异常退出,主进程会立刻拉起一个新的子进程,同时主子进程也可以通过该socketpair进行数据通信。除了自身子进程可以管理,也可以通过配置文件配置来拉起其他程序作为自己的子进程来管理,有些类似于supervisord。

多线程:多线程分为两类,一类是常规的线程池,另一类是模块化的线程。后者也是一主多从模型,主与子之间是通过socketpair进行通信,而每一个子线程都有其入口函数(类似main函数),每一个子线程通常都是处理一类单一事务。

使用举例

上面说了那么多,下面就来看一个多进程的例子。

首先,我们要先安装Melon:

$ git clone https://github.com/Water-Melon/Melon.git
$ ./configure
$ make
$ sudo make install
$ sudo echo "/usr/local/melon/lib/" >> /etc/ld.so.conf
$ sudo ldconfig

安装好后,Melon会被安装在/usr/local/melon下。

接着,我们创建一个名为hello.c的源文件来完成我们期望的功能:

#include <stdio.h>
#include "mln_framework.h"
#include "mln_log.h"
#include "mln_event.h"char text[1024];static int global_init(void);
static void worker_process(mln_event_t *ev);
static void print_handler(mln_event_t *ev, void *data);int main(int argc, char *argv[])
{struct mln_framework_attr attr;attr.argc = argc;attr.argv = argv;attr.global_init = global_init;attr.master_process = NULL;attr.worker_process = worker_process;return mln_framework_init(&attr);
}static int global_init(void)
{//global variable init functionint n = snprintf(text, sizeof(text)-1, "hello world\n");text[n] = 0;return 0;
}static void worker_process(mln_event_t *ev)
{//we can set event handler here//let's set a timermln_event_timer_set(ev, 1000, text, print_handler);
}static void print_handler(mln_event_t *ev, void *data)
{mln_log(debug, "%s\n", (char *)data);mln_event_timer_set(ev, 1000, data, print_handler);
}

这段代码主要是初始化了一个全局变量,然后给每一个子进程创建了一个定时事件,即每一秒中输出一个hello world。

我们先进行编译链接生成可执行程序:

$ cc -o hello hello.c -I /usr/local/melon/include/ -L /usr/local/melon/lib/ -lmelon

然后,我们需要先修改Melon库的配置文件:

$ sudo vim /usr/local/melon/conf/melon.conflog_level "none";
//user "root";
daemon off;
core_file_size "unlimited";
//max_nofile 1024;
worker_proc 1;
thread_mode off;
framework off;
log_path "/usr/local/melon/logs/melon.log";
/** Configurations in the 'exec_proc' are the* processes which are customized by user.** Here is an example to show you how to* spawn a program.*     keepalive "/tmp/a.out" ["arg1" "arg2" ...]* The command in this example is 'keepalive' that* indicate master process to supervise this* process. If process is killed, master process* would restart this program.* If you don't want master to restart it, you can*     default "/tmp/a.out" ["arg1" "arg2" ...]** But you should know that there is another* arugment after the last argument you write here.* That is the file descriptor which is used to* communicate with master process.*/
exec_proc {// keepalive "/tmp/a";
}
thread_exec {
//    restart "hello" "hello" "world";
//    default "haha";
}

我们做如下修改:

framework off; --> framework "multiprocess";
worker_proc 1; --> worker_proc 3;

这样,多进程框架将被启用,且会产生三个子进程。

程序启动后如下:

$ ./hello
Start up worker process No.1
Start up worker process No.2
Start up worker process No.3
02/08/2021 09:34:46 GMT DEBUG: hello.c:print_handler:39: PID:25322 hello world02/08/2021 09:34:46 GMT DEBUG: hello.c:print_handler:39: PID:25323 hello world02/08/2021 09:34:46 GMT DEBUG: hello.c:print_handler:39: PID:25324 hello world02/08/2021 09:34:47 GMT DEBUG: hello.c:print_handler:39: PID:25322 hello world02/08/2021 09:34:47 GMT DEBUG: hello.c:print_handler:39: PID:25323 hello world02/08/2021 09:34:47 GMT DEBUG: hello.c:print_handler:39: PID:25324 hello world...

这时,可以ps看一下,一共存在四个hello进程,一个为主,其余三个为子进程。

小结

事实上,Melon并不会有过多条条框框需要开发者小心谨慎怕踩坑。与Skynet类似,Melon提供的绝大多数内容都可独立使用,而不必一定与多进程多线程框架结合。因此,这也给了使用者极大的自由度。

Melon的官方QQ群号:756582294

感谢阅读,欢迎各位在评论区留言评论。

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

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

相关文章

Python Tkinter GUI 基本概念

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;如果停止&#xff0c;就是低谷&#xf…

ACM题解Day10|总结篇|进制转化,GCD ,LCM ,二分答案

&#x1f525;博客介绍&#xff1a; 27dCnc [Cstring中find_first_not_of()函数和find_last_not_of()函数-CSDN博客] 方差,期望 概率 今日打卡: 算法周总结 ACM题解Day3| To Crash or not To Crash,Integer Prefix ,I don’t want to pay for the Late Jar-CSDN博客 第3题:…

【C语言】终の指针(前篇)

个人主页点这里~ 指针初阶点这里~ 指针初阶2.0点这里~ 指针进阶点这里~ 终の指针 一、回调函数二、qsort函数1、整形比较2、结构数据比较①结构体②-> 的使用③结构数据比较 一、回调函数 回调函数就是⼀个通过函数指针调用的函数。 把一个函数的指针作为参数传递给另一…

【JavaEE初阶】 JVM 运行时数据区简介

文章目录 &#x1f343;前言&#x1f332;堆&#xff08;线程共享&#xff09;&#x1f384;Java虚拟机栈&#xff08;线程私有&#xff09;&#x1f38b;本地方法栈&#xff08;线程私有&#xff09;&#x1f333;程序计数器&#xff08;线程私有&#xff09;&#x1f334;方法…

20个Python函数程序实例

前面介绍的函数太简单了&#xff1a; 以下是 20 个不同的 Python 函数实例 下面深入一点点&#xff1a; 以下是20个稍微深入一点的&#xff0c;使用Python语言定义并调用函数的示例程序&#xff1a; 20个函数实例 简单函数调用 def greet():print("Hello!")greet…

2025张宇考研数学,百度网盘视频课+36讲PDF讲义+真题

张宇老师的课属于幽默生动&#xff0c;会让一个文科生爱上数学&#xff0c;但是有的同学不知道在哪看&#xff0c;可以看一下&#xff1a;2025张宇考研数学全程网盘 docs.qq.com/doc/DTmtOa0Fzc0V3WElI 可以粘贴在浏览器 张宇30讲作为一本基础讲义&#xff1a;和教材…

unity学习(50)——服务器三次注册限制以及数据库化角色信息5--角色信息数据库化收尾

上一节内容结束后确实可以写入文件了&#xff0c;但还有两个问题&#xff1a; 1.一个是players.txt中&#xff0c;每次重启服务器&#xff0c;当注册新账号创建角色时&#xff0c;players.txt之前内容都会清空。 2.players.txt之前已经注册3次的账号&#xff0c;新注册的角色…

BUUCTF-Misc2

wireshark1 1.打开附件 发现是流量包&#xff0c;放到Wireshark中分析 2.过滤 根据题目的提示寻找管理员登录的网站&#xff0c;从中获取密码 用http.request.methodPOST&#xff0c;过滤当前的 HTTP 请求为 POST 方法 3.查找 双击过滤后的流量包&#xff0c;查找管理员密码…

C# 高阶语法 —— Winfrom链接SQL数据库的存储过程

存储过程在应用程序端的使用的优点 1 如果sql语句直接写在客户端&#xff0c;以一个字符串的形式体现的&#xff0c;提示不友好&#xff0c;会导致效率降低 2 sql语句写在客户端&#xff0c;可以利用sql注入进行攻击&#xff0c;为了安全性&#xff0c;可以把sql封装在…

基于cnn卷积神经网络的车辆颜色检测识别-图像去雾-图像去雨(改进yolo目标检测-附代码)

– 引言&#xff1a; 开篇简述图像处理在智能交通监控、自动驾驶等领域的关键作用&#xff0c;并强调随着深度学习尤其是卷积神经网络&#xff08;CNN&#xff09;的发展&#xff0c;在复杂环境下的车辆颜色精确识别、图像恢复&#xff08;如去雾和去雨&#xff09;等难题得以…

CTP-API开发系列之五:SimNow环境介绍

CTP-API开发系列之五&#xff1a;SimNow环境介绍 CTP-API开发系列之五&#xff1a;SimNow环境介绍SimNow模拟测试环境第一套第二套登录关键字段可视化终端常见问题 CTP-API开发系列之五&#xff1a;SimNow环境介绍 如果你要研发一套国内期货程序化交易系统&#xff0c;从模拟测…

fasta文件与fastq文件相互转化Python脚本

fa文件与fq文件互相转换 今天分享的内容是fasta文件与fastq文件的基本知识&#xff0c;以及通过Python实现两者互相转换的方法。 测序数据公司给的格式通常是fq.gz&#xff0c;也就是fastq文件&#xff0c;计算机的角度来说&#xff0c;生物的序列属于一种字符串&#xff0c;就…