Asterisk内核框架(2)--启动过程
2012-12-03 10:47
344 查看
asterisk启动过程
主要就main函数讲解asterisk的启动过程:
int main(int argc, char *argv[])
{
int c;
char filename[80] = "";
char hostname[MAXHOSTNAMELEN] = "";
char tmp[80];
char * xarg = NULL;
int x;
FILE *f;
sigset_t sigs;
int num;
int isroot = 1;
char *buf;
char *runuser = NULL, *rungroup = NULL;
/*保存命令行参数(argv[]->_argv[]),以便程序重启时使用*/
/* Remember original args for restart */
if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
}
for (x=0; x<argc; x++)
_argv[x] = argv[x];
_argv[x] = NULL;
if (geteuid() != 0)
isroot = 0;
/*命令如果是rasterisk,设置AST_OPT_FLAG_NO_FORK和AST_OPT_FLAG_REMOTE标志位*/
/* if the progname is rasterisk consider it a remote console */
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, "<Unknown>", 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"));
/* Check for options */
/*检查命令行的输入参数,匹配参数范围是“mtThfFdvVqprRgciInx:U:G:C:L:M:”,不同的参数输入走到不同的case分支处理。有几个v,verbose级别就增加几*/
while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:")) != -1) {
switch (c) {
#if HAVE_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;
case 'h':
show_cli_help();
exit(0);
case 'V':
show_version();
exit(0);
case 'U':
runuser = ast_strdupa(optarg);
break;
case 'G':
rungroup = ast_strdupa(optarg);
break;
case '?':
exit(1);
}
}
/*如果用了-c或者-v或者-r并且没有-x cmd参数,则打印欢迎信息*/
if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
ast_register_verbose(console_verboser);
WELCOME_MESSAGE;
}
/*如果没有开调试则简单打印Booting... */
if (ast_opt_console && !option_verbose)
ast_verbose("[ Booting...\n");
/*显示控制台时,不论是本地还是远程,都不能使用-F参数,否则无效*/
if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
}
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts (which need to know if/when
* the main asterisk process has died yet). */
if (ast_opt_remote) {
strcpy(argv[0], "rasterisk");
for (x = 1; x < argc; x++) {
argv[x] = argv[0] + 10;
}
}
/*读取主配置文件,主配置文件是由make menuselect配置的*/
if (ast_opt_console && !option_verbose)
ast_verbose("[ Reading Master Configuration ]\n");
ast_readconfig();
/*如果启动加了-g,取消core dump文件的大小限制*/
if (ast_opt_dump_core) {
struct rlimit l;
memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &l)) {
ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
}
}
/*修改用户和组权限*/
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP;
if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
runuser = ast_config_AST_RUN_USER;
#ifndef __CYGWIN__
if (isroot)
ast_set_priority(ast_opt_high_priority);
if (isroot && rungroup) {
struct group *gr;
gr = getgrnam(rungroup);
if (!gr) {
ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
exit(1);
}
if (setgid(gr->gr_gid)) {
ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
exit(1);
}
if (setgroups(0, NULL)) {
ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
exit(1);
}
if (option_verbose)
ast_verbose("Running as group '%s'\n", rungroup);
}
if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
#ifdef HAVE_CAP
int has_cap = 1;
#endif /* HAVE_CAP */
struct passwd *pw;
pw = getpwnam(runuser);
if (!pw) {
ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
exit(1);
}
#ifdef HAVE_CAP
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
has_cap = 0;
}
#endif /* HAVE_CAP */
if (!isroot && pw->pw_uid != geteuid()) {
ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
exit(1);
}
if (!rungroup) {
if (setgid(pw->pw_gid)) {
ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
exit(1);
}
if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
exit(1);
}
}
if (setuid(pw->pw_uid)) {
ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
exit(1);
}
if (option_verbose)
ast_verbose("Running as user '%s'\n", runuser);
#ifdef HAVE_CAP
if (has_cap) {
cap_t cap;
cap = cap_from_text("cap_net_admin=ep");
if (cap_set_proc(cap))
ast_log(LOG_WARNING, "Unable to install capabilities.\n");
if (cap_free(cap))
ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
}
#endif /* HAVE_CAP */
}
#endif /* __CYGWIN__ */
#ifdef linux
if (geteuid() && ast_opt_dump_core) {
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
}
}
#endif
主要就main函数讲解asterisk的启动过程:
int main(int argc, char *argv[])
{
int c;
char filename[80] = "";
char hostname[MAXHOSTNAMELEN] = "";
char tmp[80];
char * xarg = NULL;
int x;
FILE *f;
sigset_t sigs;
int num;
int isroot = 1;
char *buf;
char *runuser = NULL, *rungroup = NULL;
/*保存命令行参数(argv[]->_argv[]),以便程序重启时使用*/
/* Remember original args for restart */
if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
}
for (x=0; x<argc; x++)
_argv[x] = argv[x];
_argv[x] = NULL;
if (geteuid() != 0)
isroot = 0;
/*命令如果是rasterisk,设置AST_OPT_FLAG_NO_FORK和AST_OPT_FLAG_REMOTE标志位*/
/* if the progname is rasterisk consider it a remote console */
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, "<Unknown>", 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"));
/* Check for options */
/*检查命令行的输入参数,匹配参数范围是“mtThfFdvVqprRgciInx:U:G:C:L:M:”,不同的参数输入走到不同的case分支处理。有几个v,verbose级别就增加几*/
while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:")) != -1) {
switch (c) {
#if HAVE_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;
case 'h':
show_cli_help();
exit(0);
case 'V':
show_version();
exit(0);
case 'U':
runuser = ast_strdupa(optarg);
break;
case 'G':
rungroup = ast_strdupa(optarg);
break;
case '?':
exit(1);
}
}
/*如果用了-c或者-v或者-r并且没有-x cmd参数,则打印欢迎信息*/
if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
ast_register_verbose(console_verboser);
WELCOME_MESSAGE;
}
/*如果没有开调试则简单打印Booting... */
if (ast_opt_console && !option_verbose)
ast_verbose("[ Booting...\n");
/*显示控制台时,不论是本地还是远程,都不能使用-F参数,否则无效*/
if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
}
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts (which need to know if/when
* the main asterisk process has died yet). */
if (ast_opt_remote) {
strcpy(argv[0], "rasterisk");
for (x = 1; x < argc; x++) {
argv[x] = argv[0] + 10;
}
}
/*读取主配置文件,主配置文件是由make menuselect配置的*/
if (ast_opt_console && !option_verbose)
ast_verbose("[ Reading Master Configuration ]\n");
ast_readconfig();
/*如果启动加了-g,取消core dump文件的大小限制*/
if (ast_opt_dump_core) {
struct rlimit l;
memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &l)) {
ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
}
}
/*修改用户和组权限*/
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP;
if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
runuser = ast_config_AST_RUN_USER;
#ifndef __CYGWIN__
if (isroot)
ast_set_priority(ast_opt_high_priority);
if (isroot && rungroup) {
struct group *gr;
gr = getgrnam(rungroup);
if (!gr) {
ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
exit(1);
}
if (setgid(gr->gr_gid)) {
ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
exit(1);
}
if (setgroups(0, NULL)) {
ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
exit(1);
}
if (option_verbose)
ast_verbose("Running as group '%s'\n", rungroup);
}
if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
#ifdef HAVE_CAP
int has_cap = 1;
#endif /* HAVE_CAP */
struct passwd *pw;
pw = getpwnam(runuser);
if (!pw) {
ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
exit(1);
}
#ifdef HAVE_CAP
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
has_cap = 0;
}
#endif /* HAVE_CAP */
if (!isroot && pw->pw_uid != geteuid()) {
ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
exit(1);
}
if (!rungroup) {
if (setgid(pw->pw_gid)) {
ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
exit(1);
}
if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
exit(1);
}
}
if (setuid(pw->pw_uid)) {
ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
exit(1);
}
if (option_verbose)
ast_verbose("Running as user '%s'\n", runuser);
#ifdef HAVE_CAP
if (has_cap) {
cap_t cap;
cap = cap_from_text("cap_net_admin=ep");
if (cap_set_proc(cap))
ast_log(LOG_WARNING, "Unable to install capabilities.\n");
if (cap_free(cap))
ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
}
#endif /* HAVE_CAP */
}
#endif /* __CYGWIN__ */
#ifdef linux
if (geteuid() && ast_opt_dump_core) {
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
}
}
#endif
相关文章推荐
- 跟踪分析Linux内核的启动过程
- 实验三:跟踪分析Linux内核的启动过程
- 基于Linux2.6.35内核的zImage启动过程研究
- linux内核启动设备探测过程
- U-Boot启动内核的过程
- Linux内核源码分析--内核启动命令行的传递过程(Linux-3.0 ARMv7)
- Linux 内核启动过程分析----zImage自解压
- 跟踪内核启动过程CONFIG_DEBUG_LL【转自】
- Linux内核启动过程分析
- [置顶] Android Multimedia框架总结(十九)Camera2框架C/S模型之CameraService启动及与Client连接过程
- 内核修改Android 启动过程logo修改
- Asterisk内核框架(转帖)
- 内核启动过程
- 跟踪分析Linux内核的启动过程
- 启动redboot后,向目标机烧写一个linux内核的全过程
- Linux内核源码分析--内核启动之zImage自解压过程
- ARM linux解析之压缩内核zImage的启动过程 二
- linux启动流程分析-内核解压缩过程
- 内核启动全过程
- 内核启动过程