PHP 7源码结构初步介绍
源码目录一定程度上反映了编码者的代码组织思路。在详细介绍源码之前,我们还有必要了解 PHP 7 源码的目录结构。
PHP 7 主要包含这些源码目录:sapi
、Zend
、main
、ext
、TSRM
,本节会简要介绍各目录构成。
sapi目录源码
sapi
目录是对输入和输出层的抽象,是 PHP 提供对外服务的规范。
PHP 程序的输入可以是来自于命令行的标准输入,也可以是来自基于 cgi/fastcgi
协议的网络请求。同理,输出可以写到命令行的标准输出,也可以作为基于 cgi/fastcgi
协议的网络响应返回给客户端。
PHP 为支持多场景交互,为不同的场景模式编写独立的程序。
例如,命令行模式对应的是二进制程序 bin/php
;内置模块的模式不需要提供二进制程序,作为普通函数供 Apache 或任意 C/C++ 程序来调用即可;CGI
模式对应的是二进制程序 bin/cgi
; FastCGI
模式对应的是二进制程序 sbin/php-fpm
。同时,对多个模式抽象出了相同的模板(源码实现为结构体 sapi_module_struct
),其定义了模式启动、关闭、激活(处理请求前)、失效(处理请求后)等多个钩子函数指针。每一个模式将这些函数指针指向自己的函数,实现不同模式之间处理输入、输出的差异化。
有了这一层,可以轻松扩展 PHP 对外服务的方式。假设需要以一种二进制协议的方式来和 PHP 交互,只需要实例化一个新的 sapi_module_struct
,并实现需要的钩子函数即可。当然,你需要在钩子函数里面关心如何根据二进制协议解析出相应的脚本文件和参数等输入/输出问题。
下面介绍几种常用的 SAPI。
-
apache2handler
: Apache 扩展,编译后生成动态链接库,配置到 Apache 下,当有http
请求到 Apache 时,根据配置会调用此动态链接库,执行 PHP 代码,完成与PHP
的交互。 -
cgi-fcgi
:编译后生成支持 CGI 协议的可执行程序,webserver
(通常为 Apache 或 Nginx)通过 CGI 协议把请求传给 CGI 进程,执行代码将结果返回给webserver
,退出进程。 -
fpm-fcgi
: fpm 全称为 FastCGI Process Manager, PHP 官方提供的FastCGI
进程管理器。以 Nginx 服务器为例,当有http
协议请求发送到 Nginx 服务器,Nginx 按照FastCGI
协议把请求交给php-fpm
进程处理。 -
cli
: Command Line Interface 的简称,PHP 的命令行交互接口。
Zend目录源码
Zend
目录是 PHP
的核心代码。我们选取其中几个比较受关注的部分简要阐述。
内存管理模块
PHP
实现了自己的内存管理器,主要操作实现在 zend_alloc_sizes.h
、zend_alloc.h
、zend_alloc.c
三个文件中。
-
zend_alloc_sizes.h
:PHP 的内存管理器也实行分级管理,即分配策略按照需要的大小共有三种规格,分配时会根据实际需要空间选择对齐,再进行分配。规格分级从小到大分别称为small
、large
和huge
。该文件便定义了 PHP 内存分配的基本单位。这里简要说明下三种规格。-
small
内存小于 3072B。当 PHP 申请的内存小于 3072 字节,使用small
分配策略; -
large
内存介于 3072B 和 4KB 之间; -
huge
内存大于 2MB。
-
-
zend_alloc.h
:主要是一些内存操作函数的声明。PHP 内存管理器在 C 语言常见内存操作函数malloc()
、free()
等之上做了一层封装。 -
zend_alloc.c
:定义了内存操作函数的实现以及 PHP 内存管理器的核心数据结构_zend_mm_heap
等。本书第 9 章会重点介绍 PHP 内存管理器的实现。
本书第 9 章会重点介绍 PHP 内存管理器的实现。
main目录源码
main
目录是 SAPI
层和 Zend
层的黏合剂。
Zend
层实现了 PHP
脚本的编译和执行,sapi
层实现了输入和输出的抽象,main
目录则起到了承上启下的作用:承上,解析 SAPI
的请求,分析要执行的脚本文件和参数;启下,调用 Zend
引擎之前,完成必要的初始化等工作。如模块初始化—— php_module_startup()
。上文 SAPI
目录提到的模式启动的钩子函数都会调用这个 API
,再如脚本执行—— php_execute_script()
,它是执行 PHP
脚本的通用入口,可以在 main
目录中找到。
TSRM目录源码
PHP 在早期更多的是单个进程、单线程模型运行的,在后期才引入了线程安全机制 ZTS(Zend Thread Safety)
。TSRM
正是在这样的场景之下诞生的。
TSRM
是 Thread Safe Resource Manager 的缩写——线程安全资源管理器。不同于本章其他小节在 PHP
应用开发中的广泛涉及与实践,PHP
多线程实际开发场景要少得多。PHP
提供了条件编译选项—— enable-maintainer-zts
,以激活定义 ZTS
常量,支持线程安全。
线程安全机制主要为了保证共享资源的安全。PHP 的线程安全机制简洁直观——在多线程环境下,为每个线程提供独立的全局变量副本。具体实施是通过 TSRM
为每个线程分配(分配前加锁)一个独立 ID
(自增)作为当前线程的全局变量内存区索引,在以后的全局变量访问中,实现线程之间的完全独立。
netware 目录源码
在 PHP 源码中,netware
一般是指针对 NetWare 操作系统的支持。NetWare 是 Novell 开发的一种网络操作系统,主要用于文件和打印服务。PHP 中的 NetWare 相关代码和功能主要用于在这种操作系统上运行 PHP 脚本。
具体来说,netware
相关代码可能涉及以下几个方面:
-
系统调用和环境:处理 NetWare 系统特有的系统调用和环境变量。
-
文件系统:处理 NetWare 特有的文件系统操作,例如路径处理、文件权限等。
-
网络通信:处理 NetWare 的网络通信协议和接口。
-
编译和配置:在编译 PHP 源代码时,根据目标操作系统是 NetWare,调整编译选项和配置。
PHP 中可能会有一些条件编译的代码,例如:
#ifdef NETWARE
// NetWare 特定的代码
#endif
这种代码块会在编译时根据是否定义了 NETWARE
这个宏来决定是否包含其中的代码。
总的来说,netware
相关的代码和功能是为了确保 PHP 能在 NetWare 操作系统上正常运行,并且能够利用该操作系统的特性。
scripts 目录源码
在 PHP 源代码中,scripts
目录通常包含各种脚本,这些脚本在 PHP 源代码的编译、安装、配置和测试过程中发挥重要作用。具体来说,scripts
目录可能包含以下几类脚本:
- 构建脚本
-
-
这些脚本用于编译和构建 PHP 源代码。例如,
configure
脚本用于配置编译选项,生成适用于当前系统的 Makefile。 -
典型的构建脚本有:
configure
,buildconf
,genfiles
等。
-
- 安装脚本
-
-
这些脚本用于安装 PHP 和相关扩展。它们通常在构建完成后运行,负责将编译好的二进制文件和库文件复制到适当的安装目录。
-
例如:
install-pear-nozlib.phar
用于安装 PEAR 包管理系统。
-
- 测试脚本
-
-
这些脚本用于运行 PHP 的测试套件,以确保代码的正确性和稳定性。它们可以在开发过程中运行,也可以在持续集成环境中运行。
-
例如:
run-tests.php
用于运行 PHP 的单元测试。
-
- 工具脚本
-
-
这些脚本提供各种辅助工具,用于开发和维护 PHP 代码库。例如,格式化代码、生成文档、检查代码质量等。
-
例如:
pharcmd
、phpize
等。
-
- 配置脚本
-
-
这些脚本用于生成或修改配置文件,设置 PHP 环境和选项。例如,生成
php.ini
文件,配置扩展等。 -
例如:
php-config
脚本用于提供 PHP 配置信息。
-
典型的 scripts
目录结构和内容可能如下:
php-src/
└── scripts/
├── configure
├── buildconf
├── genfiles
├── install-pear-nozlib.phar
├── run-tests.php
├── pharcmd
├── phpize
├── php-config
└── other-scripts...
这些脚本在 PHP 的开发和部署过程中扮演着重要的角色,确保代码可以正确地编译、配置、安装和运行。
win32 目录源码
在 PHP 源代码中,win32
目录通常包含与在 Windows 操作系统上构建和运行 PHP 相关的代码和文件。这个目录的主要作用是提供特定于 Windows 平台的支持,以确保 PHP 能够在 Windows 上正常编译、安装和运行。
具体来说,win32 目录的作用包括以下几个方面:
-
Windows 平台特定的实现:
-
包含用于在 Windows 上实现 PHP 功能的代码。例如,文件系统操作、网络通信、进程管理等,这些操作在 Windows 上可能与其他操作系统有所不同。
-
-
编译和构建支持:
-
包含用于在 Windows 上编译和构建 PHP 的脚本和配置文件。这些文件配置了 Windows 编译器(如 MSVC)和构建工具(如 nmake)的选项和参数。
-
例如:
buildconf.js
,config.w32
等脚本和配置文件。
-
-
Windows 特定的扩展:
-
包含一些特定于 Windows 平台的 PHP 扩展的源代码和配置。这些扩展可能利用 Windows 特有的功能或 API。
-
例如:对 COM 和 DCOM 的支持,Windows 服务等。
-
-
安装和部署脚本:
-
包含用于在 Windows 上安装和配置 PHP 的脚本和工具。这些脚本帮助用户在 Windows 系统上正确设置 PHP 环境。
-
例如:
phpize.bat
,php-config.bat
等。
-
通过这些文件和目录,PHP 源代码可以在 Windows 平台上顺利地编译和运行,同时利用 Windows 系统的特性和功能。