freeswitch的任务引擎实现分析
概述
freeswitch核心框架中有一个定时任务系统,在开发过程中用来做一些延时操作和异步操作很方便。
我们在VOIP的呼叫流程中,经常会有一些对实时性要求没那么高的操作,或者会有阻塞流程的操作,我们都可以开启一个定时任务子流程,来达到延时和异步的目标。
下面,我们来对这个任务引擎的代码实现做一个简单的梳理和分析。
环境
centos:CentOS release 7.0 (Final)或以上版本
freeswitch:v1.8.7
GCC:4.8.5
数据结构
源码文件
src\include\switch_scheduler.h
src\switch_scheduler.c
任务数据结构
struct switch_scheduler_task {
int64_t created;
int64_t runtime;
uint32_t cmd_id;
uint32_t repeat;
char *group;
void *cmd_arg;
uint32_t task_id;
unsigned long hash;
};
struct switch_scheduler_task_container {
switch_scheduler_task_t task;
int64_t executed;
int in_thread;
int destroyed;
int running;
switch_scheduler_func_t func;
switch_memory_pool_t *pool;
uint32_t flags;
char *desc;
struct switch_scheduler_task_container *next;
};
typedef struct switch_scheduler_task_container switch_scheduler_task_container_t;
static struct {
switch_scheduler_task_container_t *task_list;
switch_mutex_t *task_mutex;
uint32_t task_id;
int task_thread_running;
switch_queue_t *event_queue;
switch_memory_pool_t *memory_pool;
} globals;
总图

常用接口
查看src\include\switch_scheduler.h头文件,常用接口如下。
switch_scheduler_add_task //Schedule a task in the future
switch_scheduler_del_task_id //Delete a scheduled task
switch_scheduler_del_task_group //Delete a scheduled task based on the group name
switch_scheduler_task_thread_start //Start the scheduler system
switch_scheduler_task_thread_stop //Stop the scheduler system
外部接口很简单。初始化接口使用start和stop,新增任务使用add_task,删除任务使用del_task_id,另外有一个del_task_group的接口针对任务群。
引擎初始化switch_scheduler_task_thread_start
函数原型
SWITCH_DECLARE(void) switch_scheduler_task_thread_start(void);
函数逻辑:
1, 初始化内存池globals.memory_pool。
2, 初始化互斥锁globals.task_mutex。
3, 初始化消息队列globals.event_queue。
4, 创建任务执行线程,线程函数switch_scheduler_task_thread,以下是任务线程的逻辑流程。
5, 设置全局变量globals.task_thread_running = 1。
6, 任务线程循环开始,task_thread_loop(0)。
7, 加锁globals.task_mutex。
8, 遍历任务链表globals.task_list,检查任务执行时间,符合执行时间的任务检查线程标识,对于有单独线程标识SSHF_OWN_THREAD的任务启动线程task_own_thread并执行,对于没有单独线程标识的任务,在当前线程中执行。
9, 解锁globals.task_mutex。
10, 加锁globals.task_mutex。
11, 遍历任务链表globals.task_list,检查任务删除标识tp->destroyed,销毁任务,释放任务相关内存。
12, 解锁globals.task_mutex。
13, 从全局消息队列globals.event_queue中获取事件,并发布该事件。
14, 任务线程循环结束。
15, task_thread_loop(1),遍历任务链表globals.task_list,设置所有任务删除标识tp->destroyed = 1,销毁任务,释放任务相关内存。
16, 从全局消息队列globals.event_queue中获取事件并销毁。
17, 设置全局变量globals.task_thread_running = 0。
引擎初始化后的内存模型如图

引擎停止switch_scheduler_task_thread_stop
函数原型
SWITCH_DECLARE(void) switch_scheduler_task_thread_stop(void);
函数逻辑:
1, 设置全局变量globals.task_thread_running=-1。
2, 等待任务线程退出。
3, 销毁内存池globals.memory_pool。
新增任务switch_scheduler_add_task
函数原型
SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
switch_scheduler_func_t func,
const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags);
函数逻辑:
1, 加锁globals.task_mutex。
2, 分配一块内存给任务容器container,类型为switch_scheduler_task_container_t。
3, container数据初始化。包括回调函数func和任务预定运行时间等信息。
4, 将container插入任务链表globals.task_list的队尾。
5, 解锁globals.task_mutex。
6, 新建SWITCH_EVENT_ADD_SCHEDULE事件,并将事件插入消息队列globals.event_queue。
7, 结束返回任务id。
增加多个任务之后的内存模型如图

