读apache代码v2.0---发文于2015-5-6

一。概要
1.平台功能层,可移植运行库层,核心功能层,可选功能层,第三方支持库
2.核心功能层:mod_core 处理配置文件中的大部分配置指令
mod_so 动态加载其余模块
mpm 多进程处理
3.http_config:对配置文件解析,处理,保存.
http_connection:处理http连接
http_protocol:解析http请求头,生成返回给客户端的响应包.
http_request:ap_process_request请求处理。请求本身属性管槽更改,比如ap_allow_methods。子请求。重定向请求。
http_core:处理http协议。
mod_core:对核心需要的指令进行比较。


二。apache启动。(server/main.c)
http://blog.csdn.net/fatowen/article/details/5112349
 Apache运行MAIN函数入口->init_process初始化apr库(apache也是apr库的使用者)->首先要将相应的可选挂钩注册到核心->>init_process函数内初始化在命令行输入的指令信息并赋值存储在process_rec全局变量中->ap_setup_prelinked_modules将所有预链接的模块加入到模块链表中->ap_read_config将读取配置文件和命令行指令信息存放在相应的链表中Apache根据指令加载与连接模块->->ap_run_rewrite_args对通过命令行传入的参数进行重写,只有mpm才用到->apr_getopt对指令进行进一步解析->apr_pool_create分配全局内存池->ap_replace_stderr_log生成日志文件->ap_read_config读取配置文件,在ap_build_config函数中执行指令,并生成配置树->运行ap_run_pre_config()挂钩->ap_process_config_tree处理配置树->所有挂钩排序->检验配置文件挂钩ap_run_test_config()->->运行ap_run_open_logs()挂钩->运行挂钩ap_run_post_config()(运行读取配置文件之后的挂钩函数)其中的mod_ssl的挂钩ssl_init_Module()实现了具体操作-------->进入主循环->清空有挂钩函数->ap_register_hooks遍历所有模块注册的挂钩函数->再次运行读取配置文件,并生成配置树->运行挂钩ap_run_post_config()的过程->ap_run_optional_fn_retrieve其他模块声明自己的导出函数->ap_mpm_run()


1. 初始化内存池资源
2.两次对配置文件读取和解析。第一次预读取,获取第二次读时的配置信息,第二次读取内容。
3.初始化虚拟主机
4.初始化数据库连接。
5.通过ap_mpm_run交给mpm模块。当该模块失败或完毕时返回主程序。各种os特性限制,不存在一种普适的并发模型。
 交给mpm时为普通用户权限。


二。当有请求过来时,堆栈如下:
kd> kp
ChildEBP RetAddr  
0190ff10 6ff0b022 libhttpd!ap_process_request(struct request_rec * r = 0x00705c98) [e:\modsecurity\httpd-2.2.29\httpd-2.2.29\modules\http\http_request.c @ 259]
0190ff28 6ff05215 libhttpd!ap_process_http_connection(struct conn_rec * c = 0x00704cb8)+0x52 [e:\modsecurity\httpd-2.2.29\httpd-2.2.29\modules\http\http_core.c @ 190]
0190ff40 6ff05503 libhttpd!ap_run_process_connection(struct conn_rec * c = 0x00704cb8)+0x25 [e:\modsecurity\httpd-2.2.29\httpd-2.2.29\server\connection.c @ 43]
0190ff50 6ff1f64e libhttpd!ap_process_connection(struct conn_rec * c = 0x00704cb8, void * csd = 0x006f1c60)+0x33 [e:\modsecurity\httpd-2.2.29\httpd-2.2.29\server\connection.c @ 190]
0190ff70 78543433 libhttpd!worker_main(void * thread_num_val = 0x00704cb0)+0x9e [e:\modsecurity\httpd-2.2.29\httpd-2.2.29\server\mpm\winnt\child.c @ 784]
0190ffa8 785434c7 MSVCR90!_callthreadstartex(void)+0x1b [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c @ 348]




三。http连接处理
1.pre_connection的挂钩:
core_pre_connection(core.c中,是必须的。禁用nagle算法,),
ssl_hook_pre_connection,
nwssl_pre_connection,
logio_pre_conn插入log_input_outpu输入输出过滤器,
dumpio_pre_conn,
2. process_connection(允许协议模块处理,比如ftp,pop3.现在主要是http_core.c中的ap_process_http_connection和ap_process_http_async_connection). 
ap_read_request.
ap_process_request.
 
