FreeSWITCH源码分析之主函数main()






FreeSWITCH源码分析之主函数main()





原创

2017年08月21日 16:19:54

        <ul class="article_tags clearfix csdn-tracking-statistics tracking-click" data-mod="popu_377" style="display: none;">
            <li class="tit">标签:</li>







    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行。函数原型如下:

  1. SWITCH_DECLARE(switch_status_t)  
  2.   
  3. switch_core_init_and_modload(switch_core_flag_tflags, switch_bool_t console, const char **err)  
  4.   
  5. 其中,SWITCH_DECLARE(type)宏在windows下展开为  
  6.   
  7. #define SWITCH_DECLARE(type) __declspec(dllexport) type __stdcall  
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部分字段的初始化——

代码段如下:

  1. if(runtime.runlevel > 0) {  
  2.   
  3.     /* one percustomer */  
  4.   
  5.     returnSWITCH_STATUS_SUCCESS;  
  6.   
  7. }  
  8.   
  9.   
  10.   
  11. runtime.runlevel++;//从这里可见,runlevel大于0是一个服务器已启动的标志,所以不必在进行  
  12.   
  13. //以下的初始化操作,直接返回SWITCH_STATUS_SUCCESS即可。  
  14.   
  15. runtime.dummy_cng_frame.data =runtime.dummy_data;  
  16.   
  17. runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data);  
  18.   
  19. runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data);  
  20.   
  21. switch_set_flag((&runtime.dummy_cng_frame),SFF_CNG);  
  22.   
  23.   
  24.   
  25. switch_set_flag((&runtime),SCF_NO_NEW_SESSIONS);  
  26.   
  27. runtime.hard_log_level = SWITCH_LOG_DEBUG;  
  28.   
  29. runtime.mailer_app = ”sendmail”;  
  30.   
  31. runtime.mailer_app_args = ”-t”;  
  32.   
  33. runtime.max_dtmf_duration =SWITCH_MAX_DTMF_DURATION;  
  34.   
  35. runtime.default_dtmf_duration =SWITCH_DEFAULT_DTMF_DURATION;  
  36.   
  37. runtime.min_dtmf_duration= SWITCH_MIN_DTMF_DURATION;  
     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";

     runtime.max_dtmf_duration =SWITCH_MAX_DTMF_DURATION;

     runtime.default_dtmf_duration =SWITCH_DEFAULT_DTMF_DURATION;

     runtime.min_dtmf_duration= SWITCH_MIN_DTMF_DURATION;


接下来又重新初始化了一遍apr库,很奇怪,不知道是不是一个多余的步骤。^_^

 

  1. /* INIT APR andCreate the pool context */  
  2.   
  3. if(apr_initialize() != SWITCH_STATUS_SUCCESS) {  
  4.   
  5.     *err = ”FATALERROR! Could not initialize APR\n”;  
  6.   
  7.     returnSWITCH_STATUS_MEMERR;  
  8.   
  9. }  
  10.   
  11. if(!(runtime.memory_pool = switch_core_memory_init())) {  
  12.   
  13.     *err = ”FATALERROR! Could not allocate memory pool\n”;  
  14.   
  15.     returnSWITCH_STATUS_MEMERR;  
     /* INIT APR andCreate the pool context */

     if(apr_initialize() != SWITCH_STATUS_SUCCESS) {

         *err = "FATALERROR! Could not initialize APR\n";

         returnSWITCH_STATUS_MEMERR;

     }

     if(!(runtime.memory_pool = switch_core_memory_init())) {

         *err = "FATALERROR! Could not allocate memory pool\n";

         returnSWITCH_STATUS_MEMERR;
  1. <span style=“color:rgb(51,51,51);font-family:verdana, Arial, Helvetica, sans-serif;font-size:14px;”>}//从这里可以看见,全局的runtime是有一个内存池来管理它所需要的其他资源的。</span>  
}//从这里可以看见,全局的runtime是有一个内存池来管理它所需要的其他资源的。


②  安装时的目录信息的相关设置,与runtime结构挂钩,代码如下

  1. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//主目录,即工程所在目录,一般为./bin,./表示安装路径  
  2.   
  3. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//模块所在目录,一般为安装目录./mod,./表示安装路径  
  4.   
  5. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//配置文件所在目录,一般为./conf  
  6.   
  7. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//日志所在的目录。一般为./log  
  8.   
  9. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//进程文件所在目录,一般为./run,进程文件为freeswitch.pid  
  10.   
  11. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//数据库文件所在目录,一般为./db  
  12.   
  13. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//脚本文件所在目录,一般为./script,存放系统需要执行的脚本文件,  
  14.   
  15. //比较常用的由javascript脚本和lua脚本。  
  16.   
  17. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);  
  18.   
  19. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);  
  20.   
  21. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//录音文件所在目录  
  22.   
  23. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//声音文件所在目录。  
  24.   
  25. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//临时目录。  
switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//主目录,即工程所在目录,一般为./bin,./表示安装路径

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//模块所在目录,一般为安装目录./mod,./表示安装路径

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//配置文件所在目录,一般为./conf

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//日志所在的目录。一般为./log

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//进程文件所在目录,一般为./run,进程文件为freeswitch.pid

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//数据库文件所在目录,一般为./db

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//脚本文件所在目录,一般为./script,存放系统需要执行的脚本文件,

//比较常用的由javascript脚本和lua脚本。

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//录音文件所在目录

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//声音文件所在目录。

switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir,SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);//临时目录。


③     全局的互斥变量和哈希表初始化,代码片段如下:

  1.  switch_mutex_init(&runtime.uuid_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);  
  2.   
  3.  switch_mutex_init(&runtime.throttle_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);  
  4.   
  5.  switch_mutex_init(&runtime.session_hash_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);  
  6.   
  7.  switch_mutex_init(&runtime.global_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);  
  8.   
  9.  switch_mutex_init(&runtime.global_var_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);  
  10.   
  11.   
  12.   
  13. switch_core_hash_init(&runtime.global_vars,runtime.memory_pool);  
  14.   
  15. switch_core_hash_init(&runtime.mime_types,runtime.memory_pool);  
     switch_mutex_init(&runtime.uuid_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);

     switch_mutex_init(&runtime.throttle_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);

     switch_mutex_init(&runtime.session_hash_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);

     switch_mutex_init(&runtime.global_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);

     switch_mutex_init(&runtime.global_var_mutex,SWITCH_MUTEX_NESTED, runtime.memory_pool);

以及

    switch_core_hash_init(&runtime.global_vars,runtime.memory_pool);

    switch_core_hash_init(&runtime.mime_types,runtime.memory_pool);


 

④     系统相关的很重要的初始化

  1. 1.       switch_core_set_globals()  
  2.   
  3. 由于在主函数中已经设置好了各个安装目录,所以此次调用将不做任何实际意义的工作。  
  4.   
  5. 2.       switch_core_session_init(runtime.memory_pool)  
  6.   
  7. 3.       load_mime_types()  
  8.   
  9. 4.       gethostname(hostname, sizeof(hostname))获取主机名  
  10.   
  11. 5.       switch_find_local_ip(guess_ip,sizeof(guess_ip), &mask, AF_INET)获取主机的ip地址。这里主要是获取ipv4的地址,下面还要重新调用一次该函数获取ipv6的地址。  
  12.   
  13. 6.        switch_console_init(runtime.memory_pool)初始化控制台。函数的实际代码如下:  
  14.   
  15. a)   SWITCH_DECLARE(switch_status_t)switch_console_init(switch_memory_pool_t *pool)  
  16.   
  17. b)   {  
  18.   
  19. c)    switch_mutex_init(&globals.func_mutex,SWITCH_MUTEX_NESTED, pool);  
  20.   
  21. d)    switch_core_hash_init(&globals.func_hash,pool);  
  22.   
  23. e)    switch_console_add_complete_func(”::console::list_uuid”,(switch_console_complete_callback_t) switch_console_list_uuid);  
  24.   
  25. f)    returnSWITCH_STATUS_SUCCESS;  
  26.   
  27. g)        }  
  28.   
  29. 7.       switch_event_init(runtime.memory_pool)初始化freeswitch整个系统的事件机制,这个初始化很重要,在函数内部除了初始化一些互斥量,哈希队列,还创建了三个用于事件循环的队列,然后启动三个线程,分别代表了三个队列的时间循环处理线程。而所有的资源,都有runtime.memory_pool进行管理,event事件的循环处理见后续分析。  
  30.   
  31. 8.       switch_xml_init(runtime.memory_pool,err)进行xml配置文件相关的初始化。  
  32.   
  33. 9.       switch_log_init(runtime.memory_pool,runtime.colorize_console)日志系统的初始化。  
  34.   
  35. 10.    switch_load_core_config(”switch.conf”)读取全局的配置文件,然后根据该配置文件中的指令,依次读取后续的子目录下面的各个配置文件,详见后续分析。  
  36.   
  37. 11.    switch_core_state_machine_init(runtime.memory_pool)state_machine是整个FS系统的核心部位了,即通话状态机,根据各个channel的状态执行相应的状态处理函数,见后续分析。此处的函数为空函数。  
  38.   
  39. 12.    switch_core_sqldb_start()sql数据库的相关初始化。  
  40.   
  41. 13.    switch_rtp_init(runtime.memory_pool)rtp协议的初始化。函数内调用srtp_init()初始化rtp协议栈,freeswitch所用的rtp库是libsrtp。  
  42.   
  43. 14.    switch_scheduler_add_task(switch_epoch_time_now(NULL),heartbeat_callback, ”heartbeat”“core”, 0, NULL, SSHF_NONE |SSHF_NO_DEL)  
1.       switch_core_set_globals()

由于在主函数中已经设置好了各个安装目录,所以此次调用将不做任何实际意义的工作。

2.       switch_core_session_init(runtime.memory_pool)

3.       load_mime_types()

4.       gethostname(hostname, sizeof(hostname))获取主机名

5.       switch_find_local_ip(guess_ip,sizeof(guess_ip), &mask, AF_INET)获取主机的ip地址。这里主要是获取ipv4的地址,下面还要重新调用一次该函数获取ipv6的地址。

6.        switch_console_init(runtime.memory_pool)初始化控制台。函数的实际代码如下:

a)   SWITCH_DECLARE(switch_status_t)switch_console_init(switch_memory_pool_t *pool)

b)   {

c)    switch_mutex_init(&globals.func_mutex,SWITCH_MUTEX_NESTED, pool);

d)    switch_core_hash_init(&globals.func_hash,pool);

e)    switch_console_add_complete_func("::console::list_uuid",(switch_console_complete_callback_t) switch_console_list_uuid);

