linux下php开发自定义扩展库

来源:互联网 发布:个人淘宝账号查询 编辑:程序博客网 时间:2024/05/29 16:28

php扩展开发

加上会出什么问题,不加会报什么错;所以在编译PHP的时候除了必要的目录指定,好多参数都没有加……等我在安装web程序的时候,才发现,很多参数是要加上的,但是我lnmp已经搭建好了,也不想重新编译,重新安装。。于是就在网上找到了此文一、添加FTP扩展1、找到原来的源码包解压一下如:php-5.2.13进入到到FTP的扩展目录/root/lnmp/php-5.3.0/ext/ftp2、调用phpize程序生成编译配置文件复制代码 代码如下:root@dns ftp]# /usr/local/php5/bin/phpizeConfiguring for:PHP Api Version: 20041225Zend Module Api No: 20060613Zend Extension Api No: 2200605193. 编译扩展库,分别执行下面的configure和make命令。#./configure --with-php-config=/usr/local/php5/bin/php-config#configure这一步执行通过后,再执行make命令,如果configure执行不通过,则查找错误原因。#make#make成功执行后,生成的扩展库文件在当前目录的 modules 子目录下,复制代码 代码如下:[root@Ansen ftp]# ls modules/ftp.la ftp.so4、编辑php.ini文档,创建extension_dir的目录,将编译好的扩展文件复制到extension下面将extension_dir = "./" 改成复制代码 代码如下:extension_dir = "/usr/local/php5/lib/php/extension"复制代码 代码如下:[root@Ansen modules]#cp ftp.so /usr/local/php5/lib/php/extension5、在php.ini的添加扩展库位置,设置要添加的扩展库。在989处添加 extension=ftp.so6、重启一下apache 就可以得到ftp的支持了二、添加zlib扩展复制代码 代码如下:[root@Ansen zlib]# pwd/root/lnmp/php-5.3.0/ext/zlib[root@Ansen zlib]#mv config0.m4 config.m4[root@Ansen zlib]#/usr/local/php5/bin/phpize[root@Ansen zlib]#./configure --with-php-config=/usr/local/php5/bin/php-config[root@Ansen zlib]#make[root@Ansen zlib]# cp modules/zlib.so /usr/local/php5/lib/php/extension/[root@Ansen zlib]#vi /usr/local/php5/lib/php.ini添加extension=zlib.so8、重启apache就可以了PS:其它扩展可以参考上面两种扩展的方法进行安装补充简洁版:一开始编译php的时候,忘了,现在用phpize安装扩展库进行添加找到当前运行的php版本的源代码目录,如 php-5.2.12。进入curl扩展库目录#cd /home/changyou/php-5.2.12/ext/curl(调用phpize程序生成编译配置文件)#/usr/local/web/php/bin/phpize(编译扩展库,分别执行下面的configure和make命令)#./configure –with-php-config=/usr/local/web/php/bin/php-config(configure这一步执行通过后,再执行make命令,如果configure执行不通过,则查找错误原因)#makemake成功执行后,生成的扩展库文件在当前目录的 modules 子目录下如我这里的目录是:/home/changyou/php-5.2.12/ext/curl/modules/curl.so然后配置php.ini文件,将编译好的扩展库文件复制到php的extension目录下#cp /home/changyou/php-5.2.12/ext/curl/modules/curl.so /usr/local/web/php/lib/php/extension/最后修改 php.ini 添加配置extension_dir = “/usr/local/web/php/lib/php/extension/”extension=curl.so 

如何编写PHP自定义模块和切入PHP调用linux底层的过程

