asterisk内核框架.docx

上传人:b****6 文档编号:4279312 上传时间:2022-11-28 格式:DOCX 页数:23 大小:26.19KB
下载 相关 举报
asterisk内核框架.docx_第1页
第1页 / 共23页
asterisk内核框架.docx_第2页
第2页 / 共23页
asterisk内核框架.docx_第3页
第3页 / 共23页
asterisk内核框架.docx_第4页
第4页 / 共23页
asterisk内核框架.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

asterisk内核框架.docx

《asterisk内核框架.docx》由会员分享,可在线阅读,更多相关《asterisk内核框架.docx(23页珍藏版)》请在冰豆网上搜索。

asterisk内核框架.docx

asterisk内核框架

Asterisk内核框架

Asterisk是一个开源的pbx系统,在公开的资料中,很难找到asterisk内核系统的详细描述。

因此,很有必要写一篇内核框架的描述文档,作为内部培训文档,相互学习提高。

本文主要从三个层面来描述asterisk内核,即asterisk内核模块、内核启动过程、基本呼叫流程。

一、            asterisk内核模块

Asterisk由内部核心和外围动态可加载模块组成。

内部核心由以下六个部分组成:

PBX交换核心模块(PBXSwitchingCore)、调度和I/O管理模块(SchedulerandI/OManager)、应用调用模块(ApplicationLauncher)、编解码转换模块(CodecTranslator)、动态模块加载器模块(DynamicModuleLoader)和CDR生成模块(CDRCore)。

外围动态可加载模块包括以App_开始的Applications、以Func_开始的Functions、以Res_开始的Resources、以Chan_开始的channels、以Codec_开始的codec编解码模块等。

1.        内核模块

1)       PBX交换核心模块(PBXSwitchingCore):

l        pbx.c

pbx.c是asterisk的核心模块,每路呼叫都需要经过它调度。

pbx实现了builtinapplications,也就是内置的应用,比如最常见的Answer,Hangup,Background,Wait等等。

structast_app是一个关键数据结构,它定义了注册builtinapplications的结构。

load_pbx函数用来注册builtinapplications和一些命令行CLI命令(每个模块都有些CLI命令)。

该函数在系统启动时被调用。

pbx_exec是Answer/BackGround/Busy/Goto/GotoIf/Hangup/Set等builtinapplications的执行入口函数,它被pbx_extension_helper调用。

ast_pbx_start函数是每路呼叫的起点。

2)       调度和I/O管理模块(SchedulerandI/OManager):

l        Channel.c:

Channel.c/channel.h定义了channel操作的结构体和接口函数。

structast_channel_tech结构体是所有channel都要用到的关键结构体,它定义channel操作的一系列回调函数指针,如call、hangup、answer等。

每个channel模块都会定义ast_channel_tech的实体,并将各自的回调函数赋值给它。

例如chan_sip.c中定义如下:

/*!

\briefDefinitionofthischannelforPBXchannelregistration*/

staticconststructast_channel_techsip_tech={

      .type="SIP",

      .description="SessionInitiationProtocol(SIP)",

      .capabilities=((AST_FORMAT_MAX_AUDIO<<1)-1),

      .properties=AST_CHAN_TP_WANTSJITTER|AST_CHAN_TP_CREATESJITTER,

      .requester=sip_request_call,

      .devicestate=sip_devicestate,

      .call=sip_call,

      .hangup=sip_hangup,

      .answer=sip_answer,

      .read=sip_read,

      .write=sip_write,

      .write_video=sip_write,

      .indicate=sip_indicate,

      .transfer=sip_transfer,

      .fixup=sip_fixup,

      .send_digit_begin=sip_senddigit_begin,

      .send_digit_end=sip_senddigit_end,

      .bridge=ast_rtp_bridge,

      .send_text=sip_sendtext,

      .func_channel_read=acf_channel_read,

};

ast_call、ast_hangup、ast_answer等函数分别实现ast_channel_tech中的call、hangup、answer等回调函数的调用。

structast_channel结构体定义了channel的上下文参数,它是每个参与呼叫的channel必不可少的,都会调用ast_channel_alloc来申请ast_channel。

l        io.c

io.c实现了asterisk跟外部交互时的I/O管理,如chan_sip为了从外部接收SIP信令,调用ast_io_add添加IO接口,并调用ast_io_wait实现外部消息接收。