f)    returnSWITCH_STATUS_SUCCESS;

g)        }

7.       switch_event_init(runtime.memory_pool)初始化freeswitch整个系统的事件机制,这个初始化很重要,在函数内部除了初始化一些互斥量,哈希队列,还创建了三个用于事件循环的队列,然后启动三个线程,分别代表了三个队列的时间循环处理线程。而所有的资源,都有runtime.memory_pool进行管理,event事件的循环处理见后续分析。

8.       switch_xml_init(runtime.memory_pool,err)进行xml配置文件相关的初始化。

9.       switch_log_init(runtime.memory_pool,runtime.colorize_console)日志系统的初始化。

10.    switch_load_core_config("switch.conf")读取全局的配置文件,然后根据该配置文件中的指令,依次读取后续的子目录下面的各个配置文件,详见后续分析。

11.    switch_core_state_machine_init(runtime.memory_pool)state_machine是整个FS系统的核心部位了,即通话状态机,根据各个channel的状态执行相应的状态处理函数,见后续分析。此处的函数为空函数。

12.    switch_core_sqldb_start()sql数据库的相关初始化。

13.    switch_rtp_init(runtime.memory_pool)rtp协议的初始化。函数内调用srtp_init()初始化rtp协议栈,freeswitch所用的rtp库是libsrtp。

14.    switch_scheduler_add_task(switch_epoch_time_now(NULL),heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE |SSHF_NO_DEL)


在freeswitch中有一个task调度机制,这里讲heartbeat加入到task队列中。事件由

  1. switch_scheduler_task_container_t结构描述,在switch_scheduler.c中,通过全局的  
  2.   
  3. static struct {  
  4.   
  5. switch_scheduler_task_container_t*task_list;  
  6.   
  7. switch_mutex_t*task_mutex;  
  8.   
  9. uint32_t task_id;  
  10.   
  11. int task_thread_running;  
  12.   
  13. switch_memory_pool_t *memory_pool;  
  14.   
  15. } globals;  
switch_scheduler_task_container_t结构描述,在switch_scheduler.c中,通过全局的

static struct {

switch_scheduler_task_container_t*task_list;

switch_mutex_t*task_mutex;

uint32_t task_id;

int task_thread_running;

switch_memory_pool_t *memory_pool;

} globals;


 

Globals变量对task队列进行管理。Task的调度的线程也是在switch_core_init()中启动的,具体的启动函数时switch_scheduler_task_thread_start().该函数内部生成的线程主函数为switch_scheduler_task_thread():函数里有主循环;

  1. while (globals.task_thread_running == 1) {  
  2.   
  3.          if(task_thread_loop(0)) {  
  4.   
  5.               break;  
  6.   
  7.          }  
  8.   
  9.          switch_yield(500000);  
  10.   
  11. }  
while (globals.task_thread_running == 1) {

         if(task_thread_loop(0)) {

              break;

         }

         switch_yield(500000);

}


通过层层剥离,会进入task_thread_loop中一次执行挂接在switch_scheduler.c中得全局globals的task队列。

  

switch_loadable_module_init()

在switch_core_init_and_modload()中还调用了switch_loadable_module_init(),这里就是根据目录信息加载各个动态模块的地方了。函数定义在switch_loadable_module.c文件中,属于核心组件的一部分。

 

函数内根据平台做了相关处理,在win32平台下,还需要通过函数switch_loadable_module_path_init()获取环境变量的相关信息。另外需要注意的是,该函数内部重新重新生成了一个memory_pool不再是上面描述的runtime的memory_pool了。代码如下:

  1. switch_core_new_memory_pool(&loadable_modules.pool);  
  2.   
  3. 其中loadable_modules是一个文件作用域范围的全局量,  
  4.   
  5. static structswitch_loadable_module_container loadable_modules;类型为  
  6.   
  7. switch_loadable_module_container,定义如下:  
  8.   
  9. //************* switch_loadable_module_container的定义*****************************//  
  10.   
  11. structswitch_loadable_module_container {  
  12.   
  13. switch_hash_t *module_hash;//存放各个模块结构的哈希表指针  
  14.   
  15. switch_hash_t *endpoint_hash;// 存放各个endpoint_interface的哈希表指针  
  16.   
  17. switch_hash_t *codec_hash; // 存放各个codec_interface的哈希表指针  
  18.   
  19. switch_hash_t *dialplan_hash; // 存放各个diaplan_interface的哈希表指针  
  20.   
  21. switch_hash_t *timer_hash;// // 存放各个计时器的哈希表指针  
  22.   
  23. switch_hash_t *application_hash;//存放各个application_interface的哈希表指针  
  24.   
  25. switch_hash_t *api_hash; // 存放各个api_interface的哈希表指针  
  26.   
  27. switch_hash_t *file_hash;  
  28.   
  29. switch_hash_t *speech_hash;  
  30.   
  31. switch_hash_t *asr_hash;  
  32.   
  33. switch_hash_t *directory_hash;  
  34.   
  35. switch_hash_t *chat_hash;  
  36.   
  37. switch_hash_t *say_hash;  
  38.   
  39. switch_hash_t *management_hash;  
  40.   
  41. switch_mutex_t *mutex;//全局互斥量  
  42.   
  43. switch_memory_pool_t *pool;//用于模块相关的apr内存池  
  44.   
  45. };  
switch_core_new_memory_pool(&loadable_modules.pool);

