1. res_config_mysql的模块加载早于chan_sip,他们的加载函数均为load_module
先分析res_config_mysql的load_module函数
parse_config(0);
parse_config解析res_config_mysql文件,并用文件中的配置信息填充mysql_conn结构体
我当前的res_config_mysql文件如下
[general]
dbhost = 192.168.1.182
dbname = asterisk
dbuser = root
dbpass = 123456
dbport = 3306
解析完成后,mysql_conn里面会得到这些数据struct mysql_conn {
AST_RWLIST_ENTRY(mysql_conn) list;
ast_mutex_t lock;
MYSQL handle;
char host[50]; 192.168.1.182
char name[50]; asterisk
char user[50]; root
char pass[50]; 123456
char sock[50];
char charset[50];
int port; 3306
int connected;
time_t connect_time;
enum requirements requirements;
char unique_name[0];
};
ast_config_engine_register(&mysql_engine);
将res_config_mysql这个模块的函数结构体注册到
static struct ast_config_engine *config_engine_list;
实际res_config_mysql的load_module函数完成两个事情,解析res_config_mysql.conf配置文件,并存储。
然后向系统注册res_config_mysql的功能函数
2. chan_sip模块的加载
chan_sip模块的加载也是load_module函数,在这个函数中我们主要关注reload_config函数
在reload_config函数中调用
cfg = ast_config_load(config, config_flags); config为sip.conf
但是这里ast_config_load并不是直接加载sip.conf文件来生成一个ast_config结构体的。
我们将其展开来分析,ast_config_load最终是调用了ast_config_internal_load
3. ast_config_internal_load分析
if (!ast_test_flag(&flags, CONFIG_FLAG_NOREALTIME) && config_engine_list) {
flags是0,并且res_config_mysql模块将其函数注册到了config_engine_list中,因此if语句为真
struct ast_config_engine *eng;
从下面find_engine的分析,eng将得到res_config_mysql的ast_config_engine结构体
eng = find_engine(filename, 1, db, sizeof(db), table, sizeof(table));
if (eng && eng->load_func) {
loader = eng;
} else {
eng = find_engine("global", 1, db, sizeof(db), table, sizeof(table));
if (eng && eng->load_func)
loader = eng;
}
}
最后调用了res_config_mysql的oad_func函数,即config_mysql函数
result = loader->load_func(db, table, filename, cfg, flags, suggested_include_file, who_asked);
4. find_engine分析
find_engine展开解释,在extconfig.conf被解析后,config_maps里面如下
name = extensions dirver =mysql database =general table =extensions
name = sip.conf dirver =mysql database =general table =sip_config2
for (map = config_maps; map; map = map->next) {
family为"sip.conf",因此,for结束后,database = general, table = sip_config2
if (!strcasecmp(family, map->name) && (priority == map->priority)) {
if (database)
ast_copy_string(database, map->database, dbsiz);
if (table)
ast_copy_string(table, map->table ? map->table : family, tabsiz);
break;
}
}
/* Check if the required driver (engine) exist */
if (map) {
从res_config_mysql看他的ast_config_engine的定义里面,其name为mysql,从上面看map的driver也是mysql,
因此 find_engine这个函数最后返回了res_config_mysql这个ast_config_engine
for (eng = config_engine_list; !ret && eng; eng = eng->next) {
if (!strcasecmp(eng->name, map->driver))
ret = eng;
}
}