概述

freeswitch的外围模块是插件式的,可以动态的加载和卸载,使用起来非常的灵活和方便。

如果我们自己来设计一个开源的代码框架,相信这种插件式的模块结构是非常适合多人合作的模式。

本文对fs的模块加载接口进行一些分析和讨论,作为借鉴。

环境

centos:CentOS  release 7.0 (Final)或以上版本

freeswitch:v1.8.7

GCC:4.8.5

模块接口

freeswitch新增mod_task模块的介绍,见之前的文章。

在mod_task模块实现中,有3个最基本的宏定义。分别对应模块的加载,卸载和定义。

SWITCH_MODULE_LOAD_FUNCTION(mod_task_load);

SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_task_shutdown);

SWITCH_MODULE_DEFINITION(mod_task, mod_task_load, mod_task_shutdown, NULL);

宏定义展开后

switch_status_t mod_task_load (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool);

switch_status_t mod_task_shutdown (void);

static const char modname[] =  mod_task ;

switch_loadable_module_function_table_t mod_task_module_interface = {

5,

mod_task_load,

mod_task_shutdown,

NULL,

0

};

使用nm命令查看mod_task模块符号表

[root@localhost mod]# nm -s mod_task.so

00000000002020c8 B __bss_start

U bzero@@GLIBC_2.2.5

00000000002020c8 b completed.6355

w __cxa_finalize@@GLIBC_2.2.5

0000000000000b10 t deregister_tm_clones

0000000000000b80 t __do_global_dtors_aux

0000000000201cd0 t __do_global_dtors_aux_fini_array_entry

0000000000201ce0 d __dso_handle

0000000000201ce8 d _DYNAMIC

00000000002020c8 D _edata

00000000002020d0 B _end

0000000000001060 T _fini

0000000000000bc0 t frame_dummy

0000000000201cc8 t __frame_dummy_init_array_entry

00000000000014c0 r __FRAME_END__

U free@@GLIBC_2.2.5

00000000000012c0 r __func__.18215

0000000000001300 r __func__.18222

00000000000012e0 r __func__.18230

00000000000012d2 r __func__.18237

00000000000012a0 r __func__.18245

0000000000202000 d _GLOBAL_OFFSET_TABLE_

w __gmon_start__

000000000000132c r __GNU_EH_FRAME_HDR

00000000000009f8 T _init

w _ITM_deregisterTMCloneTable

w _ITM_registerTMCloneTable

0000000000201cd8 d __JCR_END__

0000000000201cd8 d __JCR_LIST__

w _Jv_RegisterClasses

0000000000001323 r modname

0000000000000c40 t mod_task_load

00000000002020a0 D mod_task_module_interface

0000000000000c00 t mod_task_shutdown

0000000000000b40 t register_tm_clones

U __strdup@@GLIBC_2.2.5

U switch_channel_export_variable_var_check

U switch_console_set_complete

U switch_core_session_get_channel

U switch_event_bind

U switch_event_get_header_idx

U switch_loadable_module_create_interface

U switch_loadable_module_create_module_interface

U switch_log_printf

U switch_separate_string

0000000000000d80 t task_api_function

0000000000000ee0 t task_app_function

0000000000000f70 t task_event_channel_hangup_complete

0000000000001010 t task_event_handler

00000000002020c8 d __TMC_END__

模块加载

freeswitch启动过程中,会根据配置文件“/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml”的内容,顺序加载所有模块。

对某一个模块的加载过程参考“src\switch_loadable_module.c”文件中的“switch_loadable_module_load_file”函数。

函数中主要使用了“dlopen”,“dlsym”等系统接口,来打开“mod_task.so”动态库文件和查找到”mod_task_module_interface”结构数据。

再调用”mod_task_module_interface->load”函数(指向“mod_task_load”),初始化mod_task模块。

模块卸载

模块卸载的流程参考”src\switch_loadable_module.c”文件中的“do_shutdown”函数。

在全局数据中查找到mod_task模块结构体,调用“module->switch_module_shutdown”函数(指向“mod_task_shutdown”),清理模块,回收资源。

总结

freeswitch使用了系统的动态库管理接口,来动态的加载和卸载外围模块,灵活方便。

空空如常

求真得真