其中loadable_modules是一个文件作用域范围的全局量,

static structswitch_loadable_module_container loadable_modules;类型为

switch_loadable_module_container,定义如下:

//************* switch_loadable_module_container的定义*****************************//

structswitch_loadable_module_container {

switch_hash_t *module_hash;//存放各个模块结构的哈希表指针

switch_hash_t *endpoint_hash;// 存放各个endpoint_interface的哈希表指针

switch_hash_t *codec_hash; // 存放各个codec_interface的哈希表指针

switch_hash_t *dialplan_hash; // 存放各个diaplan_interface的哈希表指针

switch_hash_t *timer_hash;// // 存放各个计时器的哈希表指针

switch_hash_t *application_hash;//存放各个application_interface的哈希表指针

switch_hash_t *api_hash; // 存放各个api_interface的哈希表指针

switch_hash_t *file_hash;

switch_hash_t *speech_hash;

switch_hash_t *asr_hash;

switch_hash_t *directory_hash;

switch_hash_t *chat_hash;

switch_hash_t *say_hash;

switch_hash_t *management_hash;

switch_mutex_t *mutex;//全局互斥量

switch_memory_pool_t *pool;//用于模块相关的apr内存池

};


该结构包含了若该的哈希表指针,分别指向存放各个接口结构的哈希表。

//***********************************************************************************//

 

接下来函数初始化了用于存放各个接口的哈希表,以及全局互斥量。

 

该函数是通过switch_loadable_module_load_module_ex((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, global, &err)函数加载模块的。可见这里使用到了模块的目录信息SWITCH_GLOBAL_dirs.mod_dir。

 

 

switch_loadable_module_load_module_ex()

函数原型为:

static switch_status_t switch_loadable_module_load_module_ex(char *dir, char*fname, switch_bool_t runtime, switch_bool_t global, constchar **err)

这里讲该函数顶定义成了一个static类型,只能在本文件中被调用。dir是上面个传下来的目录信息,fname是读取配置文件得到的需要加载的动态对象名(例如mod_conference.dll,mod_sofia.dll或mod_conference.so,mod_sofia.so等)

 

在该函数中,通过以下两个函数完成动态对象的加载:

1.  switch_loadable_module_load_file(path,file, global, &new_module),这里我是用了调用时的实参,globals并非上面提出的全局管理结构,而是一个SWITCH_STATUS的枚举对象。Path是加上了路径的完整文件名,而file仍然是配置文件中取得的名称。New_module是一个秒速模块的结构对象,具体的类型为

  1. a)   struct switch_loadable_module {  
  2.   
  3. b)        char *key;  
  4.   
  5. c)        char*filename;  
  6.   
  7. d)        int perm;  
  8.   
  9. e)        switch_loadable_module_interface_t*module_interface;  
  10.   
  11. f)        switch_dso_lib_t lib;  
  12.   
  13. g)        switch_module_load_t switch_module_load;  
  14.   
  15. h)        switch_module_runtime_tswitch_module_runtime;  
  16.   
  17. i)        switch_module_shutdown_tswitch_module_shutdown;  
  18.   
  19. j)        switch_memory_pool_t *pool;  
  20.   
  21. k)        switch_status_t status;  
  22.   
  23. l)        switch_thread_t *thread;  
  24.   
  25. m)        switch_bool_t shutting_down;  
  26.   
  27. n)        calltime_t *time_record;  
  28.   
  29. o)   };  
a)   struct switch_loadable_module {

b)        char *key;

c)        char*filename;

d)        int perm;

e)        switch_loadable_module_interface_t*module_interface;

f)        switch_dso_lib_t lib;

g)        switch_module_load_t switch_module_load;

h)        switch_module_runtime_tswitch_module_runtime;

i)        switch_module_shutdown_tswitch_module_shutdown;

j)        switch_memory_pool_t *pool;

k)        switch_status_t status;

l)        switch_thread_t *thread;

m)        switch_bool_t shutting_down;

n)        calltime_t *time_record;

o)   };


在switch_loadable_module_load_module_ex函数的开始出定义 

switch_loadable_module_t*new_module = NULL;

在switch_loadable_module_load_file函数中,会为每一个模块生成一个资源池

switch_core_new_memory_pool(&pool);

