深入理解PHP之源码目录结构与功能说明

深入理解PHP之源码目录结构与功能说明

说明

本文将详细讲解PHP源码目录结构以及其中各个子目录的作用,帮助读者深入理解PHP的内部结构,从而更好地学习和使用PHP。

源码目录结构

PHP源码目录结构主要分为以下几个部分:

  • build:构建PHP的脚本和辅助工具;
  • ext:PHP的扩展库;
  • main:PHP的主要源代码,包括Zend引擎、内部函数和类库等;
  • sapi:PHP的SAPI接口,用于与Web服务器等程序进行交互;
  • TSRM:线程安全相关代码;
  • Zend:Zend引擎的源代码。

以下是具体的目录结构及其功能:

├── build // 构建PHP的脚本和辅助工具
├── ext // PHP的扩展库
│   ├── bcmath
│   ├── ...
│   └── zip
├── main // PHP的主要源代码
│   ├── output.c // PHP输出相关代码,处理echo、print等输出语句
│   ├── php.h // PHP的主要头文件,定义了一些常量和类型等
│   ├── php.ini-development // PHP开发版本的配置文件
│   ├── php.ini-production // PHP生产版本的配置文件
│   ├── php.ini-production.cli // PHP使用命令行运行时生产版本的配置文件
│   ├── php.ini-recommended // 推荐的PHP配置文件
│   ├── php_stdlib.h // PHP标准库头文件
│   ├── SAPI.h // PHP的SAPI接口头文件
│   ├── sapi_server.h // PHP的Web服务器SAPI接口头文件
│   ├── sapi_cli.h // PHP的命令行SAPI接口头文件
│   ├── zend_API.h // Zend引擎的API接口头文件
│   ├── zend_compile.h // Zend编译相关头文件
│   ├── zend_execute.h // Zend执行相关头文件
│   ├── zend_hash.h // Zend哈希表头文件
│   ├── zend_ini.h // Zend配置文件读取头文件
│   ├── zend_language_parser.h // Zend语言解析器头文件
│   ├── zend_mmap.h // Zend内存映射相关头文件
│   └── zend_operators.h // Zend操作符相关头文件
├── sapi // PHP的SAPI接口,用于与Web服务器等程序进行交互
│   ├── apache2handler // Apache2 SAPI接口相关代码
│   ├── cli // 命令行SAPI接口相关代码
│   ├── fpm // PHP FastCGI进程管理器相关代码
│   ├── litespeed // LiteSpeed SAPI接口相关代码
│   ├── phpdbg // PHP调试器SAPI接口相关代码
│   └── embed // PHP嵌入其他程序的SAPI接口相关代码
├── TSRM // 线程安全相关代码
└── Zend // Zend引擎的源代码
    ├── zend_API.c // Zend引擎的API接口代码
    ├── zend_compile.c // Zend编译相关代码
    ├── zend_execute.c // Zend执行相关代码
    ├── zend_hash.c // Zend哈希表相关代码
    ├── zend_ini.c // Zend配置文件读取相关代码
    ├── zend_language_parser.c // Zend语言解析器相关代码
    ├── zend_list.c // Zend列表相关代码
    ├── zend_mmap.c // Zend内存映射相关代码
    ├── zend_operators.c // Zend操作符相关代码
    └── zend_variables.c // Zend变量相关代码

示例-1: 自定义PHP扩展

通过PHP的扩展库,我们可以为PHP添加自定义的功能。下面是一个简单的示例:自定义一个PHP函数,用于计算斐波那契数列:

  1. 首先在ext目录下创建一个新的目录,命名为fibonacci,并创建config.m4文件:
PHP_ARG_ENABLE(fibonacci, whether to enable Fibonacci function,
[ --enable-fibonacci
   Enable Fibonacci support])

if test $PHP_FIBONACCI != "no"; then
  PHP_SUBST(FIBONACCI_SHARED_LIBADD)
  PHP_NEW_EXTENSION(fibonacci, fibonacci.c, $ext_shared)
fi
  1. 创建fibonacci.c文件,写入以下代码:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

PHP_FUNCTION(fibonacci)
{
    long n, i, t1 = 0, t2 = 1, next_term;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &n) == FAILURE) {
        return;
    }

    for (i = 0; i < n; i++) {
        if (i <= 1) {
            next_term = i;
        } else {
            next_term = t1 + t2;
            t1 = t2;
            t2 = next_term;
        }
    }

    RETURN_LONG(next_term);
}

