Internal php and gdb php core

  • 1,083 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,083
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
4
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Internal PHP and gdb php core alpha.1986@gmail.com
  • 2. Agenda • Overview • PHP lifecycle • Zend Engine 2 & PHP Opcodes • PHP 变量 • PHP 函数 • PHP OO • Some Details • PHP extensions • gdb php core
  • 3. Overview
  • 4. Overview • Php 5.2.x – Zend Engine 2.0 • OO的改进
  • 5. Overview – 代码结构 • main – php的核心文件以及基础设施 • Zend – Zend engine2 – 词法语法分析,虚拟机,所有与”php”相关的 • ext – 扩展目录 • sapi – 服务器抽象层(mod_php,fastcgi,etc) • TSRM – 线程安全相关
  • 6. PHP lifecycle - CLI
  • 7. PHP lifecycle – Apache Multiprocess Individual process life cycle
  • 8. PHP lifecycle – Apache Multiprocess Multiprocess life cycles
  • 9. PHP lifecycle – 扩展 • PHP_MINIT_FUNCTION(mysqli); • PHP_MSHUTDOWN_FUNCTION(mysqli); • PHP_RINIT_FUNCTION(mysqli); • PHP_RSHUTDOWN_FUNCTION(mysqli);
  • 10. PHP lifecycle – execute PHP • Lexical Analysis • Syntax Analysis • Opcodes Generation • Opcodes Execution
  • 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. PHP lifecycle – tokens zend_language_scanner.l 中有所有token的定义,php的token_get_all函数可以获得 一段php代码的token
  • 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. 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. 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. PHP Opcodes <?php echo "hello world!"; 通过vld扩展可以查看opcode,space@bb-space-test000 /home/space/php5/bin/php -dvld.active=1 test3.php
  • 17. PHP Opcodes <?php function testHello(){ return "hello world"; } echo testHello();
  • 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. 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. 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. 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. PHP 变量 - HashTable • 整个zend engine最核心的数据结构 • 不仅仅是php中的array,ze中大量采用 HashTable来实现自己的逻辑,比如OO的逻辑, 全局大变量等等 • zend_hash.h
  • 23. PHP 函数 <?php fcrypt_hstr_2id("space","aaaa"); strstr("abcde","abc"); echo "done"; PHP中的user_function和扩展中的函数都是DO_FCALL指令,echo是指令不是函数
  • 24. PHP 函数 • DO_FCALL最终调到 static int zend_do_fcall_common_helper_SPEC(ZEND_OPCOD E_HANDLER_ARGS) // zend_vm_execute.h
  • 25. zend_do_fcall_common_helper_SPEC
  • 26. PHP 函数 • 两种类型函数 – User function(写在php代码中的函数) – Internal function(扩展中的函数) • Php代码的函数栈会在zend vm中也体现出 来! – 就是zend_do_fcall_common_helper_SPEC形成的 栈(还包括execute,zend_execute_internal等) • abc
  • 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. 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. Some Details • 大量的宏 – # define EG(v) (executor_globals.v) //Zend/zend_globals_macros.h – #define EX(element) execute_data->element
  • 30. 比较重要的全局变量 • ZEND_API zend_compiler_globals compiler_globals; • ZEND_API zend_executor_globals executor_globals; • 尤其对于executor_globals会有大量的运行时 数据
  • 31. PHP extensions(学习hack php的一些思路) • eAccelerator • Xdebug • Xphrof
  • 32. PHP extensions - eAccelerator • PHP_MINIT_FUNCTION(eaccelerator) 中 zend_compile_file = eaccelerator_compile_file; • eaccelerator_compile_file会首先从cache中读 opcode,没有cache才会重新生成,cache • 来实现opcode cache
  • 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. 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. 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. gdb php core 类似于下面这种,需要了解php的逻辑来排查问题的
  • 37. gdb php core • source ~/php-5.2.10/.gdbinit 初始化一些gdb 命令(方便查询hashtable) • 如果获取当前执行在php的那个函数?
  • 38. gdb php core – 在哪个类?
  • 39. gdb php core – 获取php中的全局变量 • $_SERVER,$_GET,$_POST 等这些php代码中 的大变量如何获取? • executor_globals • executor_globals->symbol_table 全局的变量 在这个符号表里
  • 40. 这次没有涉及到的 • PHP SAPI架构 • PHP HashTable细节 • PHP内存管理 • PHP ZTS & TSRM等线程安全机制 • OO的更多细节以及如何编写OO扩展 • 变量的作用域 • Zend vm更深入的分析 • 等等 • 这些内容也期待大家共同参与
  • 41. 参考资料 • Php.net • Extending and Embedding PHP • http://www.php-internal.com/ • http://www.laruence.com/
  • 42. Thank you!