2.  switch_loadable_module_process(file,new_module)函数主要是将new_module以及module中定义的各个接口结构加入全局哈希表,在插入哈希表的过程中,由loadable_modules.mutex进行临界保护,举例如下:

  1. ①   switch_core_hash_insert(loadable_modules.module_hash, key,new_module);//将new_module  
  2.   
  3. //插入loadable_modules.module_hash指向的哈希表。  
  4.   
  5. ②   if (new_module->module_interface->endpoint_interface){  
  6.   
  7. constswitch_endpoint_interface_t *ptr;  
  8.   
  9.           for (ptr =new_module->module_interface->endpoint_interface; ptr; ptr =ptr->next) {  
  10.   
  11. switch_core_hash_insert(loadable_modules.endpoint_hash,ptr->interface_name, (const void *) ptr);  
  12.   
  13. }//end if  
①   switch_core_hash_insert(loadable_modules.module_hash, key,new_module);//将new_module

//插入loadable_modules.module_hash指向的哈希表。

②   if (new_module->module_interface->endpoint_interface){

constswitch_endpoint_interface_t *ptr;

          for (ptr =new_module->module_interface->endpoint_interface; ptr; ptr =ptr->next) {

switch_core_hash_insert(loadable_modules.endpoint_hash,ptr->interface_name, (const void *) ptr);

}//end if


//若new_module的module_interface中包含endpoint_interface,则将该endpoint_interface插入全局的endpoint_interface哈希表。

至此,模块加载也结束了。各个模块加载后各自进入自己的主线程中循环处理。

                </div>
</article>
  <div class="readall_box csdn-tracking-statistics tracking-click readall_box_nobg" data-mod="popu_376" style="display: none;">
      <div class="read_more_mask"></div>
      <a class="btn btn-large btn-gray-fred read_more_btn" target="_self">阅读全文</a>
  </div>
  <div class="article_copyright">

          </div>
  <ul class="article_collect clearfix csdn-tracking-statistics tracking-click" data-mod="popu_378" style="display: none;">
      <li class="tit">本文已收录于以下专栏:</li>




                  <form action="//blog.csdn.net/y_xianjun/phoenix/comment/submit?id=77451174" method="post" onsubmit="return subform(this);" id="commentform">
                      <textarea class="comment_content" name="comment_content" id="comment_content" placeholder="严禁讨论涉及中国之军/政相关话题,违者会被禁言、封号!" style="height: 28px;"></textarea>
                      <div class="bot_bar clearfix" style="opacity: 0;">
                          <div id="ubbtools" class="add_code">
                              <a href="#insertcode" code="code" target="_self"><i class="icon iconfont icon-daima"></i></a>
                          </div>

                          <input type="hidden" id="comment_replyId" name="comment_replyId">
                          <input type="hidden" id="comment_userId" name="comment_userId" value="">
                          <input type="hidden" id="commentId" name="commentId" value="">
                          <input type="submit" class="btn btn-redborder" value="发表评论">
                          <span id="tip_comment" class="tip">
                          <div style="display: none;" class="csdn-tracking-statistics tracking-click" data-mod="popu_384"><a href="#" target="_blank" class="comment_area_btn">发表评论</a></div>

                          <div id="lang_list" code="code">
                              <a href="#html" style="width:95px;" class="long_name" target="_self">HTML/XML</a>
                              <a href="#objc" style="width:95px;" class="long_name" target="_self">objective-c</a>
                              <a href="#delphi" style="width:58px;" class="zhong_name" target="_self">Delphi</a>
                              <a href="#ruby" class="zhong_name" target="_self">Ruby</a>
                              <a href="#php" target="_self">PHP</a>
                              <a href="#csharp" class="duan_name" target="_self">C#</a>
                              <a style=" border-right: none;" href="#cpp" class="duan_name" target="_self">C++</a>
                              <a style=" border-bottom:none;width:95px;" href="#javascript" class="long_name" target="_self">JavaScript</a>
                              <a style=" border-bottom:none;width:95px;" href="#vb" class="long_name" target="_self">Visual Basic</a>
                              <a style=" border-bottom:none;" href="#python" class="zhong_name" target="_self">Python</a>
                              <a style=" border-bottom:none;" href="#java" class="zhong_name" target="_self">Java</a>
                              <a style="border-bottom:none;" href="#css" class="duan_name" target="_self">CSS</a>
                              <a style="border-bottom:none;" href="#sql" class="duan_name" target="_self">SQL</a>
                              <a style="border:none; " href="#plain" class="duan_name" target="_self">其它</a>
                              <span class="arrb"></span>
                          </div>
                      </span></div>
                  </form>
              </div>
                          </div>
      </div>
  </div>
  <div class="comment_li_outbox"></div>

  <div class="more_comment" style="display: none;">
      <div id="comment_bar" class="trackgin-ad" data-mod="popu_385"></div>
  </div>

  <!-- <h3 class="recommend_tit" id="related">相关文章推荐</h3> -->
  <div class="recommend_list clearfix" id="rasss">
                                      <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <a href="http://blog.csdn.net/educast/article/details/17970117" target="_blank" strategy="BlogCommendFromBaidu_0">
                <dd>
                    <h2 style="margin-bottom: 0px;">FreeSWITCH代码分析</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/C/8/E/3_educast.jpg" alt="educast" title="educast"></li>
                        <li class="user_name">educast</li>
                        <li class="time">2014年01月07日 21:40</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>9363</span></li>
                    </ul><div class="summary">
                        什么是FreeSWITCH

FreeSWITCH 是一个可扩展的开源跨平台的电话平台,支持音频、视频、文本或任何其他形式的媒体使用的协议的路由与交互。它于2006年成立。FreeSWITCH也提…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/L_yangliu/article/details/46457203" target="_blank" strategy="BlogCommendFromBaidu_1">
                <dd>
                    <h2 style="margin-bottom: 0px;">freeswitch源码研究</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/5/6/5/3_l_yangliu.jpg" alt="L_yangliu" title="L_yangliu"></li>
                        <li class="user_name">L_yangliu</li>
                        <li class="time">2015年06月11日 14:24</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>1769</span></li>
                    </ul><div class="summary">
                        熟悉的过程:

switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, “Activate Eventing Engine.\n”);
将日志输…

                </dd>
            </a>
        </dl>
                                      <dl class="">
        <script>
        (function() {
          var s = "_" + Math.random().toString(36).slice(2);
          document.write('<div id="' + s + '"></div>');
          (window.slotbydup=window.slotbydup || []).push({
            id: '4765209',
            container: s,
            size: '808,120',
            display: 'inlay-fix'
          });
        })();
        </script><div id="_f1arky7oz3fx8s2rm9m5cdi"></div><script charset="utf-8" src="http://pos.baidu.com/ncfm?di=4765209&amp;dri=0&amp;dis=0&amp;dai=0&amp;ps=9982x243&amp;enu=encoding&amp;dcb=___adblockplus&amp;dtm=SSP_JSONP&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1521083181316&amp;ti=FreeSWITCH%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B%E4%B8%BB%E5%87%BD%E6%95%B0main()%20-%20CSDN%E5%8D%9A%E5%AE%A2&amp;ari=2&amp;dbv=2&amp;drs=1&amp;pcs=1522x709&amp;pss=1522x10016&amp;cfv=0&amp;cpl=31&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1521083181&amp;rw=709&amp;ltu=http%3A%2F%2Fblog.csdn.net%2Fy_xianjun%2Farticle%2Fdetails%2F77451174&amp;ltr=http%3A%2F%2Fblog.csdn.net%2Fl_yangliu%2Farticle%2Fdetails%2F46457203&amp;ecd=1&amp;uc=1920x1040&amp;pis=-1x-1&amp;sr=1920x1080&amp;tcn=1521083181"></script><iframe scrolling="no" style="width: 100%; height: 113px; border: 0px;"></iframe>
      </dl>
                                    <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/Neohan/article/details/48288491" target="_blank" strategy="BlogCommendFromBaidu_2">
                <dd>
                    <h2>FreeSWITCH - mod_xml_rpc源码分析七server.c</h2>
                    <div class="summary">
                        xcx                        </div>

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/E/9/4/3_neohan.jpg" alt="Neohan" title="Neohan"></li>
                        <li class="user_name">Neohan</li>
                        <li class="time">2015年10月07日 10:15</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>737</span></li>
                    </ul>
                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/luozirong/article/details/78881825" target="_blank" strategy="BlogCommendFromBaidu_3">
                <dd>
                    <h2>freeswitch mrcp 源码分析--event事件产生</h2>
                    <div class="summary">
                        event事件的构建主要在speech_thread()函数里面。static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thre...                        </div>

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/7/C/5/3_luozirong.jpg" alt="luozirong" title="luozirong"></li>
                        <li class="user_name">luozirong</li>
                        <li class="time">2017年12月23日 19:52</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>235</span></li>
                    </ul>
                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/luozirong/article/details/78876787" target="_blank" strategy="BlogCommendFromBaidu_4">
                <dd>
                    <h2>freeswitch mrcp 源码分析--数据接收(下)</h2>
                    <div class="summary">
                        在前两篇我们介绍了mrcp接收后的处理,最后会调用apr_queue_push扔到消息队列里面。 

对应的,在apt_consumer_task.apt_consumer_task_run()中会循环…

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/7/C/5/3_luozirong.jpg" alt="luozirong" title="luozirong"></li>
                        <li class="user_name">luozirong</li>
                        <li class="time">2017年12月22日 21:03</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>247</span></li>
                    </ul>
                </dd>
            </a>
        </dl><dl id="yd_a_d_feed_5" class="yd_a_d_feed_cla" style="height:124px;overflow: hidden;"><iframe scrolling="no" style="width: 100%; height: 90px; border: 0px;"></iframe></dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/y_xianjun/article/details/47107393" target="_blank" strategy="BlogCommendFromBaidu_5">
                <dd>
                    <h2>软交换FreeSWITCH系统概要和源代码分析预备知识</h2>
                    <div class="summary">
                        asterisk与freeswitch的比较:

1:Asterisk是针对1百人以下的小型系统,相同的硬件配置下单系统最多并发200路,而根据国外爱好者测试freeswitch可达到2000-300…

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/B/5/1/3_y_xianjun.jpg" alt="y_xianjun" title="y_xianjun"></li>
                        <li class="user_name">y_xianjun</li>
                        <li class="time">2015年07月28日 16:35</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>799</span></li>
                    </ul>
                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/turbocc/article/details/78900178" target="_blank" strategy="BlogCommendFromBaidu_6">
                <dd>
                    <h2 style="margin-bottom: 0px;">freeswitch代码分析笔记</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/F/1/4/3_turbocc.jpg" alt="turbocc" title="turbocc"></li>
                        <li class="user_name">turbocc</li>
                        <li class="time">2017年12月26日 11:10</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>117</span></li>
                    </ul><div class="summary">
                        一、main分析

1.调用switch_core_init_and_modload加载模块
->建立内存池switch_core_new_memory_pool(&loadable_modules…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/zoutian007/article/details/7772020" target="_blank" strategy="BlogCommendFromBaidu_7">
                <dd>
                    <h2 style="margin-bottom: 0px;">如何看懂源代码–(分析源代码方法)</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/E/3/4/3_zoutian007.jpg" alt="zoutian007" title="zoutian007"></li>
                        <li class="user_name">zoutian007</li>
                        <li class="time">2012年07月22日 10:53</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>2193</span></li>
                    </ul><div class="summary">
                        我们在写程式时,有不少时间都是在看别人的代码。例如看小组的代码,看小组整合的守则,若一开始没规划怎么看,

就会“噜看噜苦(台语) ”

不管是参考也好,从开源抓下来研究也好,为了了解箇中含意,在…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/educast/article/details/17969985" target="_blank" strategy="BlogCommendFromBaidu_8">
                <dd>
                    <h2>软交换freeswitch系统概要和源代码分析初步</h2>
                    <div class="summary">
                        asterisk与freeswitch的比较:

1:Asterisk是针对1百人以下的小型系统,相同的硬件配置下单系统最多并发200路,而根据国外爱好者测试freeswitch可达到2000-300…

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/C/8/E/3_educast.jpg" alt="educast" title="educast"></li>
                        <li class="user_name">educast</li>
                        <li class="time">2014年01月07日 21:34</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>3675</span></li>
                    </ul>
                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics downloadElement" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a class="clearfix" href="https://download.csdn.net/download/luolaigen2008/4067404" target="_blank" strategy="BlogCommendFromBaidu_9">
                <dd class="floatL">
                    <div class="summary">
                        <h2>Freeswitch软件架构分析</h2>
                        <div class="summary">
                            <ul>
                                <li class="time">2012年02月16日 12:57</li>
                                <li class="visited_num fileSize">840KB</li>
                                <li class="download_btn">下载</li>
                            </ul>
                        </div>
                    </div>
                </dd>
                <dt class="floatR"><img class="maxwidth" src="http://csdnimg.cn/release/download/old_static/images/minetype/doc.svg" alt="" title=""></dt>
            </a>
        </dl>
                                                              <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/luozirong/article/details/78857016" target="_blank" strategy="BlogCommendFromBaidu_10">
                <dd>
                    <h2 style="margin-bottom: 0px;">freeswitch mrcp 源码分析--数据解析</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/7/C/5/3_luozirong.jpg" alt="luozirong" title="luozirong"></li>
                        <li class="user_name">luozirong</li>
                        <li class="time">2017年12月20日 20:12</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>214</span></li>
                    </ul><div class="summary">
                        /** Parse message by raising corresponding event handlers */

APT_DECLARE(apt_message_status_e) apt_m…

                </dd>
            </a>
        </dl><div id="yd_a_d_feed_11" class="yd_a_d_feed_cla" style="height:124px;overflow: hidden;"><div id="BAIDU_SSP__wrapper_u3203594_0"><iframe id="iframeu3203594_0" name="iframeu3203594_0" src="http://pos.baidu.com/ncfm?conwid=920&amp;conhei=117&amp;rdid=3203594&amp;dc=3&amp;di=u3203594&amp;dri=0&amp;dis=0&amp;dai=4&amp;ps=10997x223&amp;enu=encoding&amp;dcb=___adblockplus&amp;dtm=HTML_POST&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1521083181316&amp;ti=FreeSWITCH%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B%E4%B8%BB%E5%87%BD%E6%95%B0main()%20-%20CSDN%E5%8D%9A%E5%AE%A2&amp;ari=2&amp;dbv=2&amp;drs=3&amp;pcs=1522x709&amp;pss=1522x12385&amp;cfv=0&amp;cpl=31&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1521083181&amp;rw=709&amp;ltu=http%3A%2F%2Fblog.csdn.net%2Fy_xianjun%2Farticle%2Fdetails%2F77451174&amp;ltr=http%3A%2F%2Fblog.csdn.net%2Fl_yangliu%2Farticle%2Fdetails%2F46457203&amp;ecd=1&amp;uc=1920x1040&amp;pis=-1x-1&amp;sr=1920x1080&amp;tcn=1521083182&amp;qn=a9ce559d29ffdbaa&amp;tt=1521083181148.842.842.843" width="920" height="117" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" style="border:0;vertical-align:bottom;margin:0;width:920px;height:117px" allowtransparency="true"></iframe></div><script type="text/javascript">var cpro_id = "u3203594";</script><script type="text/javascript" src="//cpro.baidustatic.com/cpro/ui/c.js"></script></div>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/wh8_2011/article/details/53064977" target="_blank" strategy="BlogCommendFromBaidu_11">
                <dd>
                    <h2 style="margin-bottom: 0px;">linux内核奇遇记之md源代码解读之一</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/D/4/6/3_wh8_2011.jpg" alt="wh8_2011" title="wh8_2011"></li>
                        <li class="user_name">wh8_2011</li>
                        <li class="time">2016年11月07日 11:49</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>313</span></li>
                    </ul><div class="summary">
                        linux内核奇遇记之md源代码解读之一

转载请注明出处:http://blog.csdn.net/liumangxiong
最近花了一段时间认真地学习了一下md代码,并且在原代码的基础上开发…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/y_xianjun/article/details/47107551" target="_blank" strategy="BlogCommendFromBaidu_12">
                <dd>
                    <h2 style="margin-bottom: 0px;">FreeSWITCH代码分析</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/B/5/1/3_y_xianjun.jpg" alt="y_xianjun" title="y_xianjun"></li>
                        <li class="user_name">y_xianjun</li>
                        <li class="time">2015年07月28日 16:41</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>1656</span></li>
                    </ul><div class="summary">
                        什么是FreeSWITCH

FreeSWITCH 是一个可扩展的开源跨平台的电话平台,支持音频、视频、文本或任何其他形式的媒体使用的协议的路由与交互。它于2006年成立。FreeSWITCH也提…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics downloadElement" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a class="clearfix" href="https://download.csdn.net/download/qgjrbnz/9869694" target="_blank" strategy="BlogCommendFromBaidu_13">
                <dd class="floatL">
                    <div class="summary">
                        <h2>开源软交换系统freeSwitch sip模块的源码初步分析</h2>
                        <div class="summary">
                            <ul>
                                <li class="time">2017年06月13日 21:04</li>
                                <li class="visited_num fileSize">253KB</li>
                                <li class="download_btn">下载</li>
                            </ul>
                        </div>
                    </div>
                </dd>
                <dt class="floatR"><img class="maxwidth" src="http://csdnimg.cn/release/download/old_static/images/minetype/pdf.svg" alt="" title=""></dt>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics downloadElement" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a class="clearfix" href="https://download.csdn.net/download/hxdhxd_hxd/6850459" target="_blank" strategy="searchFromBaidu_14">
                <dd class="floatL">
                    <div class="summary">
                        <h2>freeswitch源代码</h2>
                        <div class="summary">
                            <ul>
                                <li class="time">2014年01月15日 10:31</li>
                                <li class="visited_num fileSize">36.13MB</li>
                                <li class="download_btn">下载</li>
                            </ul>
                        </div>
                    </div>
                </dd>
                <dt class="floatR"><img class="maxwidth" src="http://csdnimg.cn/release/download/old_static/images/minetype/unkonw.svg" alt="" title=""></dt>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/y_xianjun/article/details/77451174" target="_blank" strategy="searchFromBaidu_15">
                <dd>
                    <h2 style="margin-bottom: 0px;">FreeSWITCH源码分析之主函数main()</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/B/5/1/3_y_xianjun.jpg" alt="y_xianjun" title="y_xianjun"></li>
                        <li class="user_name">y_xianjun</li>
                        <li class="time">2017年08月21日 16:19</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>234</span></li>
                    </ul><div class="summary">
                        Freeswitch的主函数是在文件switch.c中定义的,该文件的260行是整个程序的入口,主函数主要完成的功能是包括,命令行解析,初始化apr库,构建全局内存池,模块加载和初始化核心组件。

 …

                </dd>
            </a>
        </dl><dl id="yd_a_d_feed_17" class="yd_a_d_feed_cla" style="height:124px;overflow: hidden;"><iframe scrolling="no" style="width: 100%; height: 90px; border: 0px;"></iframe></dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/educast/article/details/17921619" target="_blank" strategy="BlogCommendFromQuerySearch_16">
                <dd>
                    <h2 style="margin-bottom: 0px;">运行 FreeSWITCH</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/C/8/E/3_educast.jpg" alt="educast" title="educast"></li>
                        <li class="user_name">educast</li>
                        <li class="time">2014年01月06日 16:43</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>2652</span></li>
                    </ul><div class="summary">
                        读到本章,你应该对 FreeSWITCH 有了一个比较全面的了解,迫切地想实验它强大的功能了。让我们从最初的运行开始,一步一步进入 FreeSWITCH 的神秘世界。

命令行参数

一般来说…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/y_xianjun/article/details/73480840" target="_blank" strategy="BlogCommendFromQuerySearch_17">
                <dd>
                    <h2 style="margin-bottom: 0px;">FreeSWITCH源码分析之mod_xml_curl</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/B/5/1/3_y_xianjun.jpg" alt="y_xianjun" title="y_xianjun"></li>
                        <li class="user_name">y_xianjun</li>
                        <li class="time">2017年06月20日 20:24</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>583</span></li>
                    </ul><div class="summary">
                        近期又开始了我的FreeSWITCH研究之路, 因为项目中需要, &nbsp;使用sip_profile中的internal端点来处理sipUA的注册及在线保持做被叫, 打开了登录及呼叫认证的开关, 我们都知道...                        </div>


                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/u012377333/article/details/44346807" target="_blank" strategy="searchFromBaidu_18">
                <dd>
                    <h2 style="margin-bottom: 0px;">FreeSWITCH代码分析</h2>
                    <ul class="floatR">
                        <li class="avatar_img"><img src="//avatar.csdn.net/4/2/4/3_u012377333.jpg" alt="u012377333" title="u012377333"></li>
                        <li class="user_name">u012377333</li>
                        <li class="time">2015年03月17日 19:53</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>1268</span></li>
                    </ul><div class="summary">
                        转载:http://blog.csdn.net/educast/article/details/17970117

什么是FreeSWITCH

FreeSWITCH 是一个可扩展的开源跨平台…

                </dd>
            </a>
        </dl>
                                                <dl class="clearfix csdn-tracking-statistics recommend_article recommend_article_out" data-mod="popu_387" data-poputype="feed" data-feed-show="false" data-dsm="post">
            <a href="http://blog.csdn.net/huoyin/article/details/39327849" target="_blank" strategy="searchFromBaidu_19">
                <dd>
                    <h2>软交换freeswitch系统概要和源代码分析初步</h2>
                    <div class="summary">
                        asterisk与freeswitch的比较:

1:Asterisk是针对1百人以下的小型系统,相同的硬件配置下单系统最多并发200路,而根据国外爱好者测试freeswitch可达到2000-300…

                    <ul>
                        <li class="avatar_img"><img src="//avatar.csdn.net/A/A/5/3_huoyin.jpg" alt="huoyin" title="huoyin"></li>
                        <li class="user_name">huoyin</li>
                        <li class="time">2014年09月17日 00:24</li>
                        <li class="visited_num"><i class="icon iconfont icon-read"></i><span>1199</span></li>
                    </ul>
                </dd>
            </a>
        </dl>
                    </div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值