PHP底层未完待续

来源:互联网 发布:网页服务器软件 编辑:程序博客网 时间:2024/06/07 07:21

PHP源码目录

  • 根目录: / 这个目录包含的东西比较多,主要包含一些说明文件以及设计方案。 其实项目中的这些README文件是非常值得阅读的例如:
    /README.PHP4-TO-PHP5-THIN-CHANGES 这个文件就详细列举了PHP4和PHP5的一些差异。
    还有有一个比较重要的文件/CODING_STANDARDS,如果要想写PHP扩展的话,这个文件一定要阅读一下, 不管你个人的代码风格是什么样,怎么样使用缩进和花括号,既然来到了这样一个团体里就应该去适应这样的规范,这样在阅读代码或者别人阅读你的 代码是都会更轻松。
  • build 顾名思义,这里主要放置一些和源码编译相关的一些文件,比如开始构建之前的buildconf脚本等文件,还有一些检查环境的脚本等。
  • ext 官方扩展目录,包括了绝大多数PHP的函数的定义和实现,如array系列,pdo系列,spl系列等函数的实现,都在这个目录中。个人写的扩展在测试时也可以放到这个目录,方便测试和调试。
  • main 这里存放的就是PHP最为核心的文件了,主要实现PHP的基本设施,这里和Zend引擎不一样,Zend引擎主要实现语言最核心的语言运行环境。
    Zend Zend引擎的实现目录,比如脚本的词法语法解析,opcode的执行以及扩展机制的实现等等。
  • pear “PHP 扩展与应用仓库”,包含PEAR的核心文件。
  • sapi 包含了各种服务器抽象层的代码,例如apache的mod_php,cgi,fastcgi以及fpm等等接口。
  • TSRM PHP的线程安全是构建在TSRM库之上的,PHP实现中常见的*G宏通常是对TSRM的封装,TSRM(Thread Safe Resource Manager)线程安全资源管理器。
  • tests PHP的测试脚本集合,包含PHP各项功能的测试文件
  • win32 这个目录主要包括Windows平台相关的一些实现,比如sokcet的实现在Windows下和*Nix平台就不太一样,同时也包括了Windows下编译PHP相关的脚本。

PHP执行步骤

从宏观上来看,PHP内核的实现与世界上绝大多数的程序一样,接收输入数据, 做相应处理然后输出(返回)结果。 我们编写的代码就是PHP接收的输入数据,PHP内核对我们编写的代码进行解释和运算, 最后返回相应的运算结果。 然而,PHP与我们自己平时写的一般的C程序有所不同的是, 我们的程序一般用来解决某个具体问题, 而PHP本身实现了把用户的逻辑“翻译”为机器语言来执行的功能, 这也是各种编译语言与承载具体业务逻辑的程序代码的一个明显区别。 于是PHP就多出一个把用户代码“翻译”成具体操作的步骤:词法分析、语法分析

当用户代码输入给PHP内核去执行的时候, PHP内核会对PHP代码进行词法分析和语法分析, 词法分析是把PHP代码分割成一个个的“单元”(TOKEN), 语法分析则将这些“单元”转化为Zend Engine可执行的操作。 然后PHP内部的Zend Engine对这些操作进行顺次的执行。 Zend Engine是PHP内核的核心部分,负责最终操作的执行和结果的返回, 可以理解成为PHP内核中的“发动机”。

程序的执行

  1. 传递给php程序需要执行的文件, php程序完成基本的准备工作后启动PHP及Zend引擎, 加载注册的扩展模块。
  2. 初始化完成后读取脚本文件,Zend引擎对脚本文件进行词法分析,语法分析。然后编译成opcode执行。 如果安装了apc之类的opcode缓存, 编译环节可能会被跳过而直接从缓存中读取opcode执行。

脚本的编译执行

  1. PHP在读取到脚本文件后首先对代码进行词法分析,PHP的词法分析器是通过lex生成的, 词法规则文件在$PHP_SRC/Zend/zend_language_scanner.l, 这一阶段lex会会将源代码按照词法规则切分一个一个的标记(token)。PHP中提供了一个函数token_get_all(), 该函数接收一个字符串参数, 返回一个按照词法规则切分好的数组。

  2. 这也是Zend引擎词法分析做的事情,将代码切分为一个个的标记,然后使用语法分析器(PHP使用bison生成语法分析器, 规则见$PHP_SRC/Zend/zend_language_parser.y), bison根据规则进行相应的处理, 如果代码找不到匹配的规则,也就是语法错误时Zend引擎会停止,并输出错误信息。 比如缺少括号,或者不符合语法规则的情况都会在这个环节检查。 在匹配到相应的语法规则后,Zend引擎还会进行编译, 将代码编译为opcode, 完成后,Zend引擎会执行这些opcode, 在执行opcode的过程中还有可能会继续重复进行编译-执行, 例如执行eval,include/require等语句, 因为这些语句还会包含或者执行其他文件或者字符串中的脚本。

如果想直接查看生成的Opcode,可以使用php的vld扩展查看