From 94323cffc80658c3a132963a4c714edaa159fe19 Mon Sep 17 00:00:00 2001 From: xingskycn Date: Wed, 25 Mar 2015 15:46:04 +0800 Subject: [PATCH 01/23] commit --- 002.md | 450 ++++++++++++++++++++++++++++++++++ README.md | 1 + codes/globalss/.svnignore | 3 + codes/globalss/CREDITS | 1 + codes/globalss/EXPERIMENTAL | 0 codes/globalss/config.m4 | 9 + codes/globalss/config.w32 | 13 + codes/globalss/globalss.c | 172 +++++++++++++ codes/globalss/globalss.php | 11 + codes/globalss/php_globalss.h | 88 +++++++ codes/globalss/tests/001.phpt | 21 ++ 11 files changed, 769 insertions(+) create mode 100644 002.md create mode 100644 codes/globalss/.svnignore create mode 100644 codes/globalss/CREDITS create mode 100644 codes/globalss/EXPERIMENTAL create mode 100644 codes/globalss/config.m4 create mode 100644 codes/globalss/config.w32 create mode 100644 codes/globalss/globalss.c create mode 100644 codes/globalss/globalss.php create mode 100644 codes/globalss/php_globalss.h create mode 100644 codes/globalss/tests/001.phpt diff --git a/002.md b/002.md new file mode 100644 index 0000000..b698609 --- /dev/null +++ b/002.md @@ -0,0 +1,450 @@ +# 常用全局宏 + +1,创建一个新的扩展 + + ./ext_skel --extname=globals + +2,全局宏 + + +SG() SAPI Globals (main/SAPI.h) + + typedef struct { + const char *request_method; + char *query_string; + char *post_data, *raw_post_data; + char *cookie_data; + long content_length; + uint post_data_length, raw_post_data_length; + + char *path_translated; + char *request_uri; + + const char *content_type; + + zend_bool headers_only; + zend_bool no_headers; + zend_bool headers_read; + + sapi_post_entry *post_entry; + + char *content_type_dup; + + /* for HTTP authentication */ + char *auth_user; + char *auth_password; + char *auth_digest; + + /* this is necessary for the CGI SAPI module */ + char *argv0; + + char *current_user; + int current_user_length; + + /* this is necessary for CLI module */ + int argc; + char **argv; + int proto_num; + } sapi_request_info; + + + typedef struct _sapi_globals_struct { + void *server_context; + sapi_request_info request_info; + sapi_headers_struct sapi_headers; + int read_post_bytes; + unsigned char headers_sent; + struct stat global_stat; + char *default_mimetype; + char *default_charset; + HashTable *rfc1867_uploaded_files; + long post_max_size; + int options; + zend_bool sapi_started; + double global_request_time; + HashTable known_post_content_types; + zval *callback_func; + zend_fcall_info_cache fci_cache; + zend_bool callback_run; + } sapi_globals_struct; + + #ifdef ZTS + # define SG(v) TSRMG(sapi_globals_id, sapi_globals_struct *, v) + SAPI_API extern int sapi_globals_id; + #else + # define SG(v) (sapi_globals.v) + extern SAPI_API sapi_globals_struct sapi_globals; + + //访问SG变量 + #include "main/SAPI.h" + php_printf("default_mimetype : %s\n", SG(default_mimetype)); + + + +EG() 这个宏可以用来访问符号表,函数,资源信息和常量。 (zend/zend_globals_macros.h) + + struct _zend_executor_globals { + zval **return_value_ptr_ptr; + + zval uninitialized_zval; + zval *uninitialized_zval_ptr; + + zval error_zval; + zval *error_zval_ptr; + + /* symbol table cache */ + HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; + HashTable **symtable_cache_limit; + HashTable **symtable_cache_ptr; + + zend_op **opline_ptr; + + HashTable *active_symbol_table; + HashTable symbol_table; /* main symbol table */ + + HashTable included_files; /* files already included */ + + JMP_BUF *bailout; + + int error_reporting; + int orig_error_reporting; + int exit_status; + + zend_op_array *active_op_array; + + HashTable *function_table; /* function symbol table */ + HashTable *class_table; /* class table */ + HashTable *zend_constants; /* constants table */ + + zend_class_entry *scope; + zend_class_entry *called_scope; /* Scope of the calling class */ + + zval *This; + + long precision; + + int ticks_count; + + zend_bool in_execution; + HashTable *in_autoload; + zend_function *autoload_func; + zend_bool full_tables_cleanup; + + /* for extended information support */ + zend_bool no_extensions; + + #ifdef ZEND_WIN32 + zend_bool timed_out; + OSVERSIONINFOEX windows_version_info; + #endif + + HashTable regular_list; + HashTable persistent_list; + + zend_vm_stack argument_stack; + + int user_error_handler_error_reporting; + zval *user_error_handler; + zval *user_exception_handler; + zend_stack user_error_handlers_error_reporting; + zend_ptr_stack user_error_handlers; + zend_ptr_stack user_exception_handlers; + + zend_error_handling_t error_handling; + zend_class_entry *exception_class; + + /* timeout support */ + int timeout_seconds; + + int lambda_count; + + HashTable *ini_directives; + HashTable *modified_ini_directives; + zend_ini_entry *error_reporting_ini_entry; + + zend_objects_store objects_store; + zval *exception, *prev_exception; + zend_op *opline_before_exception; + zend_op exception_op[3]; + + struct _zend_execute_data *current_execute_data; + + struct _zend_module_entry *current_module; + + zend_property_info std_property_info; + + zend_bool active; + + zend_op *start_op; + + void *saved_fpu_cw_ptr; + #if XPFPA_HAVE_CW + XPFPA_CW_DATATYPE saved_fpu_cw; + #endif + + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; + }; + + //调用 + &EG(symbol_table) + + + +CG() 用来访问核心全局变量。(zend/zend_globals_macros.h) + + struct _zend_compiler_globals { + zend_stack bp_stack; + zend_stack switch_cond_stack; + zend_stack foreach_copy_stack; + zend_stack object_stack; + zend_stack declare_stack; + + zend_class_entry *active_class_entry; + + /* variables for list() compilation */ + zend_llist list_llist; + zend_llist dimension_llist; + zend_stack list_stack; + + zend_stack function_call_stack; + + char *compiled_filename; + + int zend_lineno; + + zend_op_array *active_op_array; + + HashTable *function_table; /* function symbol table */ + HashTable *class_table; /* class table */ + + HashTable filenames_table; + + HashTable *auto_globals; + + zend_bool parse_error; + zend_bool in_compilation; + zend_bool short_tags; + zend_bool asp_tags; + + zend_declarables declarables; + + zend_bool unclean_shutdown; + + zend_bool ini_parser_unbuffered_errors; + + zend_llist open_files; + + long catch_begin; + + struct _zend_ini_parser_param *ini_parser_param; + + int interactive; + + zend_uint start_lineno; + zend_bool increment_lineno; + + znode implementing_class; + + zend_uint access_type; + + char *doc_comment; + zend_uint doc_comment_len; + + zend_uint compiler_options; /* set of ZEND_COMPILE_* constants */ + + zval *current_namespace; + HashTable *current_import; + zend_bool in_namespace; + zend_bool has_bracketed_namespaces; + + zend_compiler_context context; + zend_stack context_stack; + + /* interned strings */ + char *interned_strings_start; + char *interned_strings_end; + char *interned_strings_top; + char *interned_strings_snapshot_top; + + HashTable interned_strings; + + const zend_encoding **script_encoding_list; + size_t script_encoding_list_size; + zend_bool multibyte; + zend_bool detect_unicode; + zend_bool encoding_declared; + + #ifdef ZTS + zval ***static_members_table; + int last_static_member; + #endif + }; + + typedef struct _zend_compiler_globals zend_compiler_globals; + #ifdef ZTS + # define CG(v) TSRMG(compiler_globals_id, zend_compiler_globals *, v) + int zendparse(void *compiler_globals); + #else + # define CG(v) (compiler_globals.v) + extern ZEND_API struct _zend_compiler_globals compiler_globals; + int zendparse(void); + #endif + + //调用 + php_printf("compiled_filename : %s\n", CG(compiled_filename)); + + + + +PG() PHP全局变量。我们知道php.ini会映射一个或者多个PHP全局结构。(main/php_globals.h) + + struct _php_core_globals { + zend_bool implicit_flush; + + long output_buffering; + + zend_bool sql_safe_mode; + zend_bool enable_dl; + + char *output_handler; + + char *unserialize_callback_func; + long serialize_precision; + + long memory_limit; + long max_input_time; + + zend_bool track_errors; + zend_bool display_errors; + zend_bool display_startup_errors; + zend_bool log_errors; + long log_errors_max_len; + zend_bool ignore_repeated_errors; + zend_bool ignore_repeated_source; + zend_bool report_memleaks; + char *error_log; + + char *doc_root; + char *user_dir; + char *include_path; + char *open_basedir; + char *extension_dir; + char *php_binary; + char *sys_temp_dir; + + char *upload_tmp_dir; + long upload_max_filesize; + + char *error_append_string; + char *error_prepend_string; + + char *auto_prepend_file; + char *auto_append_file; + + arg_separators arg_separator; + + char *variables_order; + + HashTable rfc1867_protected_variables; + + short connection_status; + short ignore_user_abort; + + unsigned char header_is_being_sent; + + zend_llist tick_functions; + + zval *http_globals[6]; + + zend_bool expose_php; + + zend_bool register_argc_argv; + zend_bool auto_globals_jit; + + char *docref_root; + char *docref_ext; + + zend_bool html_errors; + zend_bool xmlrpc_errors; + + long xmlrpc_error_number; + + zend_bool activated_auto_globals[8]; + + zend_bool modules_activated; + zend_bool file_uploads; + zend_bool during_request_startup; + zend_bool allow_url_fopen; + zend_bool enable_post_data_reading; + zend_bool always_populate_raw_post_data; + zend_bool report_zend_debug; + + int last_error_type; + char *last_error_message; + char *last_error_file; + int last_error_lineno; + + char *disable_functions; + char *disable_classes; + zend_bool allow_url_include; + zend_bool exit_on_timeout; + #ifdef PHP_WIN32 + zend_bool com_initialized; + #endif + long max_input_nesting_level; + long max_input_vars; + zend_bool in_user_include; + + char *user_ini_filename; + long user_ini_cache_ttl; + + char *request_order; + + zend_bool mail_x_header; + char *mail_log; + + zend_bool in_error_log; + + #ifdef PHP_WIN32 + zend_bool windows_show_crt_warning; + #endif + }; + typedef struct _php_core_globals php_core_globals; + #ifdef ZTS + # define PG(v) TSRMG(core_globals_id, php_core_globals *, v) + extern PHPAPI int core_globals_id; + #else + # define PG(v) (core_globals.v) + extern ZEND_API struct _php_core_globals core_globals; + #endif + + //调用 + php_printf("user_ini_filename : %s\n", PG(user_ini_filename)); + + +FG() 文件全局变量。大多数文件I/O或相关的全局变量的数据流都塞进标准扩展出口结构。(ext/standard/file.h) + + typedef struct { + int pclose_ret; + size_t def_chunk_size; + long auto_detect_line_endings; + long default_socket_timeout; + char *user_agent; /* for the http wrapper */ + char *from_address; /* for the ftp and http wrappers */ + char *user_stream_current_filename; /* for simple recursion protection */ + php_stream_context *default_context; + HashTable *stream_wrappers; /* per-request copy of url_stream_wrappers_hash */ + HashTable *stream_filters; /* per-request copy of stream_filters_hash */ + HashTable *wrapper_errors; /* key: wrapper address; value: linked list of char* */ + int pclose_wait; + } php_file_globals; + + #ifdef ZTS + #define FG(v) TSRMG(file_globals_id, php_file_globals *, v) + extern PHPAPI int file_globals_id; + #else + #define FG(v) (file_globals.v) + extern PHPAPI php_file_globals file_globals; + #endif + + diff --git a/README.md b/README.md index 03cc474..0949684 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ #### 附录 [1,gdb调试PHP扩展函数](https://github.com/Leon2012/php-ext/blob/master/001.md) +[2,常用全局宏](https://github.com/Leon2012/php-ext/blob/master/002.md) ##### 参考 diff --git a/codes/globalss/.svnignore b/codes/globalss/.svnignore new file mode 100644 index 0000000..da7f324 --- /dev/null +++ b/codes/globalss/.svnignore @@ -0,0 +1,3 @@ +.deps +*.lo +*.la diff --git a/codes/globalss/CREDITS b/codes/globalss/CREDITS new file mode 100644 index 0000000..f6e8a11 --- /dev/null +++ b/codes/globalss/CREDITS @@ -0,0 +1 @@ +globalss diff --git a/codes/globalss/EXPERIMENTAL b/codes/globalss/EXPERIMENTAL new file mode 100644 index 0000000..e69de29 diff --git a/codes/globalss/config.m4 b/codes/globalss/config.m4 new file mode 100644 index 0000000..d40e376 --- /dev/null +++ b/codes/globalss/config.m4 @@ -0,0 +1,9 @@ + PHP_ARG_WITH(globalss, for globalss support, + [ --with-globalss Include globalss support]) + + PHP_ARG_ENABLE(globalss, whether to enable globalss support, + [ --enable-globalss Enable globalss support]) + +if test "$PHP_GLOBALSS" != "no"; then + PHP_NEW_EXTENSION(globalss, globalss.c, $ext_shared) +fi diff --git a/codes/globalss/config.w32 b/codes/globalss/config.w32 new file mode 100644 index 0000000..3451f7b --- /dev/null +++ b/codes/globalss/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("globalss", "for globalss support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("globalss", "enable globalss support", "no"); + +if (PHP_GLOBALSS != "no") { + EXTENSION("globalss", "globalss.c"); +} + diff --git a/codes/globalss/globalss.c b/codes/globalss/globalss.c new file mode 100644 index 0000000..9de21bc --- /dev/null +++ b/codes/globalss/globalss.c @@ -0,0 +1,172 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2014 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_globalss.h" +#include "main/SAPI.h" + +/* If you declare any globals in php_globalss.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(globalss) +*/ + +/* True global resources - no need for thread safety here */ +static int le_globalss; + +/* {{{ globalss_functions[] + * + * Every user visible function must have an entry in globalss_functions[]. + */ +const zend_function_entry globalss_functions[] = { + PHP_FE(test_sapi_global, NULL) /* For testing, remove later. */ + PHP_FE(test_zend_global, NULL) + PHP_FE(test_php_global, NULL) + PHP_FE_END /* Must be the last line in globalss_functions[] */ +}; +/* }}} */ + +/* {{{ globalss_module_entry + */ +zend_module_entry globalss_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "globalss", + globalss_functions, + PHP_MINIT(globalss), + PHP_MSHUTDOWN(globalss), + PHP_RINIT(globalss), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(globalss), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(globalss), +#if ZEND_MODULE_API_NO >= 20010901 + PHP_GLOBALSS_VERSION, +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_GLOBALSS +ZEND_GET_MODULE(globalss) +#endif + +/* {{{ PHP_INI + */ +/* Remove comments and fill if you need to have entries in php.ini +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("globalss.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_globalss_globals, globalss_globals) + STD_PHP_INI_ENTRY("globalss.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_globalss_globals, globalss_globals) +PHP_INI_END() +*/ +/* }}} */ + +/* {{{ php_globalss_init_globals + */ +/* Uncomment this function if you have INI entries +static void php_globalss_init_globals(zend_globalss_globals *globalss_globals) +{ + globalss_globals->global_value = 0; + globalss_globals->global_string = NULL; +} +*/ +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(globalss) +{ + /* If you have INI entries, uncomment these lines + REGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(globalss) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(globalss) +{ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(globalss) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(globalss) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "globalss support", "enabled"); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + + + +PHP_FUNCTION(test_sapi_global) +{ + php_printf("default_mimetype : %s\n", SG(default_mimetype)); +} + +PHP_FUNCTION(test_zend_global) +{ + php_printf("compiled_filename : %s\n", CG(compiled_filename)); +} + +PHP_FUNCTION(test_php_global) +{ + php_printf("user_ini_filename : %s\n", PG(user_ini_filename)); +} +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/codes/globalss/globalss.php b/codes/globalss/globalss.php new file mode 100644 index 0000000..fe41d6e --- /dev/null +++ b/codes/globalss/globalss.php @@ -0,0 +1,11 @@ +"; + +if(!extension_loaded('globalss')) { + dl('globalss.' . PHP_SHLIB_SUFFIX); +} + +test_sapi_global(); +test_zend_global(); +test_php_global(); +?> diff --git a/codes/globalss/php_globalss.h b/codes/globalss/php_globalss.h new file mode 100644 index 0000000..c484308 --- /dev/null +++ b/codes/globalss/php_globalss.h @@ -0,0 +1,88 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2014 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_GLOBALSS_H +#define PHP_GLOBALSS_H + +extern zend_module_entry globalss_module_entry; +#define phpext_globalss_ptr &globalss_module_entry + +#define PHP_GLOBALSS_VERSION "0.1.0" /* Replace with version number for your extension */ + +#ifdef PHP_WIN32 +# define PHP_GLOBALSS_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_GLOBALSS_API __attribute__ ((visibility("default"))) +#else +# define PHP_GLOBALSS_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +PHP_MINIT_FUNCTION(globalss); +PHP_MSHUTDOWN_FUNCTION(globalss); +PHP_RINIT_FUNCTION(globalss); +PHP_RSHUTDOWN_FUNCTION(globalss); +PHP_MINFO_FUNCTION(globalss); + +PHP_FUNCTION(test_sapi_global); +PHP_FUNCTION(test_zend_global); +PHP_FUNCTION(test_execute_global); +PHP_FUNCTION(test_php_global); + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(globalss) + long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(globalss) +*/ + +/* In every utility function you add that needs to use variables + in php_globalss_globals, call TSRMLS_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as GLOBALSS_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define GLOBALSS_G(v) TSRMG(globalss_globals_id, zend_globalss_globals *, v) +#else +#define GLOBALSS_G(v) (globalss_globals.v) +#endif + +#endif /* PHP_GLOBALSS_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/codes/globalss/tests/001.phpt b/codes/globalss/tests/001.phpt new file mode 100644 index 0000000..ccdaea9 --- /dev/null +++ b/codes/globalss/tests/001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Check for globalss presence +--SKIPIF-- + +--FILE-- + +--EXPECT-- +globalss extension is available From 53d1f5bcac432d2f5803747da44b3b76dbbbde37 Mon Sep 17 00:00:00 2001 From: xingskycn Date: Wed, 25 Mar 2015 15:49:04 +0800 Subject: [PATCH 02/23] modify --- 002.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/002.md b/002.md index b698609..3a8fbd6 100644 --- a/002.md +++ b/002.md @@ -4,10 +4,10 @@ ./ext_skel --extname=globals -2,全局宏 +2,常用全局宏 -SG() SAPI Globals (main/SAPI.h) +A) SG() SAPI Globals (main/SAPI.h) typedef struct { const char *request_method; @@ -81,7 +81,7 @@ SG() SAPI Globals (main/SAPI.h) -EG() 这个宏可以用来访问符号表,函数,资源信息和常量。 (zend/zend_globals_macros.h) +B) EG() 这个宏可以用来访问符号表,函数,资源信息和常量。 (zend/zend_globals_macros.h) struct _zend_executor_globals { zval **return_value_ptr_ptr; @@ -190,7 +190,7 @@ EG() 这个宏可以用来访问符号表,函数,资源信息和常量。 ( -CG() 用来访问核心全局变量。(zend/zend_globals_macros.h) +C) CG() 用来访问核心全局变量。(zend/zend_globals_macros.h) struct _zend_compiler_globals { zend_stack bp_stack; @@ -296,7 +296,7 @@ CG() 用来访问核心全局变量。(zend/zend_globals_macros.h) -PG() PHP全局变量。我们知道php.ini会映射一个或者多个PHP全局结构。(main/php_globals.h) +D) PG() PHP全局变量。我们知道php.ini会映射一个或者多个PHP全局结构。(main/php_globals.h) struct _php_core_globals { zend_bool implicit_flush; @@ -422,7 +422,7 @@ PG() PHP全局变量。我们知道php.ini会映射一个或者多个PHP全局 php_printf("user_ini_filename : %s\n", PG(user_ini_filename)); -FG() 文件全局变量。大多数文件I/O或相关的全局变量的数据流都塞进标准扩展出口结构。(ext/standard/file.h) +E) FG() 文件全局变量。大多数文件I/O或相关的全局变量的数据流都塞进标准扩展出口结构。(ext/standard/file.h) typedef struct { int pclose_ret; @@ -447,4 +447,13 @@ FG() 文件全局变量。大多数文件I/O或相关的全局变量的数据 extern PHPAPI php_file_globals file_globals; #endif +F) TSRMLS相关 + + #define TSRMLS_FETCH( ) void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL) + #define TSRMG(id,type,el) (((type) (*((void ***) \ + tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->el) + #define TSRMLS_D void ***tsrm_ls + #define TSRMLS_DC , TSRMLS_D + #define TSRMLS_C tsrm_ls + #define TSRMLS_CC , TSRMLS_C From e82e4e349b627129a296896831506a40f400145e Mon Sep 17 00:00:00 2001 From: xingskycn Date: Wed, 25 Mar 2015 15:50:10 +0800 Subject: [PATCH 03/23] modify --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0949684..28f31a2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ #### 附录 [1,gdb调试PHP扩展函数](https://github.com/Leon2012/php-ext/blob/master/001.md) + [2,常用全局宏](https://github.com/Leon2012/php-ext/blob/master/002.md) ##### 参考 From 992645807df6e87a2aec0865ec77c423cb6f37b1 Mon Sep 17 00:00:00 2001 From: xingskycn Date: Wed, 25 Mar 2015 16:05:50 +0800 Subject: [PATCH 04/23] modify --- 05.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/05.md b/05.md index fc025a5..0ff366e 100644 --- a/05.md +++ b/05.md @@ -39,6 +39,26 @@ typedef Bucket* HashPosition; + //初始化HashTable + HashTable *myht; + zval *zv; + + /* Same as myht = emalloc(sizeof(HashTable)); */ + ALLOC_HASHTABLE(myht); + + zend_hash_init(myht, 0, NULL, ZVAL_PTR_DTOR, 0); + MAKE_STD_ZVAL(zv); + ZVAL_STRING(zv, "foo", 1); + + /* In PHP: $array[42] = "foo" */ + zend_hash_index_update(myht, 42, &zv, sizeof(zval *), NULL); + + zend_hash_destroy(myht); + + /* Same as efree(myht); */ + FREE_HASHTABLE(myht); + + HashTable *names, *options = NULL; HashPosition pos;//此值是Bucket的指针,pos->h表示的即是当前值的index zval **val; From a18fb68238dda10eaa392881c756e050c43a4417 Mon Sep 17 00:00:00 2001 From: xingskycn Date: Wed, 25 Mar 2015 17:33:01 +0800 Subject: [PATCH 05/23] modify --- 05.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/05.md b/05.md index 0ff366e..d582990 100644 --- a/05.md +++ b/05.md @@ -112,6 +112,10 @@ zend_hash_move_forward(names); zend_hash_move_forward_ex(names, &pos); //hash指针移至下一位 + //HashTable长度 + php_printf("%*carray(%d) {\n", depth * 2, ' ', zend_hash_num_elements(Z_ARRVAL_P(zv)) + + 3,数组函数说明 From 6fa8dd6ce2b1c36ed6f25c5bdf71b865af23be54 Mon Sep 17 00:00:00 2001 From: Leon Date: Wed, 25 Mar 2015 21:24:52 +0800 Subject: [PATCH 06/23] Update 09.md --- 09.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/09.md b/09.md index c0864e3..e1709bc 100644 --- a/09.md +++ b/09.md @@ -3,8 +3,52 @@ 1,创建一个扩展 ./ext_skel --extname=objects1 + +2,zend_class_entry结构 + + struct _zend_class_entry { + char type; + char *name; + zend_uint name_length; + struct _zend_class_entry *parent; + int refcount; + zend_bool constants_updated; + zend_uint ce_flags; + + HashTable function_table; + HashTable default_properties; + HashTable properties_info; + HashTable *static_members; + HashTable constants_table; + struct _zend_function_entry *builtin_functions; + + union _zend_function *constructor; + union _zend_function *destructor; + union _zend_function *clone; + union _zend_function *_ _get; + union _zend_function *_ _set; + union _zend_function *_ _call; + + zend_class_iterator_funcs iterator_funcs; + + /* handlers */ + zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC); + zend_object_iterator *(*get_iterator) + (zend_class_entry *ce, zval *object TSRMLS_DC); + int (*interface_gets_implemented) + (zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); + zend_class_entry **interfaces; + zend_uint num_interfaces; + + char *filename; + zend_uint line_start; + zend_uint line_end; + char *doc_comment; + zend_uint doc_comment_len; + }; + -2,类的定义 +3,类的定义 static zend_class_entry *hello_ce; //申明类 @@ -121,7 +165,7 @@ -3,类的控制 +4,类的控制 //fn_flags代表可以在定义方法时使用,zend_property_info.flags代表可以在定义属性时使用,ce_flags代表在定义zend_class_entry时候可用 //ZEND_ACC_CTOR 构造函数掩码 , ZEND_ACC_DTOR 析构函数掩码 @@ -153,7 +197,7 @@ #define ZEND_ACC_CALL_VIA_HANDLER 0x200000 /* fn_flags */ -4,宏 +5,宏 #define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL) @@ -206,6 +250,7 @@ } + @@ -214,5 +259,3 @@ - - \ No newline at end of file From 954b3267abf589093b0ad7c4f43bd43ce58bec71 Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 7 Apr 2015 17:45:09 +0800 Subject: [PATCH 07/23] add 003.md --- 003.md | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 221 insertions(+) create mode 100644 003.md diff --git a/003.md b/003.md new file mode 100644 index 0000000..ce4b7a5 --- /dev/null +++ b/003.md @@ -0,0 +1,219 @@ +# ZVAL + +1,创建一个新的扩展 + + ./ext_skel --extname=zval1 + +2,zval结构 + + #Zend/zend.h + typedef union _zvalue_value { + long lval; /* long 值 */ + double dval; /* double 值 */ + struct { /* 字符串类型值 */ + char *val; + int len; + } str; + HashTable *ht; /* hash table value */ + zend_object_value obj; /* 对像类型值 */ + } zvalue_value; + + struct _zval_struct { + /* Variable information */ + zvalue_value value; /* 值 */ + zend_uint refcount__gc; /* 引用计数 */ + zend_uchar type; /* 类型 */ + zend_uchar is_ref__gc; /* 是否引用 */ + }; + +3,宏 + + #宏的名字的规则,Z_XXXX -> zvale, Z_XXXX_P -> *zval, Z_XXXX_PP -> **zval + + #Zend/zend_alloc.h + #define ALLOC_ZVAL(z) (z) = (zval *) emalloc(sizeof(zval)) + #define FREE_ZVAL(z) efree_rel(z) + #define ALLOC_ZVAL_REL(z) (z) = (zval *) emalloc_rel(sizeof(zval)) + #define FREE_ZVAL_REL(z) efree_rel(z) + + #Zend/zend.h + #define INIT_PZVAL(z) (z)->refcount__gc = 1;(z)->is_ref__gc = 0; + #define INIT_ZVAL(z) z = zval_used_for_init; + + #define ZVAL_FALSE(z) ZVAL_BOOL(z, 0) //设置zval + #define ZVAL_TRUE(z) ZVAL_BOOL(z, 1) + + /* struct操作宏 */ + #define Z_LVAL(zval) (zval).value.lval //获取long值 + #define Z_BVAL(zval) ((zend_bool)(zval).value.lval) //获取bool值 + #define Z_DVAL(zval) (zval).value.dval //获取double值 + #define Z_STRVAL(zval) (zval).value.str.val //获取string的指针 + #define Z_STRLEN(zval) (zval).value.str.len //获取string的长度 + #define Z_ARRVAL(zval) (zval).value.ht //获取hashtable值 + #define Z_OBJVAL(zval) (zval).value.obj //获取object值 + #define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle // + #define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers // + #define Z_OBJCE(zval) zend_get_class_entry(&(zval) TSRMLS_CC) // + #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) // + #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf // + #define Z_RESVAL(zval) (zval).value.lval //获取long值 + #define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)? Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC): (is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL)) // + + /* 指针操作宏 */ + #define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) + #define Z_BVAL_P(zval_p) Z_BVAL(*zval_p) + #define Z_DVAL_P(zval_p) Z_DVAL(*zval_p) + #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) + #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) + #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p) + #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p) + #define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p) + #define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p) + #define Z_OBJVAL_P(zval_p) Z_OBJVAL(*zval_p) + #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p) + #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p) + #define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h) #define Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp) + + /* */ + #define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp) + #define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp) + #define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp) + #define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp) + #define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) + #define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp) + #define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp) + #define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp) + #define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp) + #define Z_OBJVAL_PP(zval_pp) Z_OBJVAL(**zval_pp) + #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p) + #define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p) + #define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h) + #define Z_OBJDEBUG_PP(zval_pp,is_tmp) Z_OBJDEBUG(**zval_pp,is_tmp) + + + /* 获取zval的变量类型 */ + #define Z_TYPE(zval) (zval).type + #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) + #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp) + + /* zval初始化宏 */ + #define ALLOC_ZVAL(z) (z) = (zval *) emalloc(sizeof(zval)) //初始化zval,分配内存 + #define FREE_ZVAL(z) efree_rel(z) //释放zvalue内存 + + #define ALLOC_ZVAL_REL(z)(z) = (zval *) emalloc_rel(sizeof(zval)) + #define FREE_ZVAL_REL(z) efree_rel(z) + + /* HashTable初始化宏 */ + #define ALLOC_HASHTABLE(ht) (ht) = (HashTable *) emalloc(sizeof(HashTable)) //初始化HashTable + #define FREE_HASHTABLE(ht) efree(ht) + + #define ALLOC_HASHTABLE_REL(ht) (ht) = (HashTable *) emalloc_rel(sizeof(HashTable)) + #define FREE_HASHTABLE_REL(ht) efree_rel(ht) + + + #define INIT_PZVAL(z) (z)->refcount__gc = 1; (z)->is_ref__gc = 0; //设置refcount + #define INIT_ZVAL(z) z = zval_used_for_init; + + #define ALLOC_INIT_ZVAL(zp) ALLOC_ZVAL(zp); INIT_ZVAL(*zp); //分配内存并设置默认值 + #define MAKE_STD_ZVAL(zv) ALLOC_ZVAL(zv); INIT_PZVAL(zv); //分配内存并设置默认值 + #define PZVAL_IS_REF(z) Z_ISREF_P(z) + + /* 拷贝zval的值 */ + #define ZVAL_COPY_VALUE(z, v) \ + do { \ + (z)->value = (v)->value; \ + Z_TYPE_P(z) = Z_TYPE_P(v); \ + } while (0) + + + #define INIT_PZVAL_COPY(z, v) \ + do { \ + ZVAL_COPY_VALUE(z, v); \ + Z_SET_REFCOUNT_P(z, 1); \ + Z_UNSET_ISREF_P(z); \ + } while (0) + + + + + #define ZVAL_IS_NULL(z) (Z_TYPE_P(z)==IS_NULL) //判断zval是否为NULL + + /* 设置zval为resource类型值 */ + #define ZVAL_RESOURCE(z, l) do { \ + zval *__z = (z); \ + Z_LVAL_P(__z) = l; \ + Z_TYPE_P(__z) = IS_RESOURCE;\ + } while (0) + + /* 设置zval为bool类型值 */ + #define ZVAL_BOOL(z, b) do { \ + zval *__z = (z); \ + Z_LVAL_P(__z) = ((b) != 0); \ + Z_TYPE_P(__z) = IS_BOOL; \ + } while (0) + + /* 设置zval为NULL */ + #define ZVAL_NULL(z) { \ + Z_TYPE_P(z) = IS_NULL; \ + } + + /* 设置zval为long值 */ + #define ZVAL_LONG(z, l) { \ + zval *__z = (z); \ + Z_LVAL_P(__z) = l; \ + Z_TYPE_P(__z) = IS_LONG; \ + } + + /* 设置zval为double值 */ + #define ZVAL_DOUBLE(z, d) { \ + zval *__z = (z); \ + Z_DVAL_P(__z) = d; \ + Z_TYPE_P(__z) = IS_DOUBLE; \ + } + + /* 设置zval为string值 */ + #define ZVAL_STRING(z, s, duplicate) do { \ + const char *__s=(s); \ + zval *__z = (z); \ + Z_STRLEN_P(__z) = strlen(__s); \ + Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ + Z_TYPE_P(__z) = IS_STRING; \ + } while (0) + + /* 设置zval为string值 */ + #define ZVAL_STRINGL(z, s, l, duplicate) do { \ + const char *__s=(s); int __l=l; \ + zval *__z = (z); \ + Z_STRLEN_P(__z) = __l; \ + Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\ + Z_TYPE_P(__z) = IS_STRING; \ + } while (0) + + /* 设置zval为empty string值 */ + #define ZVAL_EMPTY_STRING(z) do { \ + zval *__z = (z); \ + Z_STRLEN_P(__z) = 0; \ + Z_STRVAL_P(__z) = STR_EMPTY_ALLOC();\ + Z_TYPE_P(__z) = IS_STRING; \ + } while (0) + + /* 设置zval为zval值 */ + #define ZVAL_ZVAL(z, zv, copy, dtor) { \ + zend_uchar is_ref = Z_ISREF_P(z); \ + zend_uint refcount = Z_REFCOUNT_P(z); \ + ZVAL_COPY_VALUE(z, zv); \ + if (copy) { \ + zval_copy_ctor(z); \ + } \ + if (dtor) { \ + if (!copy) { \ + ZVAL_NULL(zv); \ + } \ + zval_ptr_dtor(&zv); \ + } \ + Z_SET_ISREF_TO_P(z, is_ref); \ + Z_SET_REFCOUNT_P(z, refcount); \ + } + + + \ No newline at end of file diff --git a/README.md b/README.md index 28f31a2..e34063a 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ [2,常用全局宏](https://github.com/Leon2012/php-ext/blob/master/002.md) +[3,zval](https://github.com/Leon2012/php-ext/blob/master/003.md) + ##### 参考 [https://github.com/sgolemon/phptek2013](https://github.com/sgolemon/phptek2013) From db75a4d6c1ac9757f51a1cb9ffb12d1279c34114 Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 7 Apr 2015 18:20:59 +0800 Subject: [PATCH 08/23] modify --- 003.md | 16 ++- codes/zval1/.svnignore | 3 + codes/zval1/CREDITS | 1 + codes/zval1/EXPERIMENTAL | 0 codes/zval1/config.m4 | 12 ++ codes/zval1/config.w32 | 13 +++ codes/zval1/php_zval1.h | 87 ++++++++++++++ codes/zval1/tests/001.phpt | 21 ++++ codes/zval1/zval1.c | 226 +++++++++++++++++++++++++++++++++++++ codes/zval1/zval1.php | 24 ++++ 10 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 codes/zval1/.svnignore create mode 100644 codes/zval1/CREDITS create mode 100644 codes/zval1/EXPERIMENTAL create mode 100644 codes/zval1/config.m4 create mode 100644 codes/zval1/config.w32 create mode 100644 codes/zval1/php_zval1.h create mode 100644 codes/zval1/tests/001.phpt create mode 100644 codes/zval1/zval1.c create mode 100644 codes/zval1/zval1.php diff --git a/003.md b/003.md index ce4b7a5..8e0eadf 100644 --- a/003.md +++ b/003.md @@ -26,7 +26,21 @@ zend_uchar is_ref__gc; /* 是否引用 */ }; -3,宏 +3,zval类型 + + #define IS_NULL 0 + #define IS_LONG 1 + #define IS_DOUBLE 2 + #define IS_BOOL 3 + #define IS_ARRAY 4 + #define IS_OBJECT 5 + #define IS_STRING 6 + #define IS_RESOURCE 7 + #define IS_CONSTANT 8 + #define IS_CONSTANT_ARRAY 9 + #define IS_CALLABLE 10 + +4,宏 #宏的名字的规则,Z_XXXX -> zvale, Z_XXXX_P -> *zval, Z_XXXX_PP -> **zval diff --git a/codes/zval1/.svnignore b/codes/zval1/.svnignore new file mode 100644 index 0000000..da7f324 --- /dev/null +++ b/codes/zval1/.svnignore @@ -0,0 +1,3 @@ +.deps +*.lo +*.la diff --git a/codes/zval1/CREDITS b/codes/zval1/CREDITS new file mode 100644 index 0000000..c507ec7 --- /dev/null +++ b/codes/zval1/CREDITS @@ -0,0 +1 @@ +zval1 diff --git a/codes/zval1/EXPERIMENTAL b/codes/zval1/EXPERIMENTAL new file mode 100644 index 0000000..e69de29 diff --git a/codes/zval1/config.m4 b/codes/zval1/config.m4 new file mode 100644 index 0000000..1e23ceb --- /dev/null +++ b/codes/zval1/config.m4 @@ -0,0 +1,12 @@ + +dnl PHP_ARG_WITH(zval1, for zval1 support, +dnl Make sure that the comment is aligned: +dnl [ --with-zval1 Include zval1 support]) + + +PHP_ARG_ENABLE(zval1, whether to enable zval1 support, + [ --enable-zval1 Enable zval1 support]) + +if test "$PHP_ZVAL1" != "no"; then + PHP_NEW_EXTENSION(zval1, zval1.c, $ext_shared) +fi diff --git a/codes/zval1/config.w32 b/codes/zval1/config.w32 new file mode 100644 index 0000000..2af1b69 --- /dev/null +++ b/codes/zval1/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("zval1", "for zval1 support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("zval1", "enable zval1 support", "no"); + +if (PHP_ZVAL1 != "no") { + EXTENSION("zval1", "zval1.c"); +} + diff --git a/codes/zval1/php_zval1.h b/codes/zval1/php_zval1.h new file mode 100644 index 0000000..f4591ce --- /dev/null +++ b/codes/zval1/php_zval1.h @@ -0,0 +1,87 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2015 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_ZVAL1_H +#define PHP_ZVAL1_H + +extern zend_module_entry zval1_module_entry; +#define phpext_zval1_ptr &zval1_module_entry + +#define PHP_ZVAL1_VERSION "0.1.0" /* Replace with version number for your extension */ + +#ifdef PHP_WIN32 +# define PHP_ZVAL1_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_ZVAL1_API __attribute__ ((visibility("default"))) +#else +# define PHP_ZVAL1_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +PHP_MINIT_FUNCTION(zval1); +PHP_MSHUTDOWN_FUNCTION(zval1); +PHP_RINIT_FUNCTION(zval1); +PHP_RSHUTDOWN_FUNCTION(zval1); +PHP_MINFO_FUNCTION(zval1); + +PHP_FUNCTION(dump_zval_type); +PHP_FUNCTION(dump_zval_value); + + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(zval1) + long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(zval1) +*/ + +/* In every utility function you add that needs to use variables + in php_zval1_globals, call TSRMLS_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as ZVAL1_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define ZVAL1_G(v) TSRMG(zval1_globals_id, zend_zval1_globals *, v) +#else +#define ZVAL1_G(v) (zval1_globals.v) +#endif + +#endif /* PHP_ZVAL1_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/codes/zval1/tests/001.phpt b/codes/zval1/tests/001.phpt new file mode 100644 index 0000000..80a7045 --- /dev/null +++ b/codes/zval1/tests/001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Check for zval1 presence +--SKIPIF-- + +--FILE-- + +--EXPECT-- +zval1 extension is available diff --git a/codes/zval1/zval1.c b/codes/zval1/zval1.c new file mode 100644 index 0000000..32ac5c7 --- /dev/null +++ b/codes/zval1/zval1.c @@ -0,0 +1,226 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2015 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_zval1.h" + + +ZEND_BEGIN_ARG_INFO(DUMP_ZVAL_TYPE_ARGINFO, 0) + ZEND_ARG_INFO(0, zv) +ZEND_END_ARG_INFO() + + +ZEND_BEGIN_ARG_INFO(DUMP_ZVAL_VALUE_ARGINFO, 0) + ZEND_ARG_INFO(0, zv) +ZEND_END_ARG_INFO() + +/* If you declare any globals in php_zval1.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(zval1) +*/ + +/* True global resources - no need for thread safety here */ +static int le_zval1; + +/* {{{ zval1_functions[] + * + * Every user visible function must have an entry in zval1_functions[]. + */ +const zend_function_entry zval1_functions[] = { + PHP_FE(dump_zval_type, DUMP_ZVAL_TYPE_ARGINFO) + PHP_FE(dump_zval_value, DUMP_ZVAL_VALUE_ARGINFO) + PHP_FE_END /* Must be the last line in zval1_functions[] */ +}; +/* }}} */ + +/* {{{ zval1_module_entry + */ +zend_module_entry zval1_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "zval1", + zval1_functions, + PHP_MINIT(zval1), + PHP_MSHUTDOWN(zval1), + PHP_RINIT(zval1), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(zval1), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(zval1), +#if ZEND_MODULE_API_NO >= 20010901 + PHP_ZVAL1_VERSION, +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_ZVAL1 +ZEND_GET_MODULE(zval1) +#endif + +/* {{{ PHP_INI + */ +/* Remove comments and fill if you need to have entries in php.ini +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("zval1.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_zval1_globals, zval1_globals) + STD_PHP_INI_ENTRY("zval1.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_zval1_globals, zval1_globals) +PHP_INI_END() +*/ +/* }}} */ + +/* {{{ php_zval1_init_globals + */ +/* Uncomment this function if you have INI entries +static void php_zval1_init_globals(zend_zval1_globals *zval1_globals) +{ + zval1_globals->global_value = 0; + zval1_globals->global_string = NULL; +} +*/ +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(zval1) +{ + /* If you have INI entries, uncomment these lines + REGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(zval1) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(zval1) +{ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(zval1) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(zval1) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "zval1 support", "enabled"); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + + +/* Remove the following function when you have successfully modified config.m4 + so that your module can be compiled into PHP, it exists only for testing + purposes. */ + +/* Every user-visible function in PHP should document itself in the source */ +/* {{{ proto string confirm_zval1_compiled(string arg) + Return a string to confirm that the module is compiled in */ +PHP_FUNCTION(dump_zval_type) +{ + zval *zv; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zv) == FAILURE) { + return; + } + + RETURN_LONG(Z_TYPE_P(zv)); +} +/* }}} */ + +PHP_FUNCTION(dump_zval_value) +{ + zval *zv; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zv) == FAILURE) { + return; + } + + switch(Z_TYPE_P(zv)) { + case IS_NULL: + RETURN_NULL(); + break; + + case IS_LONG: + RETURN_LONG(Z_LVAL_P(zv)); + break; + + case IS_DOUBLE: + RETURN_DOUBLE(Z_DVAL_P(zv)); + break; + + case IS_BOOL: + RETURN_BOOL(Z_BVAL_P(zv)); + break; + + case IS_ARRAY: + RETURN_ZVAL(zv, 1, 0); + break; + + case IS_STRING: + RETURN_STRING(Z_STRVAL_P(zv), 0) + break; + + case IS_OBJECT: + RETURN_ZVAL(zv, 1, 0); + break; + + } + +} + + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/codes/zval1/zval1.php b/codes/zval1/zval1.php new file mode 100644 index 0000000..9474952 --- /dev/null +++ b/codes/zval1/zval1.php @@ -0,0 +1,24 @@ +"; + +if(!extension_loaded('zval1')) { + dl('zval1.' . PHP_SHLIB_SUFFIX); +} +echo dump_zval_type("test")."\n"; +echo dump_zval_type(1)."\n"; +echo dump_zval_type(NULL)."\n"; +echo dump_zval_type(0.5)."\n"; +echo dump_zval_type(array())."\n"; +echo dump_zval_type(new stdClass())."\n"; + +define("PI", 3.1415926); +echo dump_zval_type(constant("PI"))."\n"; + + +echo "value:". dump_zval_value("test") . "\n"; +print_r(dump_zval_value(array("arr1"))); +print_r(dump_zval_value(new stdClass())); +echo "value:". dump_zval_value(1.23) . "\n"; +//echo "value:". dump_zval_value(array("arr1")) . "\n"; + +?> From 662d31775d78a655b018425adaca666a9470852c Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 7 Apr 2015 18:34:01 +0800 Subject: [PATCH 09/23] modify --- 003.md | 16 ++++++++++++++++ codes/zval1/zval1.c | 12 ++++++++++++ codes/zval1/zval1.php | 3 +++ 3 files changed, 31 insertions(+) diff --git a/003.md b/003.md index 8e0eadf..37c5db7 100644 --- a/003.md +++ b/003.md @@ -229,5 +229,21 @@ Z_SET_REFCOUNT_P(z, refcount); \ } +5,类型转换 + + convert_to_long(zval *op); //zval -> long + convert_to_double(zval *op); //zval -> double + convert_to_null(zval *op); //zval -> null + convert_to_boolean(zval *op); //zval -> boolean + convert_to_array(zval *op); //zval -> array + convert_to_object(zval *op); //zval -> object + + #define convert_to_cstring(op) if ((op)->type != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); } + + #define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); } + + ZEND_API double zend_string_to_double(const char *number, zend_uint length); + + ZEND_API int zval_is_true(zval *op); \ No newline at end of file diff --git a/codes/zval1/zval1.c b/codes/zval1/zval1.c index 32ac5c7..51d831f 100644 --- a/codes/zval1/zval1.c +++ b/codes/zval1/zval1.c @@ -51,6 +51,7 @@ static int le_zval1; const zend_function_entry zval1_functions[] = { PHP_FE(dump_zval_type, DUMP_ZVAL_TYPE_ARGINFO) PHP_FE(dump_zval_value, DUMP_ZVAL_VALUE_ARGINFO) + PHP_FE(convert_zval, DUMP_ZVAL_VALUE_ARGINFO) PHP_FE_END /* Must be the last line in zval1_functions[] */ }; /* }}} */ @@ -215,6 +216,17 @@ PHP_FUNCTION(dump_zval_value) } +PHP_FUNCTION(convert_zval) +{ + zval *zv; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zv) == FAILURE) { + return; + } + + convert_to_double(zv); + RETURN_ZVAL(zv, 1, 0); +} + /* * Local variables: diff --git a/codes/zval1/zval1.php b/codes/zval1/zval1.php index 9474952..ec18a3f 100644 --- a/codes/zval1/zval1.php +++ b/codes/zval1/zval1.php @@ -21,4 +21,7 @@ echo "value:". dump_zval_value(1.23) . "\n"; //echo "value:". dump_zval_value(array("arr1")) . "\n"; + +echo convert_zval("10") . "\n"; + ?> From a25699ab06cb21d4af783b6c971957810a949c2e Mon Sep 17 00:00:00 2001 From: sunzy Date: Tue, 4 Aug 2015 15:33:51 +0800 Subject: [PATCH 10/23] Update 02.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修改FALSE为FAILURE 2.修改"数组类型"为"数据类型" --- 02.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/02.md b/02.md index 7b0c278..5f6e6f8 100644 --- a/02.md +++ b/02.md @@ -24,7 +24,7 @@ static PHP_FUNCTION(params_add) { long a,b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FALSE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) { return; } RETURN_LONG(a+b); @@ -60,7 +60,7 @@ //宏说明 ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) //开始参数块定义,pass_rest_by_reference为1时,强制所有参数为引用类型 ZEND_END_ARG_INFO() //结束参数块定义 - ZEND_ARG_INFO //声明普通参数,可以用来表示PHP中的int, float, double, string等基本数组类型 + ZEND_ARG_INFO //声明普通参数,可以用来表示PHP中的int, float, double, string等基本数据类型 ZEND_ARG_OBJ_INFO //声明对象类型的参数 ZEND_ARG_ARRAY_INFO //声明数组类型的参数 ZEND_ARG_PASS_INFO(pass_by_ref) //pass_by_ref为1时,强制设置后续的参数为引用类型 @@ -173,4 +173,4 @@ - \ No newline at end of file + From d00cde1738d53fe701e36a2f5a4420e6e90d61d7 Mon Sep 17 00:00:00 2001 From: sunzy Date: Wed, 5 Aug 2015 10:51:11 +0800 Subject: [PATCH 11/23] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改"对像"为"对象" --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e34063a..66ac088 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,11 @@ [8,调用php函数](https://github.com/Leon2012/php-ext/blob/master/08.md) -[9,类与对像1](https://github.com/Leon2012/php-ext/blob/master/09.md) +[9,类与对象1](https://github.com/Leon2012/php-ext/blob/master/09.md) -[10,类与对像2(自定义object存储)](https://github.com/Leon2012/php-ext/blob/master/10.md) +[10,类与对象2(自定义object存储)](https://github.com/Leon2012/php-ext/blob/master/10.md) -[11,类与对像3(object handlers)](https://github.com/Leon2012/php-ext/blob/master/11.md) +[11,类与对象3(object handlers)](https://github.com/Leon2012/php-ext/blob/master/11.md) [12,资源](https://github.com/Leon2012/php-ext/blob/master/12.md) From d4dceb1eeeba57d9f6be47dbe124e81f00210822 Mon Sep 17 00:00:00 2001 From: sunzy Date: Fri, 7 Aug 2015 17:36:29 +0800 Subject: [PATCH 12/23] Update 04.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 加入扩展代码 --- 04.md | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/04.md b/04.md index 37f71bb..7c12ffb 100644 --- a/04.md +++ b/04.md @@ -1,8 +1,135 @@ # INI参数设置 -1,创建一个新的扩展 +## 创建一个新的扩展 + ++ 生成扩展 + +``` +./ext_skel --extname=inis +``` + ++ config.m4 + +``` +PHP_ARG_ENABLE(inis, whether to enable inis support, +[ --enable-inis Enable inis support]) + +if test "$PHP_INIS" != "no"; then + PHP_NEW_EXTENSION(inis, inis.c, $ext_shared) +fi +``` + ++ php_inis.h + +``` +ZEND_BEGIN_MODULE_GLOBALS(inis) + char *name; + long level; +ZEND_END_MODULE_GLOBALS(inis) + +#ifdef ZTS +#define INIS_G(v) TSRMG(inis_globals_id, zend_inis_globals *, v) +#else +#define INIS_G(v) (inis_globals.v) +#endif +``` + ++ inis.c + +定义全局变量 + +``` +ZEND_DECLARE_MODULE_GLOBALS(inis) +``` + +设置INI参数 + +``` +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("inis.name","sunzy",PHP_INI_ALL,OnUpdateString,name,zend_inis_globals,inis_globals) + STD_PHP_INI_ENTRY("inis.level","1",PHP_INI_ALL,OnUpdateLong,level,zend_inis_globals,inis_globals) +PHP_INI_END() +``` + +初始化函数 + +``` +static void php_inis_init_globals(zend_inis_globals *inis_globals) +{ + inis_globals->name="sunzy.org"; + inis_globals->level=10; +} +``` + +注册&清除INI变量 + +``` +PHP_MINIT_FUNCTION(inis) +{ + REGISTER_INI_ENTRIES(); + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(inis) +{ + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} +``` + +自定义函数 + +``` +PHP_FUNCTION(inis_report) +{ + php_printf("Name:%s\n",INIS_G(name)); + php_printf("Level:%d\n",INIS_G(level)); +} +``` + +注册自定义函数 + +``` +const zend_function_entry inis_functions[] = { + PHP_FE(inis_report,NULL) + PHP_FE_END /* Must be the last line in inis_functions[] */ +}; +``` + ++ 测试 + +测试脚本 + +``` +$function = "inis_report"; +call_user_func($function); +``` + +测试 + +``` +$ /usr/local/php5.6.9/bin/php -q inis.php +Functions available in the test extension: +inis_report +Name:sunzy +Level:1 +``` + +修改php.ini + +``` +inis.name=test +inis.level=2 +``` + +``` +$ /usr/local/php5.6.9/bin/php -q inis.php +Functions available in the test extension: +inis_report +Name:test +Level:2 +``` - ./ext_skel --extname=inis 2,宏 From d1c52f6efb475660c32e6a11cb366350534db8a8 Mon Sep 17 00:00:00 2001 From: sunzy Date: Fri, 7 Aug 2015 17:38:36 +0800 Subject: [PATCH 13/23] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改为相对路径 --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 66ac088..78f81d9 100644 --- a/README.md +++ b/README.md @@ -2,39 +2,39 @@ #### 目录 -[1,创建一个新的扩展](https://github.com/Leon2012/php-ext/blob/master/01.md) +[1,创建一个新的扩展](./01.md) -[2,参数传递](https://github.com/Leon2012/php-ext/blob/master/02.md) +[2,参数传递](./02.md) -[3,返回值](https://github.com/Leon2012/php-ext/blob/master/03.md) +[3,返回值](./03.md) -[4,INI参数设置](https://github.com/Leon2012/php-ext/blob/master/04.md) +[4,INI参数设置](./04.md) -[5,数组](https://github.com/Leon2012/php-ext/blob/master/05.md) +[5,数组](./05.md) -[6,Global变量](https://github.com/Leon2012/php-ext/blob/master/06.md) +[6,Global变量](./06.md) -[7,常量](https://github.com/Leon2012/php-ext/blob/master/07.md) +[7,常量](./07.md) -[8,调用php函数](https://github.com/Leon2012/php-ext/blob/master/08.md) +[8,调用php函数](./08.md) -[9,类与对象1](https://github.com/Leon2012/php-ext/blob/master/09.md) +[9,类与对象1](./09.md) -[10,类与对象2(自定义object存储)](https://github.com/Leon2012/php-ext/blob/master/10.md) +[10,类与对象2(自定义object存储)](./10.md) -[11,类与对象3(object handlers)](https://github.com/Leon2012/php-ext/blob/master/11.md) +[11,类与对象3(object handlers)](./11.md) -[12,资源](https://github.com/Leon2012/php-ext/blob/master/12.md) +[12,资源](./12.md) -[13,包装第三方库](https://github.com/Leon2012/php-ext/blob/master/13.md) +[13,包装第三方库](./13.md) #### 附录 -[1,gdb调试PHP扩展函数](https://github.com/Leon2012/php-ext/blob/master/001.md) +[1,gdb调试PHP扩展函数](./001.md) -[2,常用全局宏](https://github.com/Leon2012/php-ext/blob/master/002.md) +[2,常用全局宏](./002.md) -[3,zval](https://github.com/Leon2012/php-ext/blob/master/003.md) +[3,zval](./003.md) ##### 参考 From b460cfd9c00094db888b76e2f0a8291e2485e133 Mon Sep 17 00:00:00 2001 From: sunzy Date: Fri, 7 Aug 2015 18:07:50 +0800 Subject: [PATCH 14/23] Update 04.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修改格式 2.引入更详细的宏定义 --- 04.md | 219 +++++++++++++++++++++++++--------------------------------- 1 file changed, 93 insertions(+), 126 deletions(-) diff --git a/04.md b/04.md index 7c12ffb..93bb07d 100644 --- a/04.md +++ b/04.md @@ -38,13 +38,13 @@ ZEND_END_MODULE_GLOBALS(inis) 定义全局变量 -``` +```c ZEND_DECLARE_MODULE_GLOBALS(inis) ``` 设置INI参数 -``` +```c PHP_INI_BEGIN() STD_PHP_INI_ENTRY("inis.name","sunzy",PHP_INI_ALL,OnUpdateString,name,zend_inis_globals,inis_globals) STD_PHP_INI_ENTRY("inis.level","1",PHP_INI_ALL,OnUpdateLong,level,zend_inis_globals,inis_globals) @@ -53,7 +53,7 @@ PHP_INI_END() 初始化函数 -``` +```c static void php_inis_init_globals(zend_inis_globals *inis_globals) { inis_globals->name="sunzy.org"; @@ -63,7 +63,7 @@ static void php_inis_init_globals(zend_inis_globals *inis_globals) 注册&清除INI变量 -``` +```c PHP_MINIT_FUNCTION(inis) { REGISTER_INI_ENTRIES(); @@ -79,7 +79,7 @@ PHP_MSHUTDOWN_FUNCTION(inis) 自定义函数 -``` +```c PHP_FUNCTION(inis_report) { php_printf("Name:%s\n",INIS_G(name)); @@ -89,7 +89,7 @@ PHP_FUNCTION(inis_report) 注册自定义函数 -``` +```c const zend_function_entry inis_functions[] = { PHP_FE(inis_report,NULL) PHP_FE_END /* Must be the last line in inis_functions[] */ @@ -100,14 +100,14 @@ const zend_function_entry inis_functions[] = { 测试脚本 -``` +```php $function = "inis_report"; call_user_func($function); ``` 测试 -``` +```shell $ /usr/local/php5.6.9/bin/php -q inis.php Functions available in the test extension: inis_report @@ -122,7 +122,7 @@ inis.name=test inis.level=2 ``` -``` +```shell $ /usr/local/php5.6.9/bin/php -q inis.php Functions available in the test extension: inis_report @@ -131,128 +131,95 @@ Level:2 ``` -2,宏 +## 相关的宏 - #define ZEND_DECLARE_MODULE_GLOBALS(module_name) ts_rsrc_id module_name##_globals_id; - - #define STD_PHP_INI_ENTRY STD_ZEND_INI_ENTRY - #define STD_ZEND_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ - ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr##_id) - #define ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer) \ ++ ZEND_DECLARE_MODULE_GLOBALS ->Zend/zend_API.h + + +```c +#ifdef ZTS +#define ZEND_DECLARE_MODULE_GLOBALS(module_name) \ + ts_rsrc_id module_name##_globals_id; +#else +#define ZEND_DECLARE_MODULE_GLOBALS(module_name) \ + zend_##module_name##_globals module_name##_globals; +#endif +``` + +```ts_rsrc_id```是[线程安全](http://walu.cc/phpbook/1.4.md)里的内容 + ++ PHP_INI_BEGIN、PHP_INI_END、STD_PHP_INI_ENTRY ->main/php_ini.h + +```c +#define PHP_INI_BEGIN ZEND_INI_BEGIN +#define PHP_INI_END ZEND_INI_END +#define STD_PHP_INI_ENTRY STD_ZEND_INI_ENTRY +``` + ++ ZEND_INI_BEGIN、ZEND_INI_END、STD_ZEND_INI_ENTRY -> Zend/zend_ini.h + +```c +#define ZEND_INI_BEGIN() static const zend_ini_entry ini_entries[] = { +#define ZEND_INI_END() { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } }; + +#define ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer) \ { 0, modifiable, name, sizeof(name), on_modify, arg1, arg2, arg3, default_value, sizeof(default_value)-1, NULL, 0, 0, 0, displayer }, - - #define ZEND_INI_BEGIN() static const zend_ini_entry ini_entries[] = { - #define ZEND_INI_END() { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } }; - - //注册ini变量,在minit中调用 - #define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number TSRMLS_CC) - - //清除ini变量,在mshutdown中调用 - #define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries(module_number TSRMLS_CC) - - //在phpinfo中显示变量值,在minfo中调用 - #define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module) - - // - -3,定义ini变量 - - struct _zend_ini_entry { - int module_number; - int modifiable; - char *name; - uint name_length; - ZEND_INI_MH((*on_modify)); - void *mh_arg1; - void *mh_arg2; - void *mh_arg3; - - char *value; - uint value_length; - - char *orig_value; - uint orig_value_length; - int orig_modifiable; - int modified; - - void (*displayer)(zend_ini_entry *ini_entry, int type); - }; - - //第二个参数即为ini变量的初始值 - PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("inis.enable", "1", PHP_INI_ALL, OnUpdateBool, enable, zend_inis_globals, inis_globals) - STD_PHP_INI_ENTRY("inis.name", "", PHP_INI_ALL, OnUpdateString, name, zend_inis_globals, inis_globals) - STD_PHP_INI_ENTRY("inis.level", "0", PHP_INI_ALL, OnUpdateLong, level, zend_inis_globals, inis_globals) - PHP_INI_END() - - #展开后 - - static const zend_ini_entry ini_entries[] = {//BEGIN - {0, PHP_INI_ALL, "inis.enable", sizeof("inis.enable"), OnUpdateBool, enable, zend_inis_globals, inis_globals... }//inis.enable定义 - ... - { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } //END - }; - - /*初始化ini值的宏*/ - ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor) - - #module_name 与传递给ZEND_BEGIN_MODULE_GLOBALS()宏相同的扩展名称。 - #globals_ctor 构造函数指针。在myfile扩展里,函数原形与void php_myfile_init_globals(zend_myfile_globals *myfile_globals)类似 - #globals_dtor 析构函数指针。例如,php_myfile_init_globals(zend_myfile_globals *myfile_globals) - -4,注册/清除/显示 ini变量 - PHP_MINIT_FUNCTION(inis) - { - REGISTER_INI_ENTRIES(); - return SUCCESS; - } - - PHP_MSHUTDOWN_FUNCTION(inis) - { - UNREGISTER_INI_ENTRIES(); - return SUCCESS; - } - - PHP_MINFO_FUNCTION(inis) - { - php_info_print_table_start(); - php_info_print_table_header(2, "inis support", "enabled"); - php_info_print_table_end(); - - DISPLAY_INI_ENTRIES(); - } - -5,获取ini变量的值 +#define ZEND_INI_ENTRY3(name, default_value, modifiable, on_modify, arg1, arg2, arg3) \ + ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, NULL) - //INIS_G宏即是用于获取ini变量的值的方法 - PHP_FUNCTION(inis_report) { - php_printf("Name:%s\n", INIS_G(name)); - php_printf("Level:%d\n", INIS_G(level)); - } - - -6,修改ini变量 - - #编辑php.ini文件 - vi /etc/php/php.ini +#define ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, arg1, arg2, displayer) \ + ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, NULL, displayer) + +#define ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, arg1, arg2) \ + ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, arg1, arg2, NULL) - #添加动态库,并修改其默认值 - extension=inis.so - inis.name = leon123 - inis.level = 200 +#ifdef ZTS +#define STD_ZEND_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ + ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr##_id) +#else +#define STD_ZEND_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ + ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr) +#endif + +``` + +前面扩展中对ini变量的定义展开后 + +```c +static const zend_ini_entry ini_entries[] = {//BEGIN + {0, PHP_INI_ALL, "inis.enable", sizeof("inis.enable"), OnUpdateBool, enable, zend_inis_globals, inis_globals... }//inis.enable定义 + ... + { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } //END +}; +``` - #运行,ini变量的值变成为上面修改过的值 - kentchentekiiMac-23868:inis kentchen$ php -q inis.php - Functions available in the test extension: - inis_report - Name:leon123 - Level:200 ++ REGISTER_INI_ENTRIES、UNREGISTER_INI_ENTRIES ->Zend/zend_ini.h + +```c +#define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number TSRMLS_CC) //注册ini变量 +#define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries(module_number TSRMLS_CC) //清除ini变量 +#define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module) //在phpinfo中显示变量值 +``` + + ++ ZEND_INIT_MODULE_GLOBALS ->Zend/zend_ini.h + +```c +#ifdef ZTS +#define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor) \ + ts_allocate_id(&module_name##_globals_id, sizeof(zend_##module_name##_globals), (ts_allocate_ctor) globals_ctor, (ts_allocate_dtor) globals_dtor); +#else +#define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor) \ + globals_ctor(&module_name##_globals); +#endif +``` +初始化ini值的宏 + +> module_name 与传递给ZEND_BEGIN_MODULE_GLOBALS()宏相同的扩展名称。 + +> globals_ctor 构造函数指针。在myfile扩展里,函数原形与void php_myfile_init_globals(zend_myfile_globals *myfile_globals)类似 + +> globals_dtor 析构函数指针。例如,php_myfile_init_globals(zend_myfile_globals *myfile_globals) - #注释php.ini里设置值的语句,ini变量值变回了默认值 - kentchentekiiMac-23868:inis kentchen$ php -q inis.php - Functions available in the test extension: - inis_report - Name:leon peng - Level:100 From 351c97985eaebbf27b49dd4c286d597fbfbb83c6 Mon Sep 17 00:00:00 2001 From: sunzy Date: Tue, 11 Aug 2015 16:44:27 +0800 Subject: [PATCH 15/23] Update 05.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 格式化 --- 05.md | 325 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 168 insertions(+), 157 deletions(-) diff --git a/05.md b/05.md index d582990..8353a65 100644 --- a/05.md +++ b/05.md @@ -2,178 +2,189 @@ 1,创建一个扩展 - ./ext_skel --extname=array - +```shell +./ext_skel --extname=array +``` + 2,hashTable函数说明 - - typedef struct bucket { - ulong h; /* Used for numeric indexing */ - uint nKeyLength; - void *pData; - void *pDataPtr; - struct bucket *pListNext; - struct bucket *pListLast; - struct bucket *pNext; - struct bucket *pLast; - const char *arKey; - } Bucket; - - typedef struct _hashtable { - uint nTableSize; - uint nTableMask; - uint nNumOfElements; - ulong nNextFreeElement; - Bucket *pInternalPointer; /* Used for element traversal */ - Bucket *pListHead; - Bucket *pListTail; - Bucket **arBuckets; - dtor_func_t pDestructor; - zend_bool persistent; - unsigned char nApplyCount; - zend_bool bApplyProtection; - #if ZEND_DEBUG - int inconsistent; - #endif - } HashTable; - - typedef Bucket* HashPosition; - - - //初始化HashTable - HashTable *myht; - zval *zv; - - /* Same as myht = emalloc(sizeof(HashTable)); */ - ALLOC_HASHTABLE(myht); - - zend_hash_init(myht, 0, NULL, ZVAL_PTR_DTOR, 0); - MAKE_STD_ZVAL(zv); - ZVAL_STRING(zv, "foo", 1); - - /* In PHP: $array[42] = "foo" */ - zend_hash_index_update(myht, 42, &zv, sizeof(zval *), NULL); - zend_hash_destroy(myht); - - /* Same as efree(myht); */ - FREE_HASHTABLE(myht); +```c +typedef struct bucket { + ulong h; /* Used for numeric indexing */ + uint nKeyLength; + void *pData; + void *pDataPtr; + struct bucket *pListNext; + struct bucket *pListLast; + struct bucket *pNext; + struct bucket *pLast; + const char *arKey; +} Bucket; +typedef struct _hashtable { + uint nTableSize; + uint nTableMask; + uint nNumOfElements; + ulong nNextFreeElement; + Bucket *pInternalPointer; /* Used for element traversal */ + Bucket *pListHead; + Bucket *pListTail; + Bucket **arBuckets; + dtor_func_t pDestructor; + zend_bool persistent; + unsigned char nApplyCount; + zend_bool bApplyProtection; + #if ZEND_DEBUG + int inconsistent; + #endif +} HashTable; - HashTable *names, *options = NULL; - HashPosition pos;//此值是Bucket的指针,pos->h表示的即是当前值的index - zval **val; - zend_bool key_exist; - - //基于string key的操作函数 - - key_exist = zend_hash_exists(options, "key", sizeof("key")); //在hashtable中查找key,如果查到则返回true,只针对于"key" => "value"这样的数组 - zend_hash_find(options, "hello", sizeof("hello"), (void **)&val) == SUCCESS; //在options中查找hello,如果找到则返回SUCCESS - - char *k1 = "key1"; - zval *v1; - MAKE_STD_ZVAL(v1); - ZVAL_STRING(v1, "value1", 1); - zend_hash_add(names, k1, sizeof(k1), &v1, sizeof(zval *), NULL); //为添加hashtable添加一个新的元素, 即 "key1" => "value1" - - zend_hash_update(names, "name", sizeof("name"), &v2, sizeof(zval *), NULL);//按key更新hashtable元素的值 - - zend_hash_del(names, k1, sizeof(k1));//按key删除一个元素 - - //基于long key的操作函数 +typedef Bucket* HashPosition; + + +//初始化HashTable +HashTable *myht; +zval *zv; + +/* Same as myht = emalloc(sizeof(HashTable)); */ +ALLOC_HASHTABLE(myht); + +zend_hash_init(myht, 0, NULL, ZVAL_PTR_DTOR, 0); +MAKE_STD_ZVAL(zv); +ZVAL_STRING(zv, "foo", 1); + +/* In PHP: $array[42] = "foo" */ +zend_hash_index_update(myht, 42, &zv, sizeof(zval *), NULL); + +zend_hash_destroy(myht); + +/* Same as efree(myht); */ +FREE_HASHTABLE(myht); + + +HashTable *names, *options = NULL; +HashPosition pos;//此值是Bucket的指针,pos->h表示的即是当前值的index +zval **val; +zend_bool key_exist; + +//基于string key的操作函数 + +key_exist = zend_hash_exists(options, "key", sizeof("key")); +//在hashtable中查找key,如果查到则返回true,只针对于"key" => "value"这样的数组 +zend_hash_find(options, "hello", sizeof("hello"), (void **)&val) == SUCCESS; +//在options中查找hello,如果找到则返回SUCCESS + +char *k1 = "key1"; +zval *v1; +MAKE_STD_ZVAL(v1); +ZVAL_STRING(v1, "value1", 1); +zend_hash_add(names, k1, sizeof(k1), &v1, sizeof(zval *), NULL); //为添加hashtable添加一个新的元素, 即 "key1" => "value1" + +zend_hash_update(names, "name", sizeof("name"), &v2, sizeof(zval *), NULL);//按key更新hashtable元素的值 + +zend_hash_del(names, k1, sizeof(k1));//按key删除一个元素 - zval *v3; - MAKE_STD_ZVAL(v3); - ZVAL_STRING(v3, "value3", 1); - zend_hash_index_update(names, 0, &v3, sizeof(zval *), NULL);//按数字索引键更新HashTable元素的值 - - zval **v4; - zend_hash_index_find(names, 1, &v4); //按数字索引获取HashTable元素的值 - php_printf("v4 : "); - PHPWRITE(Z_STRVAL_PP(v4), Z_STRLEN_PP(v4)); - php_printf("\n"); +//基于long key的操作函数 - ulong idx; - idx = zend_hash_index_exists(names, 10);//按数字索引查找HashTable,如果找到返回 1, 反之则返回 0 +zval *v3; +MAKE_STD_ZVAL(v3); +ZVAL_STRING(v3, "value3", 1); +zend_hash_index_update(names, 0, &v3, sizeof(zval *), NULL);//按数字索引键更新HashTable元素的值 - zend_hash_index_del(names, 2); //按数字索引删除HashTable元素 - - - //hashTable的遍历函数 - - zend_hash_internal_pointer_reset(names); //初始化hash指针 - zend_hash_internal_pointer_reset_ex(names, &pos);//初始化hash指针,并付值给pos - - zend_hash_get_current_data(names, (void**) &val); //获取当前hash存储值,data should be cast to void**, ie: (void**) &data - zend_hash_get_current_data_ex(names, (void**) &val, &pos) == SUCCESS; //获取当前hash存储值 - - zend_hash_get_current_key(names, &key, &klen, &index, 0) == HASH_KEY_IS_LONG - zend_hash_get_current_key_ex(names, &key, &klen, &index, 0, &pos) == HASH_KEY_IS_LONG; //读取hashtable当前的KEY,返回值会有两种 HASH_KEY_IS_LONG | HASH_KEY_IS_STRING ,分别对应array("value"),array("key"=>"value")两种hashtable - - zend_hash_move_forward(names); - zend_hash_move_forward_ex(names, &pos); //hash指针移至下一位 +zval **v4; +zend_hash_index_find(names, 1, &v4); //按数字索引获取HashTable元素的值 +php_printf("v4 : "); +PHPWRITE(Z_STRVAL_PP(v4), Z_STRLEN_PP(v4)); +php_printf("\n"); + +ulong idx; +idx = zend_hash_index_exists(names, 10);//按数字索引查找HashTable,如果找到返回 1, 反之则返回 0 + +zend_hash_index_del(names, 2); //按数字索引删除HashTable元素 + + +//hashTable的遍历函数 - //HashTable长度 - php_printf("%*carray(%d) {\n", depth * 2, ' ', zend_hash_num_elements(Z_ARRVAL_P(zv)) +zend_hash_internal_pointer_reset(names); //初始化hash指针 +zend_hash_internal_pointer_reset_ex(names, &pos);//初始化hash指针,并付值给pos + +zend_hash_get_current_data(names, (void**) &val); //获取当前hash存储值,data should be cast to void**, ie: (void**) &data +zend_hash_get_current_data_ex(names, (void**) &val, &pos) == SUCCESS; //获取当前hash存储值 + +zend_hash_get_current_key(names, &key, &klen, &index, 0) == HASH_KEY_IS_LONG +zend_hash_get_current_key_ex(names, &key, &klen, &index, 0, &pos) == HASH_KEY_IS_LONG; //读取hashtable当前的KEY,返回值会有两种 HASH_KEY_IS_LONG | HASH_KEY_IS_STRING ,分别对应array("value"),array("key"=>"value")两种hashtable +zend_hash_move_forward(names); +zend_hash_move_forward_ex(names, &pos); //hash指针移至下一位 + +//HashTable长度 +php_printf("%*carray(%d) {\n", depth * 2, ' ', zend_hash_num_elements(Z_ARRVAL_P(zv)) +``` 3,数组函数说明 1)Zend's API for Associative Arrays - - zval *arr; - MAKE_STD_ZVAL(arr); - - array_init(arr); //$arr = array(); - add_assoc_long(arr, "a", 10); //$arr["a"] = 10; - add_asoc_unset(arr, "a"); //unset(arr["a"]); - add_assoc_bool(arr, "b", 1); //$arr["b"] = true; - add_assoc_resource(arr, "c", 10); //$arr["c"] = $resource; - add_assoc_double(arr, "d", 2.15); //$arr["d"] = 2.15; - add_assoc_string(arr, "e", "hello", 1); //$arr["e"] = "hello";最后一个参数表示字符串值是否复制 - add_assoc_stringl(); - - zval *sub; - MAKE_STD_ZVAL(sub); - array_init(sub); - add_assoc_zval(arr, "f", sub); //$arr["f"] = $sub; - + +```c +zval *arr; +MAKE_STD_ZVAL(arr); + +array_init(arr); //$arr = array(); +add_assoc_long(arr, "a", 10); //$arr["a"] = 10; +add_asoc_unset(arr, "a"); //unset(arr["a"]); +add_assoc_bool(arr, "b", 1); //$arr["b"] = true; +add_assoc_resource(arr, "c", 10); //$arr["c"] = $resource; +add_assoc_double(arr, "d", 2.15); //$arr["d"] = 2.15; +add_assoc_string(arr, "e", "hello", 1); //$arr["e"] = "hello";最后一个参数表示字符串值是否复制 +add_assoc_stringl(); + +zval *sub; +MAKE_STD_ZVAL(sub); +array_init(sub); +add_assoc_zval(arr, "f", sub); //$arr["f"] = $sub; +``` + 2)Zend's API for Indexed Arrays, Part 1 - - zval *arr; - MAKE_STD_ZVAL(arr); - - array_init(arr); //$arr = array(); - add_index_long(arr, 1, 10); //$arr[1] = 10; - add_index_unset(arr, 1); //unset($arr[1]); - add_index_bool(arr, 2, 1); //$arr[2] = true; - add_index_resource(arr, 3, 10); //$arr[3] = $resource; - add_index_double(arr, 4, 2.15); //$arr[4] = 2.15; - add_index_string(arr, 5, "hello", 1); //$arr[5] = "hello";最后一个参数表示字符串值是否复制 - add_index_stringl(); - - zval *sub; - MAKE_STD_ZVAL(sub); - array_init(sub); - add_index_zval(arr, 6, sub); //$arr[6] = $sub; - + +```c +zval *arr; +MAKE_STD_ZVAL(arr); + +array_init(arr); //$arr = array(); +add_index_long(arr, 1, 10); //$arr[1] = 10; +add_index_unset(arr, 1); //unset($arr[1]); +add_index_bool(arr, 2, 1); //$arr[2] = true; +add_index_resource(arr, 3, 10); //$arr[3] = $resource; +add_index_double(arr, 4, 2.15); //$arr[4] = 2.15; +add_index_string(arr, 5, "hello", 1); //$arr[5] = "hello";最后一个参数表示字符串值是否复制 +add_index_stringl(); + +zval *sub; +MAKE_STD_ZVAL(sub); +array_init(sub); +add_index_zval(arr, 6, sub); //$arr[6] = $sub; +``` + 3)Zend's API for Indexed Arrays, Part 2 - - zval *arr; - MAKE_STD_ZVAL(arr); - - array_init(arr); //$arr = array(); - add_next_index_long(arr, 10); //$arr[] = 10; - add_next_index_unset(arr); //unset($arr[]); - add_next_index_bool(arr, 1); //$arr[] = true; - add_next_index_resource(arr, 10); //$arr[] = $resource; - add_next_index_double(arr, 2.15); //$arr[] = 2.15; - add_next_index_string(arr, "hello", 1); //$arr[] = "hello";最后一个参数表示字符串值是否复制 - add_next_index_stringl(); - - zval *sub; - MAKE_STD_ZVAL(sub); - array_init(sub); - add_next_index_zval(arr, sub); //$arr[] = $sub; + +```c +zval *arr; +MAKE_STD_ZVAL(arr); + +array_init(arr); //$arr = array(); +add_next_index_long(arr, 10); //$arr[] = 10; +add_next_index_unset(arr); //unset($arr[]); +add_next_index_bool(arr, 1); //$arr[] = true; +add_next_index_resource(arr, 10); //$arr[] = $resource; +add_next_index_double(arr, 2.15); //$arr[] = 2.15; +add_next_index_string(arr, "hello", 1); //$arr[] = "hello";最后一个参数表示字符串值是否复制 +add_next_index_stringl(); + +zval *sub; +MAKE_STD_ZVAL(sub); +array_init(sub); +add_next_index_zval(arr, sub); //$arr[] = $sub; +``` From 2aba7733bc6f415762a11dd419416f088922ba71 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:25:40 +0800 Subject: [PATCH 16/23] Update 001.md --- 001.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/001.md b/001.md index 86d1baa..ef527ca 100644 --- a/001.md +++ b/001.md @@ -4,7 +4,8 @@ git clone https://github.com/php/php-src.git cd php-src - ./configure --prefix=/opt/php-debug --enable-debug --enable-cli --without-pear --enable-embed + CFLAGS=-ggdb3 + ./configure --prefix=/opt/php-debug --enable-debug --enable-cli --without-pear --enable-embed --enable-phpdbg make make install mkdir /opt/php-debug/conf/ @@ -110,4 +111,4 @@ warning: Temporarily disabling breakpoints for unloaded shared library "/opt/php-debug/lib/php/extensions/debug-non-zts-20121212/hello2.so" [Inferior 1 (process 3162) exited normally] - \ No newline at end of file + From 3901b4de66d1c480855f12ee4f8891690c8f9cba Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:26:20 +0800 Subject: [PATCH 17/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e34063a..e70ca5c 100644 --- a/README.md +++ b/README.md @@ -41,5 +41,6 @@ [https://github.com/sgolemon/phptek2013](https://github.com/sgolemon/phptek2013) [http://www.walu.cc/phpbook/](http://www.walu.cc/phpbook/) +[https://wikitech.wikimedia.org/wiki/GDB_with_PHP](https://wikitech.wikimedia.org/wiki/GDB_with_PHP) From c218f1dfe42125e0af08b7556007e6301f75f23e Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:26:47 +0800 Subject: [PATCH 18/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e70ca5c..8356fde 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ [https://github.com/sgolemon/phptek2013](https://github.com/sgolemon/phptek2013) [http://www.walu.cc/phpbook/](http://www.walu.cc/phpbook/) + [https://wikitech.wikimedia.org/wiki/GDB_with_PHP](https://wikitech.wikimedia.org/wiki/GDB_with_PHP) From 323015904a91bc42a389aafcf7ce5fd30923cddf Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:28:15 +0800 Subject: [PATCH 19/23] Update 001.md --- 001.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/001.md b/001.md index ef527ca..2508fa5 100644 --- a/001.md +++ b/001.md @@ -111,4 +111,12 @@ warning: Temporarily disabling breakpoints for unloaded shared library "/opt/php-debug/lib/php/extensions/debug-non-zts-20121212/hello2.so" [Inferior 1 (process 3162) exited normally] + (gdb) define phpbt + set $ed=execute_data + while $ed + print ((zend_execute_data *)$ed)->function_state.function->common.function_name + set $ed = ((zend_execute_data *)$ed)->prev_execute_data + end + end + From 836a159c30092c2667a13184c53e4b5fd00cabf0 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:29:33 +0800 Subject: [PATCH 20/23] Update 001.md --- 001.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/001.md b/001.md index 2508fa5..8fb01bc 100644 --- a/001.md +++ b/001.md @@ -118,5 +118,17 @@ set $ed = ((zend_execute_data *)$ed)->prev_execute_data end end + (gdb) define hashkeys + set $p = (HashTable*)$arg0->pListHead + while $p + output (Bucket*)$p + echo \t + x/s (char*)(((Bucket*)$p)->arKey) + set $p = ((Bucket*)$p)->pListNext + end + end + (gdb) define bucketdata + print **(zval**)(((struct bucket *) $arg0)->pData) + end From 47cbf4b4ff3f6a8c1947ea0703e6d9721f073af1 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 27 Nov 2015 11:52:51 +0800 Subject: [PATCH 21/23] Update 001.md --- 001.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/001.md b/001.md index 8fb01bc..34154cd 100644 --- a/001.md +++ b/001.md @@ -131,4 +131,6 @@ print **(zval**)(((struct bucket *) $arg0)->pData) end + (gdb) hashkeys executor_globals.included_files + (Bucket *) 0x7ffff7fe1be0 0x7ffff7fe1c28: "/temp/echo.php" From 863f825c727d17e319d8cb537c11590d3082b15c Mon Sep 17 00:00:00 2001 From: Leon Date: Sat, 12 Dec 2015 07:35:43 +0000 Subject: [PATCH 22/23] add ZendMM --- 004.md | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 172 insertions(+) create mode 100644 004.md diff --git a/004.md b/004.md new file mode 100644 index 0000000..fe80479 --- /dev/null +++ b/004.md @@ -0,0 +1,170 @@ +# ZendMM + +1, php内存管理内置函数 + + void *emalloc(size_t size) 分配 size 字节的内存。 + void *ecalloc(size_t nmemb, size_t size) 给 nmemb 元素分配 size 字节的缓冲区并初始化为零。 + void *erealloc(void *ptr, size_t size) 修改使用 emalloc 分配的缓冲区 ptr 的大小为 size 字节。 + void efree(void *ptr) 释放 ptr 指向的缓冲区。缓冲区必须是由 emalloc 分配的。 + void *safe_emalloc(size_t nmemb, size_t size, size_t offset) + char *estrdup(const char *s) 分配一个可存放 NULL 结尾的字符串 s 的缓冲区,并将 s复制到缓冲区内。 + char *estrndup(const char *s, unsigned int length) 类似于 estrdup,但 NULL 结尾的字符串长度是已知的。 + +2,由emalloc分配的内存都是在zend_mm_heap上 + + //zend_mm_mem_handlers + typedef struct _zend_mm_mem_handlers { + const char *name; + zend_mm_storage* (*init)(void *params); + void (*dtor)(zend_mm_storage *storage); + void (*compact)(zend_mm_storage *storage); + zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size); + zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size); + void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr); + } zend_mm_mem_handlers; + + //zend_mm_segment + typedef struct _zend_mm_segment { + size_t size; + struct _zend_mm_segment *next_segment; + } zend_mm_segment; + + //zend_mm_storage结构 + struct _zend_mm_storage { + const zend_mm_mem_handlers *handlers;//zend_mm_storage方法 (ZEND_MM_MEM_MALLOC_DSC) + void *data; + }; + + //zend_mm_heap结构 + struct _zend_mm_heap { + int use_zend_alloc; + void *(*_malloc)(size_t); + void (*_free)(void*); + void *(*_realloc)(void*, size_t); + size_t free_bitmap; + size_t large_free_bitmap; + size_t block_size; + size_t compact_size; + zend_mm_segment *segments_list; + zend_mm_storage *storage; + size_t real_size; + size_t real_peak; + size_t limit; + size_t size; + size_t peak; + size_t reserve_size; + void *reserve; + int overflow; + int internal; + #if ZEND_MM_CACHE + unsigned int cached; + zend_mm_free_block *cache[ZEND_MM_NUM_BUCKETS]; + #endif + zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2]; + zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS]; + zend_mm_free_block *rest_buckets[2]; + int rest_count; + #if ZEND_MM_CACHE_STAT + struct { + int count; + int max_count; + int hit; + int miss; + } cache_stat[ZEND_MM_NUM_BUCKETS+1]; + #endif + }; + + //zend_alloc_globals结构 + typedef struct _zend_alloc_globals { + zend_mm_heap *mm_heap; + } + + //AG宏定义 + # define AG(v) TSRMG(alloc_globals_id, zend_alloc_globals *, v) + + //emalloc函数原型 + ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { + TSRMLS_FETCH(); + + if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) { + return AG(mm_heap)->_malloc(size); + } + return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + +3,ZendMM环境变量 + +USE_ZEND_ALLOC 是否使用 ZendMM 进行内存管理。 +ZEND_MM_MEM_TYPE 指定内存分配的方案,默认 malloc +ZEND_MM_COMPACT 指定压缩边界值 + +//默认ZEND_MM_MEM_TYPE初始化 + + # define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free} + + # define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free} + + # define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} + + # define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} + +4,ZendMM 流程 + + ->SAPI + ->php_module_startup (main.c 2065) + ->zend_startup() //zend引擎启动 + ->start_memory_manager(TSRMLS_C) //开始内存管理 + ->ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor) //初始化AG + + ->alloc_globals_ctor(&alloc_globals) //申请内存 + + //分配内存,读取环境变量USE_ZEND_ALLOC,如果USE_ZEND_ALLOC==0 则禁用 ZendMMApi(emalloc/efree/...) + //初始化mm_heap的代码(USE_ZEND_ALLOC != 0) + alloc_globals->mm_heap = malloc(sizeof(struct _zend_mm_heap)); + memset(alloc_globals->mm_heap, 0, sizeof(struct _zend_mm_heap)); + alloc_globals->mm_heap->use_zend_alloc = 0; + alloc_globals->mm_heap->_malloc = malloc; + alloc_globals->mm_heap->_free = free; + alloc_globals->mm_heap->_realloc = realloc; + + //初始化mm_heap的代码(USE_ZEND_ALLOC != 0), 则启用 ZendMMApi(emalloc/efree/...) + alloc_globals->mm_heap = zend_mm_startup(); + + ->zend_mm_startup() //读取内存分配方案(默认malloc) + ->zend_mm_startup_ex() //实例化zend_mm_heap分配内存 (heap = malloc(sizeof(struct _zend_mm_heap));) + + ->emalloc() //申请内存, + //zend_mm_heap->use_zend_alloc==0 调用 mm_heap->_malloc方法初始化分配内存 + //zend_mm_heap->use_zend_alloc!=0 调用 _zend_mm_alloc_int + ->_zend_mm_alloc_int() + ->ZEND_MM_STORAGE_ALLOC(segment_size) // + -> heap->storage->handlers->_alloc + + //ZEND_MM_MEM_WIN32_DSC + ->zend_mm_mem_win32_alloc() + ->HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size)//最终把内存分配到了heap->storage->data + + //ZEND_MM_MEM_MALLOC_DSC + ->zend_mm_mem_malloc_alloc() + ->return (zend_mm_segment*)malloc(size) //最终把内存分配到了 heap->segments_list + + //ZEND_MM_MEM_MMAP_ZERO_DSC + ->zend_mm_mem_mmap_zero_alloc() + ->(zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0) //通过mmap把内存影射到heap->storage + + //ZEND_MM_MEM_MMAP_ANON_DSC + ->zend_mm_mem_mmap_anon_alloc + ->(zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0) + //最终把内存分配到了 heap->segments_list + + ->alloc_globals_dtor() //释放内存 + ->shutdown_memory_manager (main.c 2410) //结束内存管理 + ->zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC) //最终调用释放内存的方法 + +5,总结 + + a) ZEND_MM_MEM_WIN32_DSC|ZEND_MM_MEM_MMAP_ZERO_DSC 内存保存到了 heap->storage + ZEND_MM_MEM_MMAP_ANON_DSC|ZEND_MM_MEM_MALLOC_DSC 内存保存到了 heap->segments_list + + b) \ No newline at end of file diff --git a/README.md b/README.md index 16ff346..a684358 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ [3,zval](./003.md) +[4, ZendMM](./004.md) + ##### 参考 [https://github.com/sgolemon/phptek2013](https://github.com/sgolemon/phptek2013) From a0969990e6f83d144e0b5a64e7b4ae7fca52b2fb Mon Sep 17 00:00:00 2001 From: Leon Date: Sat, 12 Dec 2015 10:16:39 +0000 Subject: [PATCH 23/23] add Output --- 14.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +- 2 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 14.md diff --git a/14.md b/14.md new file mode 100644 index 0000000..abc68dc --- /dev/null +++ b/14.md @@ -0,0 +1,137 @@ +# output操作 + +1,创建一个新的扩展 + + ./ext_skel --extname=output1 + +2,修改config.m4,去掉没用的注释语句 + + cd output1 + vi config.m4 + +3,编写代码 + + vi output1.c + #修改confirm_output_compiled + PHP_FUNCTION(confirm_output_compiled) + { + char *arg = NULL; + int arg_len, len; + char *strg; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { + return; + } + + FILE *fp = NULL; + long fsize; + char *buffer; + size_t result; + + fp = fopen(arg, "r"); + if (fp == NULL) { + RETURN_FALSE; + } + + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + rewind(fp); + buffer = (char *)malloc(sizeof(char) * fsize); + result = fread(buffer, 1, fsize, fp); + fclose(fp); + + //输出Content-type + char *content_type = "'Content-type: image/jpeg"; + sapi_header_line ctr = {0}; + ctr.line = content_type; + ctr.line_len = strlen(content_type); + ctr.response_code = 200; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + + //输出图像 + php_output_write(buffer, result TSRMLS_CC); + php_output_end_all(TSRMLS_C); + + + free(buffer); + + RETURN_TRUE; + } + +4,结构 + + //1, 输出header操作 + // SAPI.h + typedef struct { + char *line; //输出的内容,记得需要自已释放内存 + uint line_len; //输出内容的长度 + long response_code; //状态码 + } sapi_header_line; + + typedef enum { /* Parameter: */ + SAPI_HEADER_REPLACE, /* sapi_header_line* */ + SAPI_HEADER_ADD, /* sapi_header_line* */ + SAPI_HEADER_DELETE, /* sapi_header_line* */ + SAPI_HEADER_DELETE_ALL, /* void */ + SAPI_HEADER_SET_STATUS /* int */ + } sapi_header_op_enum; + + #调用sapi_header_op输出内容 + char *content_type = "'Content-type: image/jpeg"; + sapi_header_line ctr = {0}; + ctr.line = content_type; + ctr.line_len = strlen(content_type); + ctr.response_code = 200; + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + + //2, 输出内容操作 + //main/php_output.h + + ZEND_BEGIN_MODULE_GLOBALS(output) + int flags; + zend_stack handlers; + php_output_handler *active; + php_output_handler *running; + const char *output_start_filename; + int output_start_lineno; + ZEND_END_MODULE_GLOBALS(output) + + #define PHP_OUTPUT_IMPLICITFLUSH 0x01 + #define PHP_OUTPUT_DISABLED 0x02 //当flags=PHP_OUTPUT_DISABLED时,则会禁止输出 + #define PHP_OUTPUT_WRITTEN 0x04 + #define PHP_OUTPUT_SENT 0x08 + #define PHP_OUTPUT_ACTIVE 0x10 + #define PHP_OUTPUT_LOCKED 0x20 + + #define PHP_OUTPUT_ACTIVATED 0x100000 + //当flags=PHP_OUTPUT_ACTIVATED,会调用sapi_module.ub_write输出, 每个SAPI都有自已的实现, cli中是调用sapi_cli_single_write() + + php_output_write(); //输出,有buffer, 调用php_output_op() + php_output_write_unbuffered();//输出,没有buffer,调用PHP_OUTPUT_ACTIVATED,会调用sapi_module.ub_write + php_output_set_status(); //用于SAPI设置output.flags , + php_output_get_status(); //获取output.flags的值 + + php_output_op();// +5,宏 + + #define PHPWRITE(str, str_len) php_output_write((str), (str_len) TSRMLS_CC) + #define PHPWRITE_H(str, str_len) php_output_write_unbuffered((str), (str_len) TSRMLS_CC) + + #define PUTC(c) (php_output_write(&(c), 1 TSRMLS_CC), (c)) + #define PUTC_H(c) (php_output_write_unbuffered(&(c), 1 TSRMLS_CC), (c)) + + #define PUTS(str) do { \ + const char *__str = (str); \ + php_output_write(__str, strlen(__str) TSRMLS_CC); \ + } while (0) + #define PUTS_H(str) do { \ + const char *__str = (str); \ + php_output_write_unbuffered(__str, strlen(__str) TSRMLS_CC); \ + } while (0) + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index a684358..e33243e 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ [13,包装第三方库](./13.md) +[14,output操作](./14.md) + #### 附录 [1,gdb调试PHP扩展函数](./001.md) @@ -36,7 +38,7 @@ [3,zval](./003.md) -[4, ZendMM](./004.md) +[4,ZendMM](./004.md) ##### 参考