FS 主函数main()
Freeswitch的主函数是在文件switch.c中定义的,该文件的260行是整个程序的入口,主函数主要完成的功能是包括,命令行解析,初始化apr库,构建全局内存池,模块加载和初始化核心组件。
初始化apr库是由apr_initialize()函数完成的,apr库是apache的可移植动态库,完成相关的内存池,线程管理的跨平台工作。该函数的调用在主函数的659行。
745行的switch_core_set_globals()主要是完成全局目录的设置。不过,在switch_core_init()中再一次调用了该函数。
747行的pid= getpid()获取程序的进程号。
754行利用apr_pool_create()创建一个匿名的内存池,由主函数中定义的switch_memory_pool_t*pool局部指针指向,但是可以知道,该内存池将作为程序的整个运行周期所使用。
本分析最关键的一点出现在784行,该行调用了switch_core_init_and_modload()函数,该函数完成了核心组件的初始化以及各个模块的动态加载。最终,形成了一个统一的系统。
switch_core_init_and_modload()
函数定义在switch_core.c文件中,第1526行。函数原型如下:
SWITCH_DECLARE(switch_status_t)
switch_core_init_and_modload(switch_core_flag_tflags, switch_bool_t console, const char **err)
其中,SWITCH_DECLARE(type)宏在windows下展开为
#define SWITCH_DECLARE(type) __declspec(dllexport) type __stdcall
主要用于将函数声明为dll的导出符号,这样,在其他模块中,便可以使用该函数了。而在其他系统平台上,该宏是一个空宏,例如在linux下,共享库的符号是全局的,不需要声明为导出符号。一般来说,freeswitch其他的动态加载模块所定义的函数不需要用该宏声明,在windows平台下,各个模块之间是隔离的,而核心模块中定义的函数大部分使用了该宏声明,因为其他模块需要大量使用核心模块中的核心函数,这里所指的核心模块是FreeSwitchCoreLib共享对象。
于是可以知道,switch_core_init_and_modload()函数可以在其他依赖于核心模块的动态加载模块中使用,这里主函数所在的模块是FreeSwitchConsole,依赖于核心模块,于是,便可以使用该函数来完成模块加载。
switch_core_init()
在该函数中调用了switch_core_init()函数,用来初始化一些全局化的信息,包括一个全局的switch_runtime结构,各种全局的哈希表,互斥变量。一条一条地分心如下:
① 全局的switch_runtime结构runtime部分字段的初始化——
代码段如下:
if(runtime.runlevel > 0) {
/* one percustomer */
returnSWITCH_STATUS_SUCCESS;
}
runtime.runlevel++;//从这里可见,runlevel大于0是一个服务器已启动的标志,所以不必在进行
//以下的初始化操作,直接返回SWITCH_STATUS_SUCCESS即可。
runtime.dummy_cng_frame.data =runtime.dummy_data;
runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data);
runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data);
switch_set_flag((&runtime.dummy_cng_frame),SFF_CNG);
switch_set_flag((&runtime),SCF_NO_NEW_SESSIONS);
runtime.hard_log_level = SWITCH_LOG_DEBUG;
runtime.mailer_app = "sendmail";
runtime.mailer_app_args = "-t";