apache的启动过程 原代码 分析.doc_第1页
apache的启动过程 原代码 分析.doc_第2页
apache的启动过程 原代码 分析.doc_第3页
apache的启动过程 原代码 分析.doc_第4页
apache的启动过程 原代码 分析.doc_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 /server/log.c 这个里面定义了ap_log_error()。2 /include/httpd.h 这个文件里面申明了基本的内容,如文件路径,字符串长度,等等。3 /server/listen.c对于apache的httpd,有很多的技术,有MPM多任务并发处理(采用记分板),内存池,线程池。1 在main()有一个for(;)里面调用了ap_mpm_run。但这个循环里好象只执行了一次,而不是一直在循环。2 在ap_mpm_run()里,有一个while (!restart_pending & !shutdown_pending)。这个循环每一秒就往返一次,一直执行,直到进程结束。如果是第一次启动,在这个循环里,会调用一个startup_children();在这里面又有一个循环调用make_child()产生初始数量的子进程。3 在上面的while里,perform_idle_server_maintenance(pconf)会每1秒执行一次,如果你kill -9一个子进程,这个函数就起作用,再重新调用make_child()生成一个子进程。4 如果执行httpd k stop,那么ap_mpm_run()会返回错误,在main()就会跳出for(;),进程退出。5 在make_child()里,有一个fork()调用产生子进程,然后在子进程里调用child_main()进行子进程的初始化处理。linux-lncx:/home/apache/httpd-2.2.11/server # ls main.cmain.clinux-lncx:/home/apache/httpd-2.2.11/server #int main(int argc, const char * const argv) char c; int configtestonly = 0; const char *confname = SERVER_CONFIG_FILE; const char *def_server_root = HTTPD_ROOT; const char *temp_error_log = NULL; const char *error; process_rec *process; server_rec *server_conf; apr_pool_t *pglobal; apr_pool_t *pconf; apr_pool_t *plog; /* Pool of log streams, reset _after_ each read of conf */ apr_pool_t *ptemp; /* Pool for temporary config stuff, reset often */ apr_pool_t *pcommands; /* Pool for -D, -C and -c switches */ apr_getopt_t *opt; apr_status_t rv; module *mod; const char *optarg; APR_OPTIONAL_FN_TYPE(ap_signal_server) *signal_server; AP_MONCONTROL(0); /* turn off profiling of startup */ process = init_process(&argc, &argv); pglobal = process-pool; pconf = process-pconf; ap_server_argv0 = process-short_name;#if APR_CHARSET_EBCDIC if (ap_init_ebcdic(pglobal) != APR_SUCCESS) destroy_and_exit_process(process, 1); #endif apr_pool_create(&pcommands, pglobal); apr_pool_tag(pcommands, pcommands); ap_server_pre_read_config = apr_array_make(pcommands, 1, sizeof(char *); ap_server_post_read_config = apr_array_make(pcommands, 1, sizeof(char *); ap_server_config_defines = apr_array_make(pcommands, 1, sizeof(char *); error = ap_setup_prelinked_modules(process); if (error) ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_EMERG, 0, NULL, %s: %s, ap_server_argv0, error); destroy_and_exit_process(process, 1); ap_run_rewrite_args(process); /* Maintain AP_SERVER_BASEARGS list in http_main.h to allow the MPM * to safely pass on our args from its rewrite_args() handler. */ apr_getopt_init(&opt, pcommands, process-argc, process-argv); while (rv = apr_getopt(opt, AP_SERVER_BASEARGS, &c, &optarg) = APR_SUCCESS) char *new; switch (c) case c: new = (char *)apr_array_push(ap_server_post_read_config); *new = apr_pstrdup(pcommands, optarg); break; case C: new = (char *)apr_array_push(ap_server_pre_read_config); *new = apr_pstrdup(pcommands, optarg); break; case d: def_server_root = optarg; break; case D: new = (char *)apr_array_push(ap_server_config_defines); *new = apr_pstrdup(pcommands, optarg); /* Setting -D DUMP_VHOSTS is equivalent to setting -S */ if (strcmp(optarg, DUMP_VHOSTS) = 0) configtestonly = 1; /* Setting -D DUMP_MODULES is equivalent to setting -M */ if (strcmp(optarg, DUMP_MODULES) = 0) configtestonly = 1; break; case e: if (strcasecmp(optarg, emerg) = 0) ap_default_loglevel = APLOG_EMERG; else if (strcasecmp(optarg, alert) = 0) ap_default_loglevel = APLOG_ALERT; else if (strcasecmp(optarg, crit) = 0) ap_default_loglevel = APLOG_CRIT; else if (strncasecmp(optarg, err, 3) = 0) ap_default_loglevel = APLOG_ERR; else if (strncasecmp(optarg, warn, 4) = 0) ap_default_loglevel = APLOG_WARNING; else if (strcasecmp(optarg, notice) = 0) ap_default_loglevel = APLOG_NOTICE; else if (strcasecmp(optarg, info) = 0) ap_default_loglevel = APLOG_INFO; else if (strcasecmp(optarg, debug) = 0) ap_default_loglevel = APLOG_DEBUG; else usage(process); break; case E: temp_error_log = apr_pstrdup(process-pool, optarg); break; case X: new = (char *)apr_array_push(ap_server_config_defines); *new = DEBUG; break; case f: confname = optarg; break; case v: printf(Server version: %sn, ap_get_server_description(); printf(Server built: %sn, ap_get_server_built(); destroy_and_exit_process(process, 0); case V: show_compile_settings(); destroy_and_exit_process(process, 0); case l: ap_show_modules(); destroy_and_exit_process(process, 0); case L: ap_show_directives(); destroy_and_exit_process(process, 0); case t: configtestonly = 1; break; case S: configtestonly = 1; new = (char *)apr_array_push(ap_server_config_defines); *new = DUMP_VHOSTS; break; case M: configtestonly = 1; new = (char *)apr_array_push(ap_server_config_defines); *new = DUMP_MODULES; break; case h: case ?: usage(process); /* bad cmdline option? then we die */ if (rv != APR_EOF | opt-ind argc) usage(process); apr_pool_create(&plog, pglobal); apr_pool_tag(plog, plog); apr_pool_create(&ptemp, pconf); apr_pool_tag(ptemp, ptemp); /* Note that we preflight the config file once * before reading it _again_ in the main loop. * This allows things, log files configuration * for example, to settle down. */ ap_server_root = def_server_root; if (temp_error_log) ap_replace_stderr_log(process-pool, temp_error_log); /*=下面这一段是对配置文件进行处理 =*/ server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); if (!server_conf) destroy_and_exit_process(process, 1); if (ap_run_pre_config(pconf, plog, ptemp) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Pre-configuration failed); destroy_and_exit_process(process, 1); rv = ap_process_config_tree(server_conf, ap_conftree, process-pconf, ptemp); if (rv = OK) ap_fixup_virtual_hosts(pconf, server_conf); ap_fini_vhost_config(pconf, server_conf); apr_hook_sort_all(); if (configtestonly) ap_run_test_config(pconf, server_conf); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, Syntax OK); destroy_and_exit_process(process, 0); /*=上面这一段是对配置文件进行处理=*/ signal_server = APR_RETRIEVE_OPTIONAL_FN(ap_signal_server); if (signal_server) int exit_status; if (signal_server(&exit_status, pconf) != 0) destroy_and_exit_process(process, exit_status); /* If our config failed, deal with that here. */ if (rv != OK) destroy_and_exit_process(process, 1); apr_pool_clear(plog); if ( ap_run_open_logs(pconf, plog, ptemp, server_conf) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Unable to open logs); destroy_and_exit_process(process, 1); if ( ap_run_post_config(pconf, plog, ptemp, server_conf) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Configuration Failed); destroy_and_exit_process(process, 1); apr_pool_destroy(ptemp); for (;) apr_hook_deregister_all(); apr_pool_clear(pconf); for (mod = ap_prelinked_modules; *mod != NULL; mod+) ap_register_hooks(*mod, pconf); /* This is a hack until we finish the code so that it only reads * the config file once and just operates on the tree already in * memory. rbb */ ap_conftree = NULL; apr_pool_create(&ptemp, pconf); apr_pool_tag(ptemp, ptemp); ap_server_root = def_server_root;/*=下面这一段是对配置文件进行处理,每次循环都要处理 =*/ server_conf = ap_read_config(process, ptemp, confname, &ap_conftree); if (!server_conf) destroy_and_exit_process(process, 1); if (ap_run_pre_config(pconf, plog, ptemp) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Pre-configuration failed); destroy_and_exit_process(process, 1); if (ap_process_config_tree(server_conf, ap_conftree, process-pconf, ptemp) != OK) destroy_and_exit_process(process, 1); ap_fixup_virtual_hosts(pconf, server_conf); ap_fini_vhost_config(pconf, server_conf); apr_hook_sort_all(); apr_pool_clear(plog); if (ap_run_open_logs(pconf, plog, ptemp, server_conf) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Unable to open logs); destroy_and_exit_process(process, 1); if (ap_run_post_config(pconf, plog, ptemp, server_conf) != OK) ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, Configuration Failed); destroy_and_exit_process(process, 1); /*=上面这一段是对配置文件进行处理,每次循环都要处理 =*/ apr_pool_destroy(ptemp); apr_pool_lock(pconf, 1); ap_run_optional_fn_retrieve(); if (ap_mpm_run(pconf, plog, server_conf) :如果出错,则跳出循环。 break; apr_pool_lock(pconf, 0); for(;)在这里结束。父进程的这个循环,每次都会重新读入配置文件进行处理。然后调用ap_mpm_run()重新生成子进程。 apr_pool_lock(pconf, 0); destroy_and_exit_process(process, 0); return 0; /* Termination ok */int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) int index; int remaining_children_to_start; apr_status_t rv; ap_log_pid(pconf, ap_pid_fname); first_server_limit = server_limit; if (changed_limit_at_restart) ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, WARNING: Attempt to change ServerLimit ignored during restart); changed_limit_at_restart = 0; /* Initialize cross-process accept lock */ ap_lock_fname = apr_psprintf(_pconf, %s.% APR_PID_T_FMT, ap_server_root_relative(_pconf, ap_lock_fname), ap_my_pid); rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname, ap_accept_lock_mech, _pconf); if (ap_accept_lock_mech = APR_LOCK_SYSVSEM) rv = unixd_set_proc_mutex_perms(accept_mutex); if (!is_graceful) if (ap_run_pre_mpm(s-process-pool, SB_SHARED) != OK) mpm_state = AP_MPMQ_STOPPING; return 1; /* fix the generation number in the global score; we just got a new, * cleared scoreboard */ ap_scoreboard_image-global-running_generation = ap_my_generation; set_signals(); 这里进行信号量设定,对主进程有效,对子进程有没有效? Apachectl restart,apachectl stop, apachectl graceful,这些命令将会导致 信号处理函数 设定如下的全局变量static int volatile shutdown_pending;static int volatile restart_pending;static int volatile is_graceful;这些变量定义在 prefork.c中。 当这些变量发生改变时,程序的流程将发生相应的变化。 if (one_process) AP_MONCONTROL(1); make_child(ap_server_conf, 0); else if (ap_daemons_max_free ap_daemons_limit) remaining_children_to_start = ap_daemons_limit; if (!is_graceful) startup_children(remaining_children_to_start); remaining_children_to_start = 0; else /* give the system some time to recover before kicking into * exponential mode */ hold_off_on_exponential_spawning = 10; ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, %s configured - resuming normal operations, ap_get_server_description(); ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, Server built: %s, ap_get_server_built();#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, AcceptMutex: %s (default: %s), apr_proc_mutex_name(accept_mutex), apr_proc_mutex_defname();#endif restart_pending = shutdown_pending = 0; mpm_state = AP_MPMQ_RUNNING; while (!restart_pending & !shutdown_pending) :这里每隔一秒就往返一次。一直进行不停 int child_slot; apr_exit_why_e exitwhy; int status, processed_status; /* this is a memory leak, but Ill fix it later. */ apr_proc_t pid; ap_wait_or_timeout(&exitwhy, &status, &pid, pconf); /* XXX: if it takes longer than 1 second for all our children * to start up and get into IDLE state then we may spawn an * extra child */ if (pid.pid != -1) processed_status = ap_process_child_status(&pid, exitwhy, status); if (processed_status = APEXIT_CHILDFATAL) mpm_state = AP_MPMQ_STOPPING; return 1; /* non-fatal death. note that its gone in the scoreboard. */ child_slot = find_child_by_pid(&pid); if (child_slot = 0) (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD, (request_rec *) NULL); if (processed_status = APEXIT_CHILDSICK) /* child detected a resource shortage (ENMFILE, ENOBUFS, etc) * cut the fork rate to the minimum */ idle_spawn_rate = 1; else if (remaining_children_to_start & child_slot ap_daemons_limit) /* were still doing a 1-for-1 replacement of dead * children with new children */ make_child(ap_server_conf, child_slot);如果apachectl graceful,将会执行到这里,在这个循环里每一次都会执行到这里,生成相应的子进程, -remaining_children_to_start; #if APR_HAS_OTHER_CHILD else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH, status) = APR_SUCCESS) /* handled */#endif else if (is_graceful) /* Great, weve probably just lost a slot in the * scoreboard. Somehow we dont know about this * child. */ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, long lost child came home! (pid %ld), (long)pid.pid); /* Dont perform idle maintenance when a child dies, * only do it when theres a timeout. Remember only a * finite number of children can die, and its pretty * pathological for a lot to die suddenly. */ continue; else if (remaining_children_to_start) /* we hit a 1 second timeout in which none of the previous * generation of children needed to be reaped. so assume * theyre all done, and pick up the slack if any is left. */ startup_children(remaining_children_to_start); remaining_children_to_start = 0; /* In any event we really shouldnt do the code below because * few of the servers we just started are in the IDLE state * yet, so wed mistakenly create an extra server. */ continue; perform_idle_server_maintenance

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论