很多地方还是看不懂,当个笔记记录下来,不对的地方大家直接指正
通过sapi/cli/php_cli.c入口文件开始一步步分析
1 _sapi_module_struct
a) name
b) pretty_name
c) startup => (int (*)(struct_sapi_module_struct *)) 0x57d070 <php_cli_startup>
d) shutdown => php_module_shutdown_wrapper
e) activate
f) deactivate => sapi_cli_deactivate
g) sapi_cli_ub_write => ub_write
h) sapi_cli_flush => flush
i) php_error
j) sapi_cli_header_handler
k) sapi_cli_send_headers
l) sapi_cli_send_header
m) sapi_cli_read_cookies
n) sapi_cli_register_variables
o) sapi_cli_log_message
2 所有sapi都需要实现一个_sapi_module_struct结构体中对应的函数
3 memcpy(cli_sapi_module.ini_entries,HARDCODED_INI, ini_entries_len+1);
a) 由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
b) void *memcpy(void *dest, constvoid *src, size_t n);
c) 为ini_entres申请ini_entries_len+1的空间
d) HARDCODED_INI 干啥用的?
4 初始化
a) orig_optarg为空
b) orig_optind为0
c) volatile int exit_status =SUCCESS; // volatile是一个类型修饰符(typespecifier)。它是被设计用来修饰被不同线程访问和修改的变量
d) lineno 初始化为0
e) volatile int module_started =0;
f) volatile int request_started =0;
5 signal(SIGPIPE, SIG_IGN); //涉及信号量的相关知识
6 sapi_startup(&cli_sapi_module); //函数分析
a) 初始化ini_entries为空
b) 将cli_sapi_module赋值给sapi_module //sapi_module_struct 并且是global的
c) sapi_globals_ctor(&sapi_globals); //sapi_globals 是sapi_globals_struct的结构体
i. memset(sapi_globals, 0,sizeof(*sapi_globals)); //初始化sapi_globals为0
ii. 其中sapi_globals中有个hashtable,值为known_post_content_types,对其进行了hash初始化,这里初始化了5个大小
iii. zend_hash.c:185 调用了_zend_hash_init_ex函数 应该是第一次hash的地方
iv. 然后调用了php_setup_sapi_content_types
1. sapi_register_post_entries
2. 参数为post_entries,是sapi_post_entry结构体
a) content_type = 0x5ec9c8 "application/x-www-form-urlencoded",
b) content_type_len = 33,
c) post_reader = 0x4c7040<sapi_read_standard_form_data>,
d) post_handler = 0x4cb780<php_std_post_handler>
3. 然后调用sapi_register_post_entry
a) 先判断SG(sapi_started) && EG(in_execution) //SG EG在哪初始化的
b) zend_hash_add(&SG(known_post_content_types),post_entry->content_type, post_entry->content_type_len+1, (void *)post_entry, sizeof(sapi_post_entry), NULL); //添加入了刚初始化的hash表中
d) virtual_cwd_startup()
i. 填充了一个main_cwd_state
ii. cwd_globals_dtor _virtual_cwd_globals一个结构体
7 while ((c = php_getopt(argc,argv, OPTIONS, &php_optarg, &php_optind, 0))!=-1) {
a) 这段switch没有进入,具体干什么作用的以后细查询
8 cli_sapi_module.startup(&cli_sapi_module)
a) 调用了php_cli_startup, cli.sapi.module作为参数
b) 调用php_module_startup模块
php_module_startup //模块初始化
1 初始化变量
a) int module_number=0;
b) module_startup = 1;
2 sapi_initialize_empty_request
a) 初始化SG符号表:server_context、request_info
3 sapi_activate
a) zend_llist_init
i. 填充一个zend_llist的结构体
b) 初始化一些SG符号表
i. sapi_headers
ii. headers_sent
iii. read_post_bytes
iv. request_info
v. global_request_time
vi. rfc1867_uploaded_files
4 sapi_module = *sf;
5 php_output_startup
a) php_output_init_globals
i. 初始化些OG符号表
1. php_body_write
2. php_header_write
3. implicit_flush
4. output_start_filename
5. output_start_lineno
6 zend_utility_functions 声明了这个结构体
a) zend utility的方法接口列表
b) php_error_cb、php_printf、php_body_write_wrapper、php_fopen_wrapper_for_zend、php_message_handler_for_zend、sapi_module.block_interruptions、sapi_module.unblock_interruptions、php_get_configuration_directive_for_zend、php_run_ticks、php_on_timeout、php_stream_open_for_zend、vspprintf、sapi_getenv
7 zend_startup //进行初始化zend_utility_functions
a) start_memory_manager
b) zend_startup_strtod //什么也没干
c) zend_startup_extensions_mechanism //扩展相关的,仅初始化了一个zend_llist结构体
d) 接下来的一大部分是将utility的functions复制给zend
i. zend_error_cb、zend_printf、zend_write、zend_fopen、zend_stream_open_function、zend_stream_open_function、zend_message_dispatcher_p、zend_block_interruptions、zend_unblock_interruptions、zend_get_configuration_directive_p、zend_ticks_function、zend_on_timeout、zend_vspprintf、zend_getenv
ii. zend_compile_file = zend_compile_file //这个额外提下,是zend_op_array*的一个function
iii. zend_compile_string = compile_string //同上
iv. zend_execute = execute
e) zend_init_opcodes_handlers //该函数声明了opcode函数列表
f) 接下来一部分分配并且初始化了一些全局的hash符号表
i. GLOBAL_FUNCTION_TABLE //100长度
ii. GLOBAL_CLASS_TABLE //10长度
iii. GLOBAL_AUTO_GLOBALS_TABLE
iv. module_registry //50 长度
v. zend_init_rsrc_list_dtors //初始化了50长度的list_destructors哈希表,用户销毁
g) zval_used_for_init //填充了一个用户初始化的变量结构
h) CG(auto_globals)初始化了8个长度的哈希符号表
i) scanner_globals_ctor(&ini_scanner_globalsTSRMLS_CC);
j) scanner_globals_ctor(&language_scanner_globalsTSRMLS_CC); //这两部分都是用来填充zend_scanner_globals结构体,进行初始化
k) zend_startup_constants //申请了长度为20的常量哈希符号表EG(zend_constants)
l) zend_set_default_compile_time_values //初始化默认的编译时变量asp_tags、short_tags、allow_call_time_pass_reference、compiler_options
m) EG(user_error_handler) = NULL; //出错EG
n) EG(user_exception_handler) =NULL; //异常的EG
o) register_standard_class //填充zend_class_entry,初始化stdClass
i. 填充zend_class_entry 结构体
ii. 初始化了多个hash表
1. &ce->default_properties
2. &ce->properties_info
3. &ce->default_static_members
4. &ce->constants_table
5. &ce->function_table
iii. 并添加进入到CG(class_table) 类哈希符号表中
p) zend_register_standard_constants
i. 注册了一些系统常量E_ALL、E_NOTICE等
ii. 注册了TRUE、FALSE、NULL等常量
q) zend_register_auto_global("GLOBALS",sizeof("GLOBALS")-1, NULL TSRMLS_CC); //注册了GLOBALS这个名称到CG(auto_globals)编译时符号表
r) zend_startup_builtin_functions
s) zend_ini_startup //申请了registered_zend_ini_directives的hash表并进行了初始化