比如我们有一个php文件test.php如下
运行php test.php实际是什么样的呢?
主要过程如下
1、调用zend_compile_file(这其实是个函数指针,默认实现是compile_file),这个函数其实就是调用lex根据zend_language_scanner.l里的定义进行词法分析,然后调用yacc根据zend_language_parser.y里的定义生成opcode,关于opcode的内容,请参考鸟哥的博客http://www.laruence.com/ 这里其实只是完成了语法解析,必没有对这些opcode如何操作进行赋值,然后调用pass_two函数对所有生成的opcode进行赋值。具体工作都在zend_vm_set_opcode_handler中完成了,而它主要是根据事先定义zend_opcode_handlers表来进行查找。
2、接下来就是调用zend_execute(其实也是一个函数指针,默认实现是execute方法),这个方法就更简单了,一个while循环来调用每个opcode所指定的handler即可。
那么对于zend里的函数调用其实分为两种,一种是zend里定义的内置函数,一种是php里用户自定义的函数。而第二种又可以分为直接调用的,和call_user_func_xxx函数调用的。前面一种是直接以opcode的方法进行,实际的执行函数是ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER。而call_user_func_xxx是调用call_user_function_ex来实现,这两个函数实现在同小异,最后都将函数的opcode载入到EG(active_op_code)中,然后再调用zend_execute。
从这里我们可以看到,其实zend_exeucte是被嵌套了的。