1. 扩展开发

1.1. 什么是扩展开发

扩展是 PHP 的重要组成部分, 是 PHP 提供给开发者用于扩展 PHP 语言功能的主要方式. 开发者可以用 C/C++定义自己的功能, 然后嵌入到 PHP 中

1.2. 扩展可以做到什么

  • 介入 PHP 的编译,执行阶段: 可以介入 PHP 框架执行的那五个阶段, 比如 opcache,就是重新定义了编译函数
  • 提供内部函数: 可以定义内部函数扩充 PHP 的函数功能, 比如 array, date 等操作
  • 提供内部类
  • 实现 RPC 客户端: 实现与外部服务器的交互, 比如 redis, mysql 等
  • 提升执行性能: PHP 是解析型语言,在性能方面远不及 C 语言,可以将耗 CPU 的操作以 C 语言代替

PHP 中的扩展分为两类: PHP 扩展, Zend 扩展, 对内核而言, 这两个分别为: 模块(module), 扩展(extension)

1.3. 扩展的实现原理

通过 zend_module_entry 这个结构表示, 这个结构定义了扩展的全部信息: 扩展名, 扩展版本, 扩展提供的函数列表, 以及 PHP 四个执行阶段 hook 函数等.

  • zend_module_entry
    • size
    • zend_api
    • zend_debug 是否开启 debug
    • zts 是否开启线程安全
    • *name 扩展名称, 不能重复
    • _zend_function_entry *functions 扩展提供的内部函数列表
    • module_startup_func 扩展初始化回调函数
    • module_shutdown_func 扩展关闭时回调函数
    • request_startup_func 请求开始前回调函数
    • request_shutdown_func 请求结束前回调函数
    • info_func php_info()函数时调用,用于展示一些配置、运行信息
    • version 扩展版本
    • type
    • handle
    • module_number 扩展的唯一编号

1.4. 扩展的开发流程

1.4.1. 编译工具

  • ext_skel: ext 目录下, 用来生成扩展的基本骨架
  • phpize: 操作复杂的autoconf/automake/autoheader/autolocal等命令,生成 configure 文件
  • php-config: 主要是获取 PHP 的安装信息的
    • PHP 安装路径
    • PHP 版本
    • PHP 源码的头文件目录
    • LDFLAGS: 外部库路径
    • 依赖的外部库: 告诉编译器要链接到哪些文件
    • 扩展存放的目录
    • 编译的 SAPI
    • PHP 编译参数

1.4.2. 编写扩展流程

  • 通过 ext 目录下ext_skel脚本生成扩展的基本框架: ./ext_skel --extname
  • 修改config.m4配置: 设置编译配置参数, 设置扩展的源文件,依赖库/函数检查等等.
  • 编写扩展要实现的功能: 按照 PHP 扩展的格式以及 PHP 提供的 API 编写功能
  • 生成 configure: 扩展写完以后执行 phpize 脚本生成 configure 及其它配置文件
  • 编译&安装: ./configure, make, make install, 然后将扩展的.so 路径添加到 php.ini 中

1.5. 扩展的运行流程

  • dlopen()打开 so 库文件
  • dlsym()获取动态库中get_module()函数的地址,get_module()是每个扩展都必须提供的一个接口,用于返回扩展zend_module_entry结构的地址
  • 调用get_module(), 获取扩展的 zend_module_entry结构
  • zend api 版本检查, 比如 php7 扩展无法在 php5 上使用
  • 注册扩展, 将扩展添加到module_registry中,这是一个全局 HashTable,用于全部扩展的zend_module_module结构.
  • 如果扩展提供了内部函数则将这些函数注册到 EG(function_table)中

results matching ""

    No results matching ""