freeswitch插件式模块接口实现方式的更多相关文章

  1. Orchard源码分析(1):插件式的支持——模块和主题

    在Orchard,模块和主题都是可以插拔式的,在源码处理时,用类型(参考:DefaultExtensionTypes)区分,都没太大的本质区别,以下都称做模块. 插件的支持,实现分以下几步: 搜集模块 ...

  2. Javascript的一种代码结构方式——插件式

    上几周一直在做公司的webos的前端代码的重构,之中对javascript的代码进行了重构(之前的代码耦合严重.拓展.修改起来比较困难),这里总结一下当中使用的一种代码结构——插件式(听起来怎么像独孤 ...

  3. C++中模块(Dll)对外暴露接口的方式

    总结下C++中模块(Dll)对外暴露接口的方式: (1)导出API函数的方式这种方式是Windows中调用DLL接口的最基本方式,GDI32.dll, User32.dll都是用这种方式对外暴露系统A ...

  4. C#实现接口的两种方式:显示实现和隐式实现接口

    本示例声明一个接口IDimensions 和一个类 Box,显式实现了接口成员 GetLength 和 GetWidth. 通过接口实例 dimensions 访问这些成员. interface ID ...

  5. 使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)

    对于一些较小的项目,具备一定经验的开发人员应该能够设计和构建出便于进行维护和扩展的应用程序.但是,随着功能模块数量(以及开发维护这些部件的人员)的不断增加,对项目实施控制的难度开始呈指数级增长. Sa ...

  6. Android应用插件式开发解决方法

    转自:http://blog.csdn.net/arui319/article/details/8109650 一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来 ...

  7. Android应用插件式开发解决方法[转]

    一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来越多,APK安装包也越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块.此时可能就需要考虑如何分 ...

  8. MEF 插件式开发之 DotNetCore 初体验

    背景叙述 在传统的基于 .Net Framework 框架下进行的 MEF 开发,大多是使用 MEF 1,对应的命名空间是 System.ComponentModel.Composition.在 Do ...

  9. MEF 插件式开发之 WPF 初体验

    MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场景中,C/S 和 B/S 中都有相应的使用场景,其中包括但不限于 ASP.NET MVC .ASP WebForms.WPF ...

随机推荐

  1. anaconda安装PIL

    PIL仅支持到python2.7: Pillow支持Python 3.x: conda install pillow 参考文献: 使用anaconda安装python3版本的PIL_不行不至-CSDN ...

  2. java 语言基础作业

    1.动手动脑 仔细阅读示例: EnumTest.java,运行它,分析运行结果? 程序运行结果: 实验结论:枚举类型是引用类型!枚举不属于原始数据类型,它的每个具体值都引用一个特定的对象.相同的值则引 ...

  3. <数据结构>XDOJ327.最短路径

    问题与解答 问题描述 求图中任意两个顶点之间的最短路径. 输入格式 输入数据第一行是一个正整数,表示图中的顶点个数n(顶点将分别按0,1,-,n-1进行编号).之后的n行每行都包含n个整数,第i行第j ...

  4. Java初学者作业——声明变量对个人信息进行输入和输出

    返回本章节 返回作业目录 需求说明: 声明变量存储个人信息(姓名.年龄.性别.地址以及余额),通过键盘输入个人信息并存储在相应的变量中, 最后将个人信息输出. 实现思路: 声明存储姓名.年龄.性别.地 ...

  5. Java初学者作业——编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天。

    返回本章节 返回作业目录 需求说明: 编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天. 实现思路: (1)声明变量 year.month和 date,用于存储日期中的年.月.日 ...

  6. Drools创建Maven工程

    1.说明 本文介绍创建Drools的Maven工程的方法, 仅使用Eclipse开发工具, 不使用Drools的相关插件, 先创建一个Maven工程, 然后引入Drools的相关依赖即可, 最后再写一 ...

  7. Git 标签使用详解

    列出标签 # 默认按字母排序显示 $ git tag # 模糊匹配查找标签 $ git tag -l "v1.8.5*" 创建标签 # 创建附注标签 $ git tag -a v1 ...

  8. CSS基础 transform属性的基本使用 移动 旋转 缩放

    1.实现元素位移效果 语法:transform:translate(x轴水平移动距离,Y轴垂直移动距离) 取值:正负都可以 取值方式:数字+px 百分比 :参照自己本的盒子的百分比 比如:本身自己的宽 ...

  9. nginx配置图片路径

    首先, 在linux下创建你存放资源的目录,例如:/data/images:用于存放图片. 下一步,打开default.conf配置文件找到server块下的location添加如下 location ...

  10. Go数组遍历与排序

    遍历数组 Go遍历数组有两种方式 1.按照数组下标进行遍历 2.用range遍历 package main import ( "fmt" ) func main() { // 声明 ...