上篇文章我们已经介绍了源码分析工具的安装、配置以及调试方法,本文我们来讲述一下PHP源码的目录结构。
一、目录概览
以php-7.0.12
为例,看过源码的同学们应该发现源码目录多达十多个,下面是每个目录的说明。
目录 | 说明 |
---|---|
TSRM | 线程相关安全的实现 |
Zend | PHP解析器的核心实现 |
build | linux下编译相关的目录 |
ext | PHP的扩展 |
main | PHP的主要代码 |
netware | 网络目录,socket的定义与实现 |
pear | PHP扩展及应用的代码仓库 |
sapi | PHP的应用层接口 |
scripts | Linux下的脚本目录 |
tests | 测试脚本目录 |
travis | 用于构建,非PHP特有目录 |
win32 | Windows下编译PHP的相关脚本 |
二、核心目录
虽然源码目录众多,但是核心目录却只有sapi、main、zend、ext、TSRM
。
2.1、SAPI
还记得PHP的应用场景吗?我们可以在命令行中访问PHP,也可以通过浏览器访问PHP脚本,甚至可以嵌入到单片机供C、C++程序调用。它们分别对应cli模式、fpm/cgi模式、embed模式,除了这些还有apache2handler、litespeed模式。
SAPI全称Server API,负责PHP对外提供服务规范,它定义了结构体sapi_module_struct
,该结构体定义了模式启动、关闭、激活、失效等多个钩子函数指针,每个模式将这些函数指针指向自己的函数,就可以轻松扩展PHP对外服务的方式。以上几种模式也正是实现了sapi_module_strcut
才完成了PHP的多场景应用。
2.2、main
main目录的作用是承接SAPI的请求,分析出要执行的脚本文件和参数,并对环境和配置进行初始化,比如初始化变量和常量、注册函数、解析配置文件、加载扩展等等。
2.3、Zend
Zend目录就是大家所熟知的Zend引擎,是PHP最核心的部分,主要负责PHP的语法实现、内存管理及脚本的编译运行环境等,它由编译器、执行器两部分组成。
编译器负责将PHP代码进行词法、语法分析,并生成抽象语法树,然后进一步编译为opcode,opcode是Zend虚拟机可识别的指令,php7一共有173个opcode,所有的语法都是由这些opcode组成的。执行器负责执行编译器输出的opcode。
2.4、ext
ext是extension的缩写,它是扩展PHP内核功能的一种方式,分为PHP扩展与zend扩展,都支持用户自定义开发,这两种都比较常见,PHP扩展有gd、json、date、array等,而我们熟知的opcache就是Zend扩展。
2.5、TSRM
TSRM全称叫做Thread Safe Resource Manager,也就是线程安全资源管理器。
我们知道,全局变量就是定义在函数外的变量,它属于公共资源,在多线程的环境下,访问公共资源就可能会引起冲突,TSRM就是为解决该问题而诞生的。它为每个线程分配一个独立的自增ID,该ID作为当前线程的全局变量内存区的索引,从而实现线程的完全独立。
其实PHP大部分SAPI都是单线程的,所以并不需要过多关注线程安全,但是在Apache或者用户自己实现的PHP环境下,就需要考虑线程安全问题了。