标准
$TOP/build $TOP/pjlib
[包含Makefile]
[针对symbian的Makefile] [参考上面] [参考上面]
[参考上面] [参考上面] [参考上面]
$TOP/build.symbian $TOP/pjlib-util $TOP/pjnath $TOP/pjmedia $TOP/pjsip $TOP/pjsip-apps $TOP/third_party bin build
而在每个子目录,可以看到分为:
[编译后产生的二进制文件] [Makefile]
build/output build/wince-evc4
[doxygen的文档,用doxygen docs/doxygen.cfg产生] [头文件] [编译后产生的库] [源代码]
docs lib src
include
图2:PJSIP包文件结构
3) PJLIB简介
要理解好PJSIP,就不得不先说说PJLIB,PJLIB算的上是这个库中最基础的库,正是这
文案
标准
个库的优美实现,才让PJSIP变得如此优越。
PJLIB提供了一系列特征,这是我们下面分析的重点,涉及到: 1).非动态内存分配[No Dynamic Memory Allocations]
实现了内存池,获取内存是从与分配的内存池中获取,高性能程序多会自己构造内
存池,后面我们会解释该内存池的使用以及基本的原理。根据作者的比较,是常规的 malloc()/free()函数的30倍。
2).OS抽象[Operating System Abstraction]
实现OS抽象的根本原因在与可移植性,毋庸置疑:).涉及到:
a).线程[Threads.]
b).线程本地存储[Thread Local Storage.] c).互斥[Mutexes.] d).信号灯[Semaphores.] e).原子变量[Atomic Variables.] f).临届区[Critical sections.] g).锁对象[Lock Objects.] h).事件对象[Event Object.]
i).时间管理[Time Data Type and Manipulation.] j).高解析的时间戳[High Resolution Timestamp.]
3).低层的网络相关IO[Low-Level Network I/O] 这涉及到:
a).Socket抽象[Socket Abstraction.]
b).网络地址解析[Network Address Resolution.] c).实现针对Socket的select API[Socket select() API.] 4).时间管理[Timer Management]
这主要涉及到两个部分,一个时定时器的管理,还有就是时间解析的精度(举例说
来,就是能精确到哪个时间等级,比如 POSIX sleep(),就只能以秒为单位,而使用select()则可以实现毫秒级别的计时)
5).各种数据结构[Various Data Structures]
主要有:
a).针对字符串的操作[String Operations] b).数组辅助[Array helper] c).Hash表[Hash Tabl] d).链表[Linked List]
e).红黑平衡树[Red/Black Balanced Tree] 使用的是TRY/CATCH
6).异常处理[Exception Construct] 7).LOG机制[Logging Facility]
8).随机数以及GUID的产生[Random and GUID Generation]
GUID指的是\,只是一个标识而已
4) PJLIB的使用以及原理
? 快速内存池[Fast Memory Pool]
前面说过,使用内存池的原因在于性能的考虑,原因是C风格的malloc()以及C++风
格的new操作在高性能或实时条件下表现并不太好,原因在于性能的瓶颈在于内存碎片问题
文案
标准
下面列举其优点与需要主要的问题: 优点:
a).不像其它内存池,允许分配不同尺寸的chunks.
b).快速. 内存chunks拥有O(1)的复杂度,并且操作仅仅是指针的算术运算,其间不需c).有效使用内存. 除了可能因为内存对齐的原因会浪费很少的内存外,内存的使用d).可预防内存泄漏.在C/C++程序中如果出现内存泄漏问题,其查找过程哪个艰辛,
要使用锁住任何互斥量. 效率非常高.
不足为外人道也:([曾经有次用别人的Code,出现了内存泄漏,在开发板上查找N天,又没工具可在开发板上使用,哪个痛苦,想自杀:(]原因很简单,你的内存都是从内存池中获取的,就算你没有释放你获取的内存,只要你记得把内存池destroy,那么内存还是会还给系统.还有设计带来的一些其它益处,比如可用性和灵活性.
e).内存泄漏更容易被跟踪.这是因为你的内存是在指定的内存池中分配的,只要能很f).设计上从内存池中获取内存这一操作是非线程安全的.原因是设计者认为内存池
快定位到内存池,内存泄漏的侦测就方便多了.
被上层对象所拥有,线程安全应该由上层对象去保证,这样的话,没有锁的问题会让内存分配变得非常的快.
g).内存池的行为像C++中的new的行为,当内存池获取内存chunks会抛出
PJ_NO_MEMORY_EXCEPTION异常,当然,因为支持异常处理,也可以使用其它方式让上层程序灵活的定义异常的处理.[这是异常处理的基本出发点,但是这有大量的争论,原因是这改变了程序的正常流程,谁能去保证这种流程是用户所需要的呢,因此C++中的异常处理饱受争议,请酌情使用]
h). 可以在后端使用任何的内存分配器.默认情况下是使用malloc/free管理内存池的
块,但是应用程序也可以指定自己的策略(strategy),例如从一个全局存储空间分配内存.
? 内存池的使用[Using Memory Pool]
a).创建内存池工厂[Create Pool Factory] 上面不是提及内存池的内部分配策略以及
异常处理方式么, 其实这就是指定这个的:) 当然,不需要你每个内存池都自己取指定策略和异常处理方式,PJLIB已经有了一个默认的实现:Caching Pool Factory,这个内存池工厂的初始化使用函数pj_caching_pool_init()
b).创建内存池[Create The Pool] 使用pj_pool_create(),其参数分别为内存工厂(Pool c).根据需要分配内存[Allocate Memory as Required] 然后,你就可以使用 d).Destroy内存池[Destroy the Pool] 这实际上是把预分配的内存还给系统.
Factory),内存池的名字(name),初始时的大小以及增长时的大小.
pj_pool_alloc(), pj_pool_calloc(), 或pj_pool_zalloc()从指定的内存池根据需要去获取内存了 e).Destroy内存池工厂[Destroy the Pool Factory] 这没什么好说的.
******************************************************************************/
4. 实验环境
此实验采用的是Win8下Microsoft Visual Stdio 2013工程。 使用的开源包是PJSIP version 2.4.5
文案
标准
******************************************************************************/
5. 实验步骤
5.1. A.在VS2013平台编译pjproject-2.3
用VS2013打开pjsip2.4.5项目
图3:VS项目升级提示
****************************************************************************** 设定启动项目在解决方案资源管理器一栏,找到pjsua,右键点击,在菜单中选择设为启动项目,可以看到pjsua字体变粗,表示设置成功具体操作如图4所示
文案
标准
创建“config_site.h”创建头文件“pjlib/include/pj/config_site.h”,空文件即可,不需要往里面写内容 4. 添加头文件夹(可选)添加下面的库文件夹到工程的搜索路径:
? pjlib/include ? pjlib-util/include ? pjnath/include ? pjmedia/include ? pjsip/include
操作方法:项目→属性→配置属性→链接器→常规→附加库目录→编辑,在弹出的对话框可以把库文件夹依次引入该过程如图4,5所示
******************************************************************************
文案