php内核探索=opcode

在前面php内核探索笔记-初窥,了解到php代码执行需要进行编译->执行。在编译阶段首先进行词法分析,然后再进行语法分析,才生成用于Zend 引擎执行的opcode。究竟opcode是什么东西呢?


opcode是计算机执行指令的一部分,用于指定要执行的操作,也被称作字节码。opcode不需要显示的操作数,操作数可以是堆栈、寄存器、某块内存或I/O端口中的值。PHP构建与Zend虚拟机之上,php中opcode就是Zend虚拟机指令。php代码编译后生成一个个op,每个op都是一个zend_op结构的C变量:

struct zend_op{
 / /op的执行句柄,定义了函数的执行方式,每一种opcode字段通过算法对应一个种类的handler
 opcode_handler_t handler;

 //这三个分别是操作结果和操作数载体,根据op的功能使用这三个字段中的某个
 znode result;
 znode op1;
 znode op2;

//扩展字段,用于保存脚本实际执行时需要的其他信息
 ulong extended_value;

//op对应源文件中行号
 uint lineno;

//保存op的编号用来区分不同的op
 zend_uchar opcode;
 };


例如如下代码是在编译器遇到pr i n t语句的时候进行编译的函数:

 void zend_do_print(znode *result, const znode *arg TSRMLS_DC)
 {
    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

    opline->result.op_type = IS_TMP_VAR;
    opline->result.u.var = get_temporary_variable(CG(active_op_array));
    opline->opcode = ZEND_PRINT;<pre name="code" class="cpp">    opline->op1 = *arg;
    SET_UNUSED(opline->op2);
    *result = opline->result;
 }
 
 


这个函数新创建一条zend_op,将返回值的类型设置为临时变量( IS_TMP_VAR),并为临时变量申请空间, 随后指定opcode为ZEND_PRINT,并将传递进来的参数赋值给这条opcode的第一个操作数。这样在最终执行这条opcode的时候, Zend引擎能获取到足够的信息以便输出内容。


php编译后的opcode存放在op_array结构中。

你可能感兴趣的:(PHP,Web,内核,opcode)