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

More Related Content

What's hot (20)

PDF
OpenEJB - 另一個選擇
Justin Lin
 
PPT
Perl在nginx里的应用
琛琳 饶
 
PDF
Composer 套件管理
Shengyou Fan
 
PPT
Php
pukongkong
 
PDF
advanced introduction to codeigniter
Bo-Yi Wu
 
PPTX
课题一:PHP5.3、PHP5.4的特性介绍与深度挖掘
Liu Allen
 
PDF
深入淺出 Web 容器 - Tomcat 原始碼分析
Justin Lin
 
PDF
Python 于 webgame 的应用
勇浩 赖
 
PDF
現代 IT 人一定要知道的 Ansible 自動化組態技巧 Ⅱ - Roles & Windows
Chu-Siang Lai
 
PDF
學好 node.js 不可不知的事
Ben Lue
 
PPTX
JavaScript 80+ Programming and Optimization Skills
Ho Kim
 
PDF
啟動 Laravel 與環境設定
Shengyou Fan
 
PDF
Symfony簡介
Ricky Su
 
PDF
Automate with Ansible basic (3/e)
Chu-Siang Lai
 
PDF
Introduction to MVC of CodeIgniter 2.1.x
Bo-Yi Wu
 
PDF
View 與 Blade 樣板引擎
Shengyou Fan
 
PDF
Javascript autoload
jay li
 
PPTX
深入PHP内核之路
Gump Law
 
PDF
View 與 Blade 樣板引擎
Shengyou Fan
 
PDF
現代 IT 人一定要知道的 Ansible 自動化組態技巧
Chu-Siang Lai
 
OpenEJB - 另一個選擇
Justin Lin
 
Perl在nginx里的应用
琛琳 饶
 
Composer 套件管理
Shengyou Fan
 
advanced introduction to codeigniter
Bo-Yi Wu
 
课题一:PHP5.3、PHP5.4的特性介绍与深度挖掘
Liu Allen
 
深入淺出 Web 容器 - Tomcat 原始碼分析
Justin Lin
 
Python 于 webgame 的应用
勇浩 赖
 
現代 IT 人一定要知道的 Ansible 自動化組態技巧 Ⅱ - Roles & Windows
Chu-Siang Lai
 
學好 node.js 不可不知的事
Ben Lue
 
JavaScript 80+ Programming and Optimization Skills
Ho Kim
 
啟動 Laravel 與環境設定
Shengyou Fan
 
Symfony簡介
Ricky Su
 
Automate with Ansible basic (3/e)
Chu-Siang Lai
 
Introduction to MVC of CodeIgniter 2.1.x
Bo-Yi Wu
 
View 與 Blade 樣板引擎
Shengyou Fan
 
Javascript autoload
jay li
 
深入PHP内核之路
Gump Law
 
View 與 Blade 樣板引擎
Shengyou Fan
 
現代 IT 人一定要知道的 Ansible 自動化組態技巧
Chu-Siang Lai
 

Similar to Internal php and gdb php core (8)

PPT
Php extension开发
thinkinlamp
 
PDF
了解Php内核
Er Zhang
 
PDF
Php for fe
jay li
 
PDF
大话Php之性能
liqiang xu
 
PPTX
PHP and Zend Internal I - 体系结构及生命周期
ericzhangcn
 
PDF
OpenWebSchool - 02 - PHP Part I
Hung-yu Lin
 
PDF
iosdfoijehsogijlphpasjkdhiusghfripugsah;dfjkhs;kjfhi
1300672728
 
PDF
Php调试技术手册发布(1.0.0 pdf)
lookforlk
 
Php extension开发
thinkinlamp
 
了解Php内核
Er Zhang
 
Php for fe
jay li
 
大话Php之性能
liqiang xu
 
PHP and Zend Internal I - 体系结构及生命周期
ericzhangcn
 
OpenWebSchool - 02 - PHP Part I
Hung-yu Lin
 
iosdfoijehsogijlphpasjkdhiusghfripugsah;dfjkhs;kjfhi
1300672728
 
Php调试技术手册发布(1.0.0 pdf)
lookforlk
 
Ad

Internal php and gdb php core

  • 2. Agenda • Overview • PHP lifecycle • Zend Engine 2 & PHP Opcodes • PHP 变量 • PHP 函数 • PHP OO • Some Details • PHP extensions • gdb php core
  • 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 – 线程安全相关
  • 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
  • 24. PHP 函数 • DO_FCALL最终调到 static int zend_do_fcall_common_helper_SPEC(ZEND_OPCOD E_HANDLER_ARGS) // zend_vm_execute.h
  • 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;
  • 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 全局的变量 在这个符号表里
  • 41. 这次没有涉及到的 • PHP SAPI架构 • PHP HashTable细节 • PHP内存管理 • PHP ZTS & TSRM等线程安全机制 • OO的更多细节以及如何编写OO扩展 • 变量的作用域 • Zend vm更深入的分析 • 等等 • 这些内容也期待大家共同参与
  • 42. 参考资料 • Php.net • Extending and Embedding PHP • http://www.php-internal.com/ • http://www.laruence.com/