Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Internal php and gdb php core

2,592 views

Published on

  • Be the first to comment

Internal php and gdb php core

  1. 1. Internal PHP and gdb php core alpha.1986@gmail.com
  2. 2. Agenda • Overview • PHP lifecycle • Zend Engine 2 & PHP Opcodes • PHP 变量 • PHP 函数 • PHP OO • Some Details • PHP extensions • gdb php core
  3. 3. Overview
  4. 4. Overview • Php 5.2.x – Zend Engine 2.0 • OO的改进
  5. 5. Overview – 代码结构 • main – php的核心文件以及基础设施 • Zend – Zend engine2 – 词法语法分析,虚拟机,所有与”php”相关的 • ext – 扩展目录 • sapi – 服务器抽象层(mod_php,fastcgi,etc) • TSRM – 线程安全相关
  6. 6. PHP lifecycle - CLI
  7. 7. PHP lifecycle – Apache Multiprocess Individual process life cycle
  8. 8. PHP lifecycle – Apache Multiprocess Multiprocess life cycles
  9. 9. PHP lifecycle – 扩展 • PHP_MINIT_FUNCTION(mysqli); • PHP_MSHUTDOWN_FUNCTION(mysqli); • PHP_RINIT_FUNCTION(mysqli); • PHP_RSHUTDOWN_FUNCTION(mysqli);
  10. 10. PHP lifecycle – execute PHP • Lexical Analysis • Syntax Analysis • Opcodes Generation • Opcodes Execution
  11. 11. PHP lifecycle – PHP Execution *.php lex Exprs yacc opcodes Zend vm zend_language_scanner.l zend_language_parser.y eAccelerator(eacc) eaccelerator.c, PHP_MINIT_FUNCTION(eaccele rator)
  12. 12. PHP lifecycle – tokens zend_language_scanner.l 中有所有token的定义,php的token_get_all函数可以获得 一段php代码的token
  13. 13. Opcodes zend_op_array Zend Engine 2 & PHP Opcodes php_execute_scrip t() zend_execute_scripts() zend_execute() user call (function/method) 包括定义在php中的函数和扩展里的函数 include/require zend_compile_file() 函数指针 Zend engine 整体流程
  14. 14. Zend Engine 2 - execute_scripts • PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) (main/main.c) • ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) (Zend/zend.c) • php_execute_script把auto_prepend_file, primary_file,auto_prepend_file这三个文件 传给zend_execute_scripts
  15. 15. Zend Engine 2 - zend_compile_file • Zend/zend.c zend_startup • 默认指向compile_file() in zend_language_scanner.c • ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) • Lexical Analysis -> Syntax Analysis -> Opcodes Generation
  16. 16. PHP Opcodes <?php echo "hello world!"; 通过vld扩展可以查看opcode,space@bb-space-test000 /home/space/php5/bin/php -dvld.active=1 test3.php
  17. 17. PHP Opcodes <?php function testHello(){ return "hello world"; } echo testHello();
  18. 18. PHP Opcodes struct _zend_op { opcode_handler_t handler; //每一个opcode对应的回调 znode result; znode op1; znode op2; ulong extended_value; uint lineno; zend_uchar opcode; // opcode值 }; typedef int (*opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); typedef unsigned char zend_uchar; //zend_compile.h( _zend_op_array 也在这里)
  19. 19. PHP Opcodes • Opcodes由zend_execute来执行 • 默认情况,zend_execute指向zend_vm_execute.h 的 ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) • 每个opcode的回调都存在全局变量zend_opcode_handlers 中,初始化在zend_init_opcodes_handlers() • 回调命名规则 ZEND_[opcode]_SPEC_(变量类型1)_(变量类型2)_HANDLER
  20. 20. PHP 变量 • 弱类型 typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; //zend.h typedef struct _zval_struct zval; struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount; zend_uchar type; /* active type */ zend_uchar is_ref; };
  21. 21. PHP 变量 - type /* data types */ // zval.type /* All data types <= IS_BOOL have their constructor/destructors skipped */ #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
  22. 22. PHP 变量 - HashTable • 整个zend engine最核心的数据结构 • 不仅仅是php中的array,ze中大量采用 HashTable来实现自己的逻辑,比如OO的逻辑, 全局大变量等等 • zend_hash.h
  23. 23. PHP 函数 <?php fcrypt_hstr_2id("space","aaaa"); strstr("abcde","abc"); echo "done"; PHP中的user_function和扩展中的函数都是DO_FCALL指令,echo是指令不是函数
  24. 24. PHP 函数 • DO_FCALL最终调到 static int zend_do_fcall_common_helper_SPEC(ZEND_OPCOD E_HANDLER_ARGS) // zend_vm_execute.h
  25. 25. zend_do_fcall_common_helper_SPEC
  26. 26. PHP 函数 • 两种类型函数 – User function(写在php代码中的函数) – Internal function(扩展中的函数) • Php代码的函数栈会在zend vm中也体现出 来! – 就是zend_do_fcall_common_helper_SPEC形成的 栈(还包括execute,zend_execute_internal等) • abc
  27. 27. PHP 函数 – 函数类型 #define ZEND_INTERNAL_FUNCTION 1 #define ZEND_USER_FUNCTION 2 #define ZEND_OVERLOADED_FUNCTION 3 #define ZEND_EVAL_CODE 4 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY typedef union _zend_function { zend_uchar type; /* MUST be the first element of this struct! */ struct { zend_uchar type; /* never used */ char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; } common; zend_op_array op_array; zend_internal_function internal_function; } zend_function;
  28. 28. PHP OO struct _zend_class_entry { char type; char *name; zend_uint name_length; struct _*parent; int refcozend_class_entry unt; HashTable function_table; HashTable default_properties; HashTable properties_info; HashTable default_static_members; 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 *serialize_func; union _zend_function *unserialize_func; ……..
  29. 29. Some Details • 大量的宏 – # define EG(v) (executor_globals.v) //Zend/zend_globals_macros.h – #define EX(element) execute_data->element
  30. 30. 比较重要的全局变量 • ZEND_API zend_compiler_globals compiler_globals; • ZEND_API zend_executor_globals executor_globals; • 尤其对于executor_globals会有大量的运行时 数据
  31. 31. PHP extensions(学习hack php的一些思路) • eAccelerator • Xdebug • Xphrof
  32. 32. PHP extensions - eAccelerator • PHP_MINIT_FUNCTION(eaccelerator) 中 zend_compile_file = eaccelerator_compile_file; • eaccelerator_compile_file会首先从cache中读 opcode,没有cache才会重新生成,cache • 来实现opcode cache
  33. 33. PHP extensions - xdebug • 函数调用的性能分析 // PHP_MINIT_FUNCTION old_compile_file = zend_compile_file; zend_compile_file = xdebug_compile_file; xdebug_old_execute = zend_execute; zend_execute = xdebug_execute; xdebug_orig_header_handler = sapi_module.header_handler; sapi_module.header_handler = xdebug_header_handler; xdebug_execute做完一堆 事情后,再调回 xdebug_old_execute
  34. 34. PHP extensions - xdebug • 代码覆盖率分析 // PHP_MINIT_FUNCTION if (XG(coverage_enable)) { XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMP); XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPZ); XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPZ_EX); XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPNZ); #define XDEBUG_SET_OPCODE_OVERRIDE_COMMON(oc) zend_set_user_opcode_handler(oc, xdebug_common_override_handler);
  35. 35. PHP extensions - Xphrof • PHP_FUNCTION(xhprof_enable) 中进行 _zend_compile_file = zend_compile_file; zend_compile_file = hp_compile_file; /* Replace zend_execute with our proxy */ _zend_execute = zend_execute; zend_execute = hp_execute;
  36. 36. gdb php core 类似于下面这种,需要了解php的逻辑来排查问题的
  37. 37. gdb php core • source ~/php-5.2.10/.gdbinit 初始化一些gdb 命令(方便查询hashtable) • 如果获取当前执行在php的那个函数?
  38. 38. gdb php core – 在哪个类?
  39. 39. gdb php core – 获取php中的全局变量 • $_SERVER,$_GET,$_POST 等这些php代码中 的大变量如何获取? • executor_globals • executor_globals->symbol_table 全局的变量 在这个符号表里
  40. 40. 这次没有涉及到的 • PHP SAPI架构 • PHP HashTable细节 • PHP内存管理 • PHP ZTS & TSRM等线程安全机制 • OO的更多细节以及如何编写OO扩展 • 变量的作用域 • Zend vm更深入的分析 • 等等 • 这些内容也期待大家共同参与
  41. 41. 参考资料 • Php.net • Extending and Embedding PHP • http://www.php-internal.com/ • http://www.laruence.com/
  42. 42. Thank you!

×