static zend_function_entry fibonacci_functions[] = {
    PHP_FE(fibonacci, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry fibonacci_module_entry = {
    STANDARD_MODULE_HEADER,
    "fibonacci",
    fibonacci_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    "1.0",
    STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(fibonacci)
  1. 在PHP源码根目录执行以下命令进行编译:
./buildconf
./configure --enable-fibonacci
make
sudo make install
  1. 在PHP中调用该函数:
echo fibonacci(10); // 输出55

示例-2: 自定义PHP SAPI接口

通过PHP的SAPI接口,我们可以自定义PHP与Web服务器等程序的交互方式。下面是一个简单的示例:自定义一个PHP SAPI接口,以HTTP GET方式获取参数并输出Hello, xxx!:

  1. 在sapi目录下创建一个新的目录,命名为custom,并创建Makefile.frag文件:
SAPI =        $(top_builddir)/sapi/custom/php
CC =          gcc
CFLAGS =      -I. -I$(top_srcdir)/Zend -I$(top_srcdir)/main \
              -I$(top_srcdir)/sapi -I$(top_srcdir) \
              $(EXTRA_INCLUDES)
LDFLAGS =     -export-dynamic $(EXTRA_LDFLAGS)
EXTRA_INCLUDES =
EXTRA_LDFLAGS =
OBJS =        custom.o \
              $(top_builddir)/Zend/zend_alloc.o \
              $(top_builddir)/Zend/zend_buildenv.o \
              $(top_builddir)/Zend/zend_builtin_functions.o \
              $(top_builddir)/Zend/zend_execute.o \
              $(top_builddir)/Zend/zend_globals.o \
              $(top_builddir)/Zend/zend_hash.o \
              $(top_builddir)/Zend/zend_indent.o \
              $(top_builddir)/Zend/zend_language_parser.o \
              $(top_builddir)/Zend/zend_list.o \
              $(top_builddir)/Zend/zend_opcode.o \
              $(top_builddir)/Zend/zend_operators.o \
              $(top_builddir)/Zend/zend_ptr_stack.o \
              $(top_builddir)/Zend/zend_stack.o \
              $(top_builddir)/Zend/zend_variables.o \
              $(top_builddir)/main/php_open_temporary_file.o \
              $(top_builddir)/main/php_logos.o

all: $(SAPI)

$(SAPI): $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $(OBJS)

clean:
        rm -f $(SAPI) $(OBJS)
  1. 创建custom.c文件,写入以下代码:
#include "php.h"
#include "SAPI.h"
#include "zend_API.h"

static sapi_module_struct custom_module = {
    "custom",                 // name
    "Custom PHP Module",      // pretty name
    php_uname('s'),           // php.sapi_name
    NULL,                     // startup
    NULL,                     // shutdown
    NULL,                     // activate
    NULL,                     // deactivate
    NULL,                     // message_handler
    NULL,                     // phpinfo
    "1.0",                    // version
    NULL,                     // globals_ctor
    NULL,                     // globals_dtor
    NULL,                     // post_startup
    NULL,                     // child_terminate
    STANDARD_SAPI_MODULE_PROPERTIES
};

static PHP_FUNCTION(hello)
{
    char *name;
    size_t name_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
        return;
    }

    php_printf("Hello, %s!", name);
}

static zend_function_entry custom_functions[] = {
    PHP_FE(hello, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry custom_module_entry = {
    STANDARD_MODULE_HEADER,
    "custom",
    custom_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    "1.0",
    STANDARD_MODULE_PROPERTIES
};

void _custom_module_startup(sapi_module_struct *sapi_module)
{
    sapi_module->php_ini_path_override = NULL;
}

static int custom_module_startup(sapi_module_struct *sapi_module)
{
    _custom_module_startup(sapi_module);
    return zend_startup_module(&custom_module_entry);
}

#ifdef COMPILE_DL_CUSTOM
ZEND_GET_MODULE(custom)
#endif

int main(int argc, char *argv[])
{
    sapi_startup(&custom_module);
    if (php_module_startup(&custom_module, NULL, 0) == FAILURE) {
        return 1;
    }
    php_output_activate(NULL, NULL);
    PHP_EMBED_MAIN_BEGIN();
    php_printf("Content-type: text/html\r\n\r\n");
    zend_execute_scripts(ZEND_REQUIRE, NULL, 1, "hello.php");
    PHP_EMBED_MAIN_END();
    return 0;
}
  1. 在PHP源码根目录执行以下命令进行编译:
cd sapi/custom
make
  1. 在sapi目录创建custom_server.php文件,写入以下代码:
<?php
$request_uri = $_SERVER['REQUEST_URI'];
parse_str(parse_url($request_uri, PHP_URL_QUERY), $params);
$name = $params['name'] ?? 'World';
echo hello($name);
  1. 进入PHP源码目录,执行以下命令启动自定义SAPI服务:
sapi/custom/php -S localhost:8000 -t sapi/custom sapi/custom_server.php
  1. 在浏览器访问http://localhost:8000/?name=PHP,可以看到输出Hello, PHP!。

总结

通过以上两个示例,我们可以了解PHP源码的目录结构和各个子目录的作用,并了解如何利用PHP扩展库和SAPI接口进行自定义开发。同时也可以为读者带来更好的学习和使用PHP的体验。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解PHP之源码目录结构与功能说明 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • PHP实现加密的几种方式介绍

    PHP实现加密的几种方式介绍 在Web应用程序中,数据的安全性一直是非常重要的问题。为了确保数据的安全性,很多应用程序都会使用加密技术来保护数据。PHP提供了多种加密技术,本文将介绍几种常用的加密方式以及它们的用途和示例。 哈希算法加密 哈希算法是将任意长度的消息压缩成固定长度的一段代码的函数。这个函数可以将任意长度的消息计算为一个短而且固定的长度,称之为哈…

    PHP 2023年5月23日
    00
  • php计算多个集合的笛卡尔积实例详解

    PHP计算多个集合的笛卡尔积实例详解 什么是笛卡尔积 笛卡尔积,又称直积,是在数学中用于组合两个集合的方法。笛卡尔积的结果是一个新的集合,该集合中的每个元素都是由两个原始集合中的一个元素组成的有序对。 举一个简单的例子:假设有两个集合,分别为A={a,b,c}和B={x,y},则A和B的笛卡尔积为: A × B = {(a,x),(a,y),(b,x),(b…

    PHP 2023年5月26日
    00
  • php常量详细解析

    下面我来详细讲解“PHP常量详细解析”的完整攻略。 什么是PHP常量 在编程中,常量是不变的量,即一旦定义就无法修改。在PHP中,常量是指一个简单值的标识符。常量一旦被定义,就无法再次修改或撤销。 如何定义常量 在PHP中,常量有两种定义方式:常量名和常量值大小写敏感和不敏感的定义方式,如下所示: 1. 定义常量名和常量值(大小写敏感) define(&qu…

    PHP 2023年5月23日
    00
  • PHP如何编写易读的代码

    关于如何编写易读的PHP代码,我提供如下攻略: 1. 使用有意义的变量名和函数名 变量和函数名应该能够描述它们在代码中的作用,可以使用有意义而明确的名称。更具体地说,变量名应该以小写字母开始,并且可以使用下划线来分割单词。函数名则可以以大写字母开始,也可以使用下划线来分割单词。以下是一些示例: // 有意义的变量名 $user_id = 123; $user…

    PHP 2023年5月23日
    00
  • PHP实现远程下载文件到本地

    下面是PHP实现远程下载文件到本地的完整攻略: 一、准备工作 在开始编写代码之前,我们需要安装PHP和相关扩展。本示例中我们需要用到的是curl扩展,可以使用以下命令进行安装: sudo apt-get install php-curl 二、实现远程下载文件到本地 实现远程下载文件到本地可以分为以下几个步骤: 1. 初始化curl 使用curl库实现远程下载…

    PHP 2023年5月23日
    00
  • PHP的HTTP客户端Guzzle简单使用方法分析

    PHP的HTTP客户端Guzzle简单使用方法分析 Guzzle是一个流行的PHP HTTP客户端库。它使用简单,强大,灵活,且能够很好的支持业务需求。在本文中,我们将介绍如何在PHP应用程序中使用Guzzle。 安装 使用Composer包管理器安装。在项目根目录下运行以下命令: composer require guzzlehttp/guzzle 基本用…

    PHP 2023年5月26日
    00
  • PHP中Socket连接及读写数据超时问题分析

    PHP中Socket连接及读写数据超时问题分析 什么是Socket Socket(套接字)是在应用层和传输层之间的一个抽象层,应用程序通过Socket与操作系统内核交互,使用TCP/IP协议进行网络通信。在PHP中,使用Socket可以轻松实现服务器和客户端的通信。 Socket连接超时问题分析 在PHP中,Socket连接可能会因为各种原因超时,比如网络不…

    PHP 2023年5月26日
    00
  • php发送get、post请求的6种方法简明总结

    PHP发送GET、POST请求的6种方法简明总结 在PHP中发送HTTP请求是比较常见的需求,本文将总结6种常用的方式,包括使用cURL和不使用cURL的方法。 1. 使用file_get_contents函数发送GET请求 file_get_contents函数可以读取文件内容,也可以用于发送GET请求。下面是一个例子: $url = ‘https://w…

    PHP 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部