删除任务switch_scheduler_del_task_id
函数原型
SWITCH_DECLARE(uint32_t) switch_scheduler_del_task_id(uint32_t task_id);
函数逻辑:
1, 加锁globals.task_mutex。
2, 遍历任务链表globals.task_list,找到对应task_id的任务。
3, 任务标识SSHF_NO_DEL则不删除。
4, 任务正在运行则不删除。
5, 设置任务删除标识tp->destroyed++。
6, 解锁globals.task_mutex。
总结
任务引擎中的循环,在任务执行正常的情况下,每隔500ms检查1次任务链表,在实际应用中,可能会有一定的延迟,无法做到实时执行。
对于任务的执行过程,考虑到有阻塞操作的任务,一定要使用单独线程执行,否则会阻塞其他任务。
定时任务引擎,使用时间轮模式是否更好用?
空空如常
求真得真
freeswitch的任务引擎实现分析的更多相关文章
- JQuery Sizzle引擎源代码分析
最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦.有没有吹牛?是不是我说大话了? 什么是Sizzle引擎? 我们经常使用JQuery的选择器查询 ...
- Java三大主流开源工作流引擎技术分析
首先,这个评论是我从网上,书中,搜索和整理出来的,也许有技术点上的错误点,也许理解没那么深入.但是我是秉着学习的态度加以评论,学习,希望对大家有用,进入正题! 三大主流工作流引擎:Shark,oswo ...
- Spark与Flink大数据处理引擎对比分析!
大数据技术正飞速地发展着,催生出一代又一代快速便捷的大数据处理引擎,无论是Hadoop.Storm,还是后来的Spark.Flink.然而,毕竟没有哪一个框架可以完全支持所有的应用场景,也就说明不可能 ...
- [转]JQuery - Sizzle选择器引擎原理分析
原文: https://segmentfault.com/a/1190000003933990 ---------------------------------------------------- ...
- Presto查询引擎简单分析
Hive查询流程分析 各个组件的作用 UI(user interface)(用户接口):提交数据操作的窗口Driver(引擎):负责接收数据操作,实现了会话句柄,并提供基于JDBC / ODBC的ex ...
- 005 -- Mysql数据库引擎特点分析
常用的数据库引擎的特点: ISAM: ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库查询次数要远大于更新次数.因此,ISAM执行读取操作的速度很快,而且不占用大量的 ...
- Flink流式引擎技术分析--大纲
Flink简介 Flink组件栈 Flink特性 流处理特性 API支持 Libraries支持 整合支持 Flink概念 Stream.Transformation.Operator Paralle ...
- MongoDb Mmap引擎分析
版权声明:本文由孔德雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/137 来源:腾云阁 https://www.qclo ...
- 开源大数据引擎:Greenplum 数据库架构分析
Greenplum 数据库是最先进的分布式开源数据库技术,主要用来处理大规模的数据分析任务,包括数据仓库.商务智能(OLAP)和数据挖掘等.自2015年10月正式开源以来,受到国内外业内人士的广泛关注 ...
随机推荐
- 简述ASP.NET网站开发步骤
新建解决方案 清除解决方案 重新生成解决方案 发布应用程序 设置配置文件 重命名配置文件 发布后生成的文件 IIS安装 安装完成后,输入http://localhost/出现 打开IIS 添加自己的网 ...
- C# 计算三角形和长方形 周长面积
编写一个控制台应用程序,输入三角形或者长方形边长,计算其周长和面积并输出. 代码如下: using System; using System.Collections.Generic; using Sy ...
- elasticsearch算法之词项相似度算法(一)
一.词项相似度 elasticsearch支持拼写纠错,其建议词的获取就需要进行词项相似度的计算:今天我们来通过不同的距离算法来学习一下词项相似度算法: 二.数据准备 计算词项相似度,就需要首先将词项 ...
- SpingMVC注解式开发-处理器方法的参数(形参request等)
HttpServletRequest HttpServletResponse HttpSession 请求中所携带的请求参数
- 在build中配置resources, 来防止我们资源导出失败问题
<!--在build中配置resources, 来防止我们资源导出失败问题--> <build> <resources> <resource> < ...
- python第三方模块详细教程(紧急情况宝典)
目录 一:第三方模块 第三方模块:并不是python自带的 需要基于网络下载! 使用下载第三方模块 需要将python pip添加到环境变量 1.验证pip路径添加成功 2.pycharm添加第三方模 ...
- Spring源码-IOC部分-Xml Bean解析注册过程【3】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- ApacheCN 深度学习译文集 20201229 更新
新增了七个教程: TensorFlow 和 Keras 应用开发入门 零.前言 一.神经网络和深度学习简介 二.模型架构 三.模型评估和优化 四.产品化 TensorFlow 图像深度学习实用指南 零 ...
- [HNOI2009]双递增序列
不难发现本题贪心是不好做的,可以考虑 \(dp\). 首先的一个想法就是令 \(dp_{i, j, k, l}\) 表示当前选到第 \(i\) 个位置,当前第一个序列选了 \(j\) 个数,当前第一个 ...
- GFS 分布式文件系统
GFS 分布式文件系统 1.GlusterFS概述 : GlusterFS简介 a) GlusterFS是一-个开源的分布式文件系统. 由存储服务器.客户端以及NFS/Samba存储网关(可选,根据 ...