3)       应用调用模块(ApplicationLauncher):

在pbx.c中定义了一系列的应用调用接口。

applications模块定义了application回调函数并注册后,在pbx.c中通过应用调用接口回调执行。

应用调用接口的关键函数是pbx_extension_helper,它执行dialplan,在cli上打印“Executing……”,并抛出amievent事件,同时调用pbx_exec执行application回调函数。

4)       编解码转换模块(CodecTranslator):

Translate.c:

structast_translator:

编码转换描述结构体,它定义了编码转换的名称、回调函数、运行时选项。

structast_trans_pvt:

编码转换上下文描述结构体。

ast_register_translator:

编码转换注册接口函数,供各编码模块调用,注册structast_translator类型的结构体变量。

ast_unregister_translator:

编码转换注销函数

ast_translate:

编码转换的执行函数。

codec_gsm.c/codec_...:

对应各种编码的编解码执行模块,如g.711alaw/g.711ulaw/gsm等。

5)       动态模块加载器模块(DynamicModuleLoader):

该模块主要是Module.h。

Module.h中定义了structast_module_info结构,用来保存各模块的注册、注销回调函数,以及模块描述信息。

load_module、unload_module,每个应用模块的注册、注销函数,由各个模块自行定义为static函数。

AST_MODULE_INFO_STANDARD:

注册接口、注销接口、模块描述信息等模块信息的登记接口。

它是一个宏定义,动态模块调用它时,首先定义类型为ast_module_info的__mod_info静态结构变量,保存模块信息,并定义__attribute__((constructor))__reg_module和__attribute__((destructor))__unreg_module,在程序启动和退出时调用。

6)       CDR生成模块(CDRCore):

Cdr.c:

ast_cdr_register:

cdrdriver注册,供cdr_mysql等调用,注册话单保存的回调函数。

ast_cdr_engine_init:

CDR模块初始化,注册cdrstatus、加载cdr.conf、启动CDR线程。

ast_cdr_detach:

产生话单的接口函数,呼叫结束时被调用。

2.        外围可加载模块:

1)       Applications

以app_开始的模块,如app_dial.c、app_db.c、app_queue.c、app_record.c、app_meetme.c等,代码保存在apps目录中。

每个application模块都定义了load_module函数和unload_module函数,分别用来注册和注销application。

load_module函数调用ast_register_application函数,注册application命令,例如app_dial模块注册Dial:

res=ast_register_application(app,dial_exec,synopsis,descrip)。

unload_module函数调用ast_unregister_application函数,注销application命令。

每个application模块都会使用AST_MODULE_INFO_STANDARD宏来登记模块信息__mod_info。

AST_MODULE_INFO_STANDARD将load_module和unload_module注册为回调函数,供moduleload/unload/reload调用。

2)       Channel

以chan_开始的模块,如chan_sip.c、chan_h323.c、chan_mgcp.c、chan_iax2.c、chan_zap.c等,对应代码保存在channels目录中。

channel注册、注销过程和application基本类似。

由于每个channel需要和外部交互,都会在load_module中启用do_monitor线程来侦听外部tcp/udp端口,接收外部消息。

每个channel也定义了各自的cli命令和Function命令,例如chan_sip定义了sipdebug/history/no/notify/prune/reload/set/show等cli命令和SIP_HEADER、CHECKSIPDOMAIN、SIPPEER、SIPCHANINFO等Function命令。

3)       Functions

以Fun_开始的模块,例如Fun_db.c、func_moh.c、func_cdr.c等,对应代码保存在funcs目录中。

Function注册、注销过程也和application类似。

每个Function模块也定义了各自的Function命令,例如Fun_db.c就定义了DB、DB_EXISTS、DB_DELETE等Function命令。

二、            asterisk启动过程

主要就main函数讲解asterisk的启动过程:

intmain(intargc,char*argv[])