四。http_protocol模块解析报文。
解析http请求头(get index.html http/1.1),请求域(accept:*/*),请求体.保存到request_rec中。
经过输入过滤器链表,比如敏感字符。


五。请求处理ap_process_requst函数。
1.请求解析。通过ap_unescap_url函数进行url字符转义(如空格转为%20)。




六。->prefork_hooks->prefork_run->make_child->child_main->apr_thread_create->start_threads
1-->create_listener_thread->create_listener_thread->listener_threadap_process_connection(server/connection.c)->ap_run_process_connection
2-->worker_thread->process_socket->ap_process_connection


七。register_hooks->ap_hook_process_connection(core_pre_connection(core.c中))->ap_process_http_connection->ap_process_http_sync_connection
-->ap_read_request
-->ap_process_request->ap_process_async_request->ap_process_request_internal(server/request.c)->ap_unescape_url(处理url)->
ap_getparents(改成绝对路径,剔除/../)->ap_location_walk(查找该url的配置信息,比如授权,权限)->ap_run_translate_name对url转换比如代理添加proxy.->ap_run_map_to_storage(转换为本地磁盘资源的路径)->ap_location_walk读取转换后的新url的配置信息->ap_run_header_parser检查http头->ap_run_access_checker检查访问限制,比如限制ip访问->ap_run_check_user_id检查用户密码->
ap_run_auth_checker资源的权限检查->ap_run_type_checker检查资源类型,由mod_mime完成.->ap_run_fixups生成相应内容给客户.


八.htaccess文件对每个请求读取一次配置文件.


九。杂项
1.条件指令由core.c处理.比如ifmodule的处理函数为函数start_ifmod.
2..htaccess处理函数为ap_parse_htaccess,在config.c文件中,在request.c中调用。当接收到一个http请求时,需要获取对应的location配置信息,目录配置信息及文件配置信息当查找目录配置信息时,需要处理.htaccess文件。
3.模块相关:
apache1.3版本模块分为三部分:模块描述结构,模块配置数据结构,apache请求各阶段对应的处理函数。函数分为两种:初始化函数和请求处理函数。初始化函数负责对模块,子进程等进程初始化,包括mod_init,child_init,child_exit.
apache2.0版本:模块描述结构,模块配置数据结构,挂钩注册函数,指令表,可选函数,过滤器相关处理。
核心模块和非核心模块通过request_rec, conn_rec, server_rec结构交互。
module结构定义在http_config.h中。
apache模块状态过程分为预加载模块,预链接模块。ap_preloaded_modules定义在os/win32/modules.c中,包括所有默认静态编译的模块。ap_prelined_modules包括默认在apache
启动后处于激活状态的模块。
ap_loaded_modules包括所有已经加载的模块,但不一定激活。ap_top_modules链表保存所有被激活的模块。
ap_setup_prelinked_modules函数开始加载模块,在main.c中。ap_add_module用于加载模块,对应于AddModule指令。
ap_add_module_commands函数将模块的指令及指令处理函数加入到指令哈希表中。
4.指令表:对于指令共享,apache2.2引入哈希表解决。键是指令名称,值是对应的处理函数的模块链表,由ap_mod_list结构表示,全局哈希表由ap_config_hash表示,每次通过ap_add_module_commands插入,然后rebuild_conf_hash重建哈希表。
动态模块加载由函数load_module实现,在modules/mappers/Mod_so.c中。
5.关于hook挂钩。使用ap_run_xxx触发挂钩,挂钩的触发通常是由核心模块在对客户端请求进行处理过程中进行的。使用ap_hook_xxx注册挂钩。当调用某个挂钩时,apache核心逐一遍历所有的模块,检查该模块是否注册了该挂钩,如果注册了,则调用该
挂钩函数处理,没有则查找下一个模块。
声明挂钩使用AP_DECLARE_HOOK. APACHE挂钩分为两类,启动挂钩和请求挂钩。启动挂钩有pre_config,post_config,open_logs及child_init.请求挂钩按顺序包括create_connection,pre_connection,process_connection,create_request,keep-alive阶段
(create_request,post_read_request),解析url阶段(translate_name(修改uri,比如mod_proxy添加proxy关键字),map_to_storage,header_parse(已废弃,换到post_read_request阶段)),授权认证阶段(access_checker(根据特定条件限制资源访问,比如ip),check_user_id(验证用户名和密码),auth_checker(通过认证的用户是否有权限查看资源)),响应内容生成阶段(type_checker(修改文档类型,比如mod_mime设置内容语言,编码及类型),fixups(向客户发送响应之前确定响应头,修改数据的最后机会),insert_filter(),handler)等。
同一挂钩的不同模块的函数数组使用apr_array_header_t数组报错,数组元素类型是ap_LINK_xxx格式。

你可能感兴趣的:(apache,代码,开源,http协议,分析)