希望本文能对那些想把php带向更宽的边界的工程师有所帮助.一个php请求的完整流程:浏览器用户--->web服务器(apache,nginx)--->Zend引擎从文件系统读取php代码文件--->Zend解释器工作--->执行解释后的代码-->Zend引擎注册的函数接口-->内置模块或者各个需要的外部模块扩展-->数据库memcache等后端资源   其中    Zend引擎注册的函数接口:就是php开发者经常接触的各种php函数.   外部模块扩展:就是php编译的各个so文件(linux)或者dll文件(windwos).   执行解释后的代码:浏览器的内容就是从这里返回的.   内置模块:也就是php每次启动的时候会携带启动的模块.从上面的流程图看php可以从3个点进行扩展.1 外部模块扩展 2 Zend引擎 3 内置模块,下面将一一讨论.   外部模块扩展.         如果你使用过dl()你就接触过这些外部的扩展模块.外部的扩展模块         文件就放在你的硬盘里,他在php脚本运行时被加载到内存中,而且只         有需要的时候才被加载.         当此次的脚本运行完之后他就会被内存释放掉,总的来说它运行的慢         但是不占资源.不需要重新编译一个php.   内置模块         虽然也是Zend引擎之外的模块,但是与外部模块扩展有些不同,他         已经在php里边了.他会使得你编译的php体积变大,如果有改变,         必须重新编译php才行.内置模块会使得         php内存变大,但是调用起来也会更加的快速.在我们的测试中一些         模块运行在内置模式会有30%以上的速度提升.   Zend引擎         首先,我绝对不建议你去修改Zend引擎.一些php语言的特性只要         在Zend引擎中才能够实现.比如要修改数组关键字的名字,可以在         这里实现.         在下载的php源代码里,以zend开头的都是zend引擎的相关代码.   外部模块扩展是下面要扩展的方式。   下面以一个简单的模块为例子说明如何编写PHP外部模块扩展:   首先编写php模块有自己的一套标准命名方式,你需要遵守,不然可能会导致   你的模块无法释放变量或者其他的问题,这些标准包括 宏定义,变量声明等   .你可以到官方浏览详细的说明./* 扩展的标准头 */#include "php.h"/* 声明这个so被导出的函数 */ZEND_FUNCTION(helloworld_module);/* Zend引擎注册的函数接口 */zend_function_entry helloworldmod_interfaces[] ={    ZEND_FE(helloworld_module, NULL)    {NULL, NULL, NULL}};/* 这是这个模块的声明实体,它的值对模块编译的时候起实际作用 */zend_module_entry helloworldmod_module_entry ={    STANDARD_MODULE_HEADER,    "Hello world",    helloworldmod_interfaces,    NULL,     NULL,     NULL,     NULL,     NULL,    NO_VERSION_YET,    STANDARD_MODULE_PROPERTIES};/* 向zend引擎声明一个备案,可以说明 helloworldmod_module_entry属于helloworldmod.so这个动态库*/#if COMPILE_DL_helloworld_moduleZEND_GET_MODULE(helloworldmod)#endif/* 这就是我们新增的函数的真正代码 */ZEND_FUNCTION(helloworld_module){    return "Hello,world";}   一般php源码目录结构类似下面:   main php的主要源代码,   ext php的扩展    sapi 与不同服务器的api交互层代码   zend zend引擎部分   TSRM 线程安全相关模块代码  我们编写的模块需要放在ext目录下面,可以根据其他扩展的config.m4文件  来修改成我们的必要编译配置信息。这里这个模块几乎是一个空的config.m4  文件就行,   然后利用phpize来生成configure文件然后是 ./configure && make    && make install执行就能编译一份的动态库  编写测试test.php<?phpecho helloworld_module();?>           输出:      "Hello,world"   切入PHP调用linux底层的过程在linux下面一个很给力的工具是LD_PRELOAD环境变量。LD_PRELOAD环境变量是编译器找到程序中所引用的函数或全局变量所存在的位置的一个过滤器,比如,在php的c代码里调用一个开始网络连接的方法connect,事实上就是通过动态链接去寻找linux的c库的函数connect,这些链接文件一般放在lib下面,这也就为影响php的代码执行提供了一个切入点。因为php程序在动态载入lib下面的函数connect之前会检查LD_PRELOAD提供的动态库里有没有这个connect函数,可以在这里对php的行为进行干涉。   下面以一个简单的过滤网络访问的例子说明如何实现:   先是一个准备作为LD_PRELOAD环境变量的值的so文件的代码。   lp_demo.c#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <stdlib.h>#include <errno.h>#include <dlfcn.h>//定义我们自己的connect函数int  connect(int  sockfd,  const  struct sockaddr *serv_addr, socklen_t             addrlen){  static int (*connect_linuxc)(int, const  struct sockaddr*, socklen_t)=NULL;  unsigned char *ip_char;  //利用 lsym的RTLD_NEXT选项绕过LD_PRELOAD环境变量的connect方法找到c库的函数  if (!connect_linuxc) connect_linuxc=dlsym(RTLD_NEXT,"connect");    ip_char=serv_addr->sa_data;    ip_char+=2;     //192.168.2.3 找到了    if ((*ip_char==192)&&(*(ip_char+1)==168)&&(*(ip_char+2)==2)&&(*(ip_char+3)==3)) {         //简单返回一个权限错误的代码            return EACCES;    }  // 调用真正的connect方法   return connect_linuxc(sockfd,serv_addr,addrlen);}  编译成so文件$ gcc -o lp_demo.so -shared lp_demo.c -ldl测试文件 test.php<?phpfile_get_contents("http://192.168.2.3/");?>  使用方法LD_PRELOAD=lp_demo.so php test.php这样他将不可能访问的到192.168.2.3这种我们内部的网址。起到一个很好的沙盒作用。除此之外我们还可以利用fwrite fopen等函数将php对文件系统的读写操作转移到mencache,nosql之类的后端资源当中。PS:在c库下面,还有一堆sys_开头的函数,它们才是内核空间里的真正的函数。
0 0