BiliBili 深入 PHP 内核源码学习笔记

BiliBili 深入 PHP 内核源码学习笔记

https://space.bilibili.com/592837309/channel/collectiondetail?sid=637954

学习内容

  • 0x01 变量

    弱类型: 无需事先申明, 弱类型非无类型, 底层做了转换 -> zval
    强类型: 必须先申明后使用

  • 0x02 函数

    zend_function 结构: 用户函数/内部函数
    模拟栈, 链表, call, ret

  • 0x03 类及对象

    成员属性 成员方法 类常量
    对象创建, 复制, 销毁

  • 0x04 字符串

    C 字符串 -> 字符数组
    zend_string 核心结构 柔性数组

  • 0x05 HashTable

    PHP数组实现基础
    镜面数据结构

  • 0x06 GC

    引用技术/写时复制
    并不是所有的变量都会触发 GC

  • 0x07 静态变量

    非真正的静态变量, 而是指向静态变量的局部变量

  • 0x08 全局变量

    类似静态变量, 但略有不同

  • 0x09 基础语法的实现

    循环 判断(条件分支) jump系列 opcode 指令

  • 0x10 扩展开发

    PHP 模块, ZEND 扩展加载 运行原理
    opcache 扩展源码

  • 0x11 内存

    内存池 线程安全

  • 0x12 词法 语法

    re2c yacc 状态机

  • 0x13 ZVM 虚拟机

    编译 执行

PHP 生命周期

取决于具体的 SAPI 的实现: PHP-CLI 或 PHP-FPM
共同点: 都经历5个主要阶段
区别: 部分阶段执行次数不同

1
2
3
4
5
6
main()
-> php_module_startup()
-> php_request_startup() <──┐
-> php_execute_script() │ fpm 多次循环
-> php_request_shutdown() ──┘
-> php_module_shutdown()

编写个扩展感受生命周期 (php@7.1 php-cli)

/path/to/php/ext 源码的扩展目录: ext_skel 脚本, 可以初始化一个自定义扩展脚手架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
./ext_skel --extname=EXT_NAME 

Creating directory EXT_NAME
Creating basic files: config.m4 config.w32 .gitignore demo.c php_demo.h CREDITS EXPERIMENTAL tests/001.phpt demo.php [done].

To use your new extension, you will have to execute the following steps:

1. $ cd ..
2. $ vi ext/demo/config.m4
3. $ ./buildconf
4. $ ./configure --[with|enable]-demo
5. $ make
6. $ ./sapi/cli/php -f ext/demo/demo.php
7. $ vi ext/demo/demo.c
8. $ make

Repeat steps 3-6 until you are satisfied with ext/demo/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.
1
2
3
4
PHP_MINIT(demo),
PHP_MSHUTDOWN(demo),
PHP_RINIT(demo), /* Replace with NULL if there's nothing to do at request start */
PHP_RSHUTDOWN(demo), /* Replace with NULL if there's nothing to do at request end */

这里的具体操作是跟着视频流程走了一遍, 部分内容不能理解, 主要是在实现扩展的 c 文件里找到定义的生命周期的四个步骤里加了自定义的输出语句, 然后编译安装后在命令行下执行 php 脚本, 发现会输出自定义的语句, 以此来感受 php 在命令行下执行的生命周期

按照视频的教程所说, 空脚本执行后应该会输出的是:

1
2
3
4
5
$ php test.php
>> module init...
>> request init...
>> request shutdown...
>> module shutdown...

但是我实际测试发现没有输出module shutdown, 但是执行如php -iphp --version之类的命令时, 则会输出module shutdown, 挺奇怪的, 暂时不理解原因, 先在这 mark 一下…