{

      intc;

      charfilename[80]="";

      charhostname[MAXHOSTNAMELEN]="";

      chartmp[80];

      char*xarg=NULL;

      intx;

      FILE*f;

      sigset_tsigs;

      intnum;

      intisroot=1;

      char*buf;

      char*runuser=NULL,*rungroup=NULL;

/*保存命令行参数(argv[]->_argv[]),以便程序重启时使用*/

      /*Rememberoriginalargsforrestart*/

      if(argc>sizeof(_argv)/sizeof(_argv[0])-1){

             fprintf(stderr,"Truncatingargumentsizeto%d\n",(int)(sizeof(_argv)/sizeof(_argv[0]))-1);

             argc=sizeof(_argv)/sizeof(_argv[0])-1;

      }

      for(x=0;x

             _argv[x]=argv[x];

      _argv[x]=NULL;

      if(geteuid()!

=0)

             isroot=0;

/*命令如果是rasterisk,设置AST_OPT_FLAG_NO_FORK和AST_OPT_FLAG_REMOTE标志位*/

      /*iftheprognameisrasteriskconsideritaremoteconsole*/

      if(argv[0]&&(strstr(argv[0],"rasterisk"))!

=NULL){

             ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK|AST_OPT_FLAG_REMOTE);

      }

/*得到当前主机名,在启动时打印出来*/

      if(gethostname(hostname,sizeof(hostname)-1))

             ast_copy_string(hostname,"",sizeof(hostname));

/*获取当前的进程标识*/

      ast_mainpid=getpid();

/*建立mu-law和a-law转换表*/

      ast_ulaw_init();

      ast_alaw_init();

/*为FFT逆变换(傅立叶逆变换)做一些初始化,用于在zaptel里进行callerid的DTMF检测*/

      callerid_init();

/*初始化内置命令的_full_cmd字符串,并注册常用命令,ast_builtins_init()->ast_cli_register_multiple()->ast_cli_register()->__ast_cli_register()*/

      ast_builtins_init();

/*初始化base64转换*/

      ast_utils_init();

/*tty/tdd初始化*/

      tdd_init();

/*设置用户历史命令的保存路径*/

      if(getenv("HOME"))

             snprintf(filename,sizeof(filename),"%s/.asterisk_history",getenv("HOME"));

      /*Checkforoptions*/

/*检查命令行的输入参数,匹配参数范围是“mtThfFdvVqprRgciInx:

U:

G:

C:

L:

M:

”,不同的参数输入走到不同的case分支处理。

有几个v,verbose级别就增加几*/

      while((c=getopt(argc,argv,"mtThfFdvVqprRgciInx:

U:

G:

C:

L:

M:

"))!

=-1){

             switch(c){

#ifHAVE_WORKING_FORK

             case'F':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_ALWAYS_FORK);

                    break;

             case'f':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK);

                    break;

#endif

             case'd':

                    option_debug++;

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK);

                    break;

             case'c':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK|AST_OPT_FLAG_CONSOLE);

                    break;

             case'n':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_COLOR);

                    break;

             case'r':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK|AST_OPT_FLAG_REMOTE);

                    break;

             case'R':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK|AST_OPT_FLAG_REMOTE|AST_OPT_FLAG_RECONNECT);

                    break;

             case'p':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_HIGH_PRIORITY);

                    break;

             case'v':

                    option_verbose++;

                    ast_set_flag(&ast_options,AST_OPT_FLAG_NO_FORK);

                    break;

             case'm':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_MUTE);

                    break;

             case'M':

                    if((sscanf(optarg,"%d",&option_maxcalls)!

=1)||(option_maxcalls<0))

                           option_maxcalls=0;

                    break;

             case'L':

                    if((sscanf(optarg,"%lf",&option_maxload)!

=1)||(option_maxload<0.0))

                           option_maxload=0.0;

                    break;

             case'q':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_QUIET);

                    break;

             case't':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_CACHE_RECORD_FILES);

                    break;

             case'T':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_TIMESTAMP);

                    break;

             case'x':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_EXEC);

                    xarg=ast_strdupa(optarg);

                    break;

             case'C':

                    ast_copy_string(ast_config_AST_CONFIG_FILE,optarg,sizeof(ast_config_AST_CONFIG_FILE));

                    ast_set_flag(&ast_options,AST_OPT_FLAG_OVERRIDE_CONFIG);

                    break;

             case'I':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_INTERNAL_TIMING);

                    break;

             case'i':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_INIT_KEYS);

                    break;

             case'g':

                    ast_set_flag(&ast_options,AST_OPT_FLAG_DUMP_CORE);

                    break;

        

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1