学习背景
PHP extension提供了与C交互的接口,从个人的理解上,很好的提供了一种将固化、重复、性能要求高的行为下沉的机制,处于php内核与php应用空间之间,为程序员提供了一种利用php的前提下高性能(相对)完成任务的可能性,因此在工作中使用该模式完成一些相对底层、高效的操作。同时,因为PHP是在C语言之上的封装,极大提升了易用性,导致一些底层功能无法完成(例如swoole提供的线程粒度的调度),因此也需要这样的机制,使PHPER可以实现更丰富的功能。更关键的是可以分层、解耦,保证核心功能的下沉与单独维护。
参考资料
- 《TIPI》
- 《PHP手册》
- 《php源码下载》
- 《PHP扩展开发及内核应用》—— 寸谋
- 《linux下编译安装lnmp环境》
- 《mac环境编译-找不到头文件-单独下载编译,修改Configure》
- 《mac环境编译-解决openssl相关库找不到的问题-修改Makefile》
正文
简介
对于PHP扩展程序,在进行源码编译时有两种选择:1是将其编译到PHP应用程序中;2是以.so动态链接库的方式,单独编译。由于PHP通常对应的是前端开发,需求经常变化,因此保证PHP应用体积够小,功能简单。在实际生产环境中,大多采用方法2,以便于灵活调配功能。
而扩展PHP的功能,可以通过扩展或加入第三方包。目前有几种方法:
- PECL:PHP Extension Community LibraryPHP扩展库,是使用c语言实现的PHP扩展,对语言本身外放方法。
- PEAR:the PHP Extension and Application RepositoryPHP扩展与应用库,代码由PHP实现,逐渐被composer取代。
- composer:PHP包管理工具,一般放在github、bitbucket上,使用composer管理的包,可以很轻松的利用SPL的autoload机制,将扩展的包打入自己的框架/项目。是目前比较火的PHP包管理方式。
PHP源码编译(MacOS 版本)
在开发PHP扩展前,首先要搞定环境。除了开发机以外,为了保证方便灵活,在本机(MacPro13’)上也构建一套php环境(实际上做这件事儿的意义并不算大,但是既然开始了,就必须都撸完,所以才有以下这么纠结的问题):
代码语言:txt复制 # 1.从官方镜像源下载php源码包(7.1.3 tar.gz版本)
wget http://cn2.php.net/get/php-7.1.13.tar.gz/from/this/mirror
# 2.解压
tar zxvf php-7.1.13.tar.gz
# 3.进入php工作目录,并且进行configure配置
cd ./php-7.1.13
# 4. 对源码进行config操作
# 4.1 如果是从git上拉下来的源码需要用这个命令生成configure,依赖autoconfig应用,如果本机上没有
./buildconf --force
# 4.2 编译php,这里面几个需要注意的是 1. enable-fpm 连接nginx 如果是apache就用apx 2. enable-maintainer-zts 打开线程安全(生产环境都需要这个,之前看blog有一种解释是,类多线程的调度方式需要实现ts,异步回调的方式则不需要,所以渣浪这边的ts都disable,那么编写生产环境扩展的时候,除非是特殊情况,否则还是保证ts 3. 如果是写php扩展,实际上尽量打开debug开关 --enable-debug)
./configure --prefix=/usr/local/php7 --with-config-file-path=/usr/local/php7/etc --with-config-file-scan-dir=/usr/local/php7/etc/php.d --enable-fpm --with-fpm-user=www --with-fpm-group=www --with-mysqli --with-pdo-mysql --with-iconv-dir --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --with-mcrypt --enable-ftp --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --disable-fileinfo --enable-maintainer-zts --enable-debug
# ps 由于mac环境与linux环境略有不同,在configure和make的过程中都会报错,按照参考资料中相关blog,一一处理即可(缺少头文件的,安装相关包,对configure文件和Makefile文件进行小幅修改)。主要调整configure、makefile中的相对路径保证可寻址。
# 5. configure命令运行成功后,生成Makefile,然后直接make三连击~
make
make test
make install
# 6. 为了更方便的使用生成全局的软连接,从某个版本开始mac上的/usr/bin目录的操作需要关闭mac的安全设置,所以用了另一个$PATH中的应用文件目录
ln -s /usr/local/php7/bin/php /usr/local/bin/php7
ln -s /usr/local/php7/bin/php-config /usr/local/bin/php7-config
ln -s /usr/local/php7/bin/phpize /usr/local/bin/php7ize
ln -s /usr/local/php7/sbin/php-fpm /usr/local/sbin/php7-fpm
# 7. 复制配置文件到相关位置(可以根据自己需要处理)
cp php.ini-production /usr/local/php7/etc/php.ini
cp sapi/fpm/init.d.php-fpm /etc/mach_init.d/php7-fpm
chmod x /etc/init.d/php7-fpm
cp /usr/local/php7/etc/php-fpm.conf.default /usr/local/php7/etc/php-fpm.conf
cp /usr/local/php7/etc/php-fpm.d/www.conf.default /usr/local/php7/etc/php-fpm.d/www.conf
####PHP扩展添加(MacOS 版本)
言归正传,如何将一个现有的extension源码添加入指定的PHP环境,分为以下几步(以鸟哥的taint为例):
代码语言:txt复制 #我一般都会将扩展源码整理到PHP源码下的ext目录下,当前使用的PHP版本为7.1
$git clone https://github.com/laruence/taint.git ./taint
$cd ./taint
#这一步在同时存在多个php版本的环境中尤其要注意,可以使用php -v 来确定当前版本,最好使用绝对路径处理
$<your own php bin path>/phpize
$./configure --with-php-config=<php-config path>
$./make #这里通常不选择make install,生成的.so/.la文件都在当前文件夹下的module文件中
#去php.ini所在目录并修改,可以使用php -i | grep 'ini'查看这个文件在哪儿
$vim <your own php lib path>php.ini
#如果要在fast-cgi或者php_mod模式下生效,还需要重启http服务器
$service php-fpm restart
$apachectl restart
#检查一下模块是否加载上了
$<your own php bin path>/php -m | grep taint
PHP扩展新建(MacOS 版本)
要编写自己的扩展,首先需要在项目下创建一个项目(摆姿势),php提供了非常便利的工具,找到PHP的源文件夹下,进入扩展源码所在目录ext/内,使用扩展初始化创建工具ext_skel,例如我们创建名为test的扩展,会在当前文件夹下生成一个名为test的扩展文件包的新文件夹,里面包含有一个php extension所需的所有骨架文件:
代码语言:txt复制$./ext_skel --extname=test
#程序在终端打印以下信息
Creating directory test
Creating basic files: config.m4 config.w32 .gitignore test.c php_test.h CREDITS EXPERIMENTAL tests/001.phpt test.php [done].
To use your new extension, you will have to execute the following steps:
1. $ cd ..
2. $ vi ext/test/config.m4
3. $ ./buildconf
4. $ ./configure --[with|enable]-test
5. $ make
6. $ ./sapi/cli/php -f ext/test/test.php
7. $ vi ext/test/test.c
8. $ make
生成的扩展test目录结构如下:
代码语言:txt复制$ tree
.
├── CREDITS
├── EXPERIMENTAL
├── config.m4 #unix类系统配置
├── config.w32 #windows系统配置
├── php_test.h #
├── test.c #扩展
├── test.php
└── tests
└── 001.phpt