PHP扩展开发学习笔记之三ext_skel工具的使用 作者: lovingyu_er 时间: 2020-06-26 21:31:33 分类: php7底层设计和源码实现 评论 注意:我使用的是php-7.1.0的版本,其他的版本可能使用方式不一样,请注意参考官方的文档。 PHP的扩展开发,为了方便开发者快速构建一个PHP的扩展,PHP官方提供了构建扩展骨架的工具```ext_skel``` 这个工具是在学习PHP扩展开发的第一个需要了解的工具: 该工具在源码的ext目录下:会有一个ext_skel可执行文件。 命令: ``` ./ext_skel --extname=ext_name ``` 比如: ``` ./ext_skel --extname=myext ``` 会在ext的目录下生成一个```myext```目录,目录的内容和如下:  该命令的别的参数: ``` ./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help] //常用的一个参数:--extname 扩展的名称 --extname=module module is the name of your extension --proto=file file contains prototypes of functions to create --stubs=file generate only function stubs in file --xml generate xml documentation to be added to phpdoc-svn --skel=dir path to the skeleton directory --full-xml generate xml documentation for a self-contained extension (not yet implemented) --no-help don't try to be nice and create comments in the code and helper functions to test if the module compiled ```
PHP扩展开发学习笔记之php-config 作者: lovingyu_er 时间: 2020-06-26 20:29:00 分类: php7底层设计和源码实现 评论 这个就是PHP源码中的```script/php-config.bin``` 源文件內容如下: ``` #! /bin/sh SED="@SED@" prefix="@prefix@" datarootdir="@datarootdir@" exec_prefix="@exec_prefix@" version="@PHP_VERSION@" vernum="@PHP_VERSION_ID@" include_dir="@includedir@/php" includes="-I$include_dir -I$include_dir/main -I$include_dir/TSRM -I$include_dir/Zend -I$include_dir/ext -I$include_dir/ext/date/lib" ldflags="@PHP_LDFLAGS@" libs="@EXTRA_LIBS@" extension_dir='@EXTENSION_DIR@' man_dir=`eval echo @mandir@` program_prefix="@program_prefix@" program_suffix="@program_suffix@" exe_extension="@EXEEXT@" php_cli_binary=NONE php_cgi_binary=NONE configure_options="@CONFIGURE_OPTIONS@" php_sapis="@PHP_INSTALLED_SAPIS@" # Set php_cli_binary and php_cgi_binary if available for sapi in $php_sapis; do case $sapi in cli) php_cli_binary="@bindir@/${program_prefix}php${program_suffix}${exe_extension}" ;; cgi) php_cgi_binary="@bindir@/${program_prefix}php-cgi${program_suffix}${exe_extension}" ;; esac done # Determine which (if any) php binary is available if test "$php_cli_binary" != "NONE"; then php_binary="$php_cli_binary" else php_binary="$php_cgi_binary" fi # Remove quotes configure_options=`echo $configure_options | $SED -e "s#'##g"` case "$1" in --prefix) echo $prefix;; --includes) echo $includes;; --ldflags) echo $ldflags;; --libs) echo $libs;; --extension-dir) echo $extension_dir;; --include-dir) echo $include_dir;; --php-binary) echo $php_binary;; --php-sapis) echo $php_sapis;; --configure-options) echo $configure_options;; --man-dir) echo $man_dir;; --version) echo $version;; --vernum) echo $vernum;; *) cat << EOF Usage: $0 [OPTION] Options: --prefix [$prefix] --includes [$includes] --ldflags [$ldflags] --libs [$libs] --extension-dir [$extension_dir] --include-dir [$include_dir] --man-dir [$man_dir] --php-binary [$php_binary] --php-sapis [$php_sapis] --configure-options [$configure_options] --version [$version] --vernum [$vernum] EOF exit 1;; esac exit 0 ``` 可以看到這是一个bash脚本,PHP安装好以后,这个脚本会被移动到bin目录下,并且重名为php-config,这个脚本主要是获取PHP的安装的信息,在编译安装的时候会把下面的信息放到php-config脚本中: 1. PHP的安装的路径 2. PHP的版本 3. PHP源码的头文件目录:main,Zend,ext,TSRM中的头文件,编写扩展时会用到这些头文件,这些头文件保存在PHP安装位置/include/php目录下 4. LDFLAGS:外部库路径 5. 依赖的外部库:告诉编译器要链接哪些文件 6. 扩展存放的目录:扩展.so保存位置,安装扩展make install 时将安装到这个目录下面 7. 编译的SAPI: 比如 cli,fpm,cgi等等 8. PHP编译参数: 编译php时执行./configure时代的编译参数 上述这些信息,在PHP编译或者安装的时候,会使用到。执行编译的时候./configue --with-php-config=/path/to/php-config 生成MakeFile时,作为参数传入即可,它的作用就是提供给configure.in获取上面的几个配置生成Makefile.如果没有指定这个参数,将默认的PHP安装路径下搜索,因此,如果想在同一台机器上安装不同的php版本,在编译安装的时候,需要指定对应版本的php-config就可以了。 下面是我安裝後的文件的內容: ``` #! /bin/sh SED="/bin/sed" prefix="/home/darrykinger.com/php-7.1" datarootdir="/home/darrykinger.com/php-7.1/php" exec_prefix="${prefix}" version="7.1.0" vernum="70100" include_dir="${prefix}/include/php" includes="-I$include_dir -I$include_dir/main -I$include_dir/TSRM -I$include_dir/Zend -I$include_dir/ext -I$include_dir/ext/date/lib" ldflags="" libs="-lcrypt -lresolv -lcrypt -lrt -lrt -lm -ldl -lnsl -lxml2 -lxml2 -lxml2 -lcrypt -lxml2 -lxml2 -lxml2 -lcrypt " extension_dir='/home/darrykinger.com/php-7.1/lib/php/extensions/debug-non-zts-20160303' man_dir=`eval echo ${datarootdir}/man` program_prefix="" program_suffix="" exe_extension="" php_cli_binary=NONE php_cgi_binary=NONE configure_options=" '--prefix=/home/darrykinger.com/php-7.1/' '--enable-fpm' '--enable-debug'" php_sapis=" cli fpm phpdbg cgi" # Set php_cli_binary and php_cgi_binary if available for sapi in $php_sapis; do case $sapi in cli) php_cli_binary="${exec_prefix}/bin/${program_prefix}php${program_suffix}${exe_extension}" ;; cgi) php_cgi_binary="${exec_prefix}/bin/${program_prefix}php-cgi${program_suffix}${exe_extension}" ;; esac done # Determine which (if any) php binary is available if test "$php_cli_binary" != "NONE"; then php_binary="$php_cli_binary" else php_binary="$php_cgi_binary" fi # Remove quotes configure_options=`echo $configure_options | $SED -e "s#'##g"` case "$1" in --prefix) echo $prefix;; --includes) echo $includes;; --ldflags) echo $ldflags;; --libs) echo $libs;; --extension-dir) echo $extension_dir;; --include-dir) echo $include_dir;; --php-binary) echo $php_binary;; --php-sapis) echo $php_sapis;; --configure-options) echo $configure_options;; --man-dir) echo $man_dir;; --version) echo $version;; --vernum) echo $vernum;; *) cat << EOF Usage: $0 [OPTION] Options: --prefix [$prefix] --includes [$includes] --ldflags [$ldflags] --libs [$libs] --extension-dir [$extension_dir] --include-dir [$include_dir] --man-dir [$man_dir] --php-binary [$php_binary] --php-sapis [$php_sapis] --configure-options [$configure_options] --version [$version] --vernum [$vernum] EOF exit 1;; esac exit 0 ```
使用swoole的协程出现Co\run function找不到 作者: lovingyu_er 时间: 2020-05-26 01:21:16 分类: 编程语言,PHP,php7底层设计和源码实现,Swoole-PHP 评论 ``` PHP Fatal error: Uncaught Error: Call to undefined method Swoole\Coroutine\Server::handler() in /Users/darry/php_about/loving_code/swoole/coroutine/swoole_coroutine.php:23 Stack trace: #0 {main} thrown in /Users/darry/php_about/loving_code/swoole/coroutine/swoole_coroutine.php on line 23 Fatal error: Uncaught Error: Call to undefined method Swoole\Coroutine\Server::handler() in /Users/darry/php_about/loving_code/swoole/coroutine/swoole_coroutine.php:23 Stack trace: #0 {main} thrown in /Users/darry/php_about/loving_code/swoole/coroutine/swoole_coroutine.php on line 23 ``` 代码是tcp 的client端 ``` //Swoole\Runtime::enableCoroutine(); //此行代码后,文件操作,sleep,Mysqli,PDO,streams等都变成异步IO,见'一键协程化'章节 $s = microtime(true); $host = "127.0.0.1"; $port = '9999'; $timeout = 0.5; Swoole\Coroutine::create(function()use ($s,$host,$port,$timeout){ $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); if(!$client->connect($host,$port,$timeout)){ echo "connect failed . Error : ".$client->errCode.PHP_EOL; }else{ $client->send(date("Y-m-d H:i:s ",$s). " msg :hello world " .PHP_EOL); echo date("Y-m-d H:i:s")." Recive ms : ".$client->recv().PHP_EOL; $client->close(); } }); ``` 解决方案,swoole官方给出的建议, 1. 检查swoole的版本,swoole的协程是在4.4.0+以后才出现的,检查版本可以使用swoole函数```swoole_version()```活着使用命令行```php --ri swoole```查看返回的字符串的```Version```的提示。 2. 如果1的满足,那么查看php是否关闭swoole的短协程名称,请打开即可。 ```swoole.use_shortname=On/Off ```来```开启 / 关闭```短名,默认为```开启```,我关闭了,由于是在```php.ini```中配置, 别的项目需要将这个配置项目关闭,偶尔不考虑打开这个,直接采用第三个解决方案。 3. 使用使用 ```Coroutine::create``` 方法替换 ```Co\Run``` 或 ```go``` 来创建协程; 问题就解决了: 参考文档: 1. ```https://wiki.swoole.com/#/question/use?id=call-to-undefined-function-corun```
以编程语言:C和PHP谈汇编语言和解释型语言的差别 作者: lovingyu_er 时间: 2019-04-23 15:52:00 分类: php7底层设计和源码实现 评论 初步了解PHP7核心源码中ext、main、sapi、TSRM、Zend目录下的文件,以及各自的功能。 ###PHP7语言的执行原理 接触的高级语言有C/c++、Python、PHP、Go/Pascal等,根据其运行的原理不同,我们可以将它们归结为两种语言:编译型语言和解释型语言。 #####编译型语言: 应用程序执行之前,就将程序源代码“翻译”成汇编语言,然后进一步根据软硬件环境编译成目标文件。完成编译工作的工具叫做编译器。 下面的一段C语言代码: ```c #include int main(){ printf("hello world"); return 1; } ``` main函数是程序的入口,实现打印“hello world”的作用。经过编译和执行的过程中,其中间会经过如下的步骤: ######第一步.预处理:将依赖处理、宏替换等包括上面代码中的#include都会在此阶段被替换掉 ######第二步.编译:将C语言编译成汇编语言程序,一条C语言会通常被编译为多条汇编代码。完成对目标程序的优化。 ######第三步.汇编器再汇编,现在已经是汇编代码,通过汇编器再会变成目标程序,比如hello.o ######第四步.链接:将一些共享的目标文件,比如printf()函数(来自于静态库),通过链接器(如Unix链接器ld)进行链接。 编译型语言都会出现上述的步骤。 #####解释型语言: 在应用程序在运行的时候才被“翻译”成机械语言。但是在执行的时候才被翻译,所以相对已经“翻译”好的编译型语言相比,其执行效率会比较低。负责解释性语言的解析工作的工具叫做解释器,还是负责 下面以PHP7为例讲述解释型语言的运行过程 ######第一步.词法分析:源码通过词法分析器分析得到Token。 ######第二步.语法分析: 基于语法分析器生成抽象语法树(AST:Abstract Syntax Tree) ######第三步.转换成opcodes:将AST转换成opcodes(opcode指令集合),PHP解释执行opcode 其执行流程:[源代码]->词法分析器->[Token]->语法分析器->[AST]->抽象语法树->[(生成可执行文件:编译器执行)|(生成opcodes可以被解释器执行)]详情可参考下一章关于PHP代码在执行时候的一些详细的讲解. #######汇编语言:编译结果最终指向了针对当前CPU体系的指令; #######解释型语言:编译成中间代码,在经过该语言指定的特定虚拟机,经过虚拟机再被翻译成CPU体系的指令被执行。 两种语言的慢就慢在“**虚拟机**”的这一步骤上。