1.前言
隨著lamp/lnmp架構的流行,Php語言越來越得到廣泛的使用。php語言在表現層有著非常優異的表現,部署方便,開發迅速。但Php語言也有著天生短板以及局限性—-對多線程以及多進程的支持不甚如意,以及相對于靜態語言緩慢的執行速度。如今網站的數據越來越多,涉及到的密集型計算對性能的要求越來越高,php語言越來越難以滿足這種計算性能的要求,由于Php底層由c語言開發完成,用c語言更改php底層以及為Php語言編寫底層拓展是解決Php本身性能的一大方法。
本文將以一個簡單實例來演示如何為Php編寫底層拓展,讀者掌握此方法后,可以根據具體的業務需求,為php編寫具有良好性能的底層拓展。如,筆者在工作中遇到過隨時計算用戶之間GPS距離的產品需求,涉及的計算量巨大。讀者遇到此類的需求,可以考慮在底層專門寫出c語言拓展來解決問題。本文成稿時間匆忙,紕漏之處在所難免,希望讀者指正。
2.編寫拓展
2.1 自動生成框架
請下載php源碼包,yum安裝的php沒有ext_skel這個文件。ext_skel這個文件就用來幫我們生成框架。具體的目錄如下:
[root@localhost~/tools/php-5.5.38/ext]> ll /root/tools/php-5.5.38/ext/ext_skel -rwxr-xr-x. 1 1000 admins 8192 Jul 20 16:41 /root/tools/php-5.5.38/ext/ext_skel
現在執行這個文件,生成一個helloWorld的框架:
[root@localhost~/tools/php-5.5.38/ext]> /root/tools/php-5.5.38/ext/ext_skel --extname=helloWorld Creating directory helloWorld Creating basic files: config.m4 config.w32 .svnignore helloWorld.c php_helloWorld.h CREDITS EXPERIMENTAL tests/001.phpt helloWorld.php [done]. To use your new extension, you will have to execute the following steps: 1. $ cd .. 2. $ vi ext/helloWorld/config.m4 3. $ ./buildconf 4. $ ./configure --[with|enable]-helloWorld 5. $ make 6. $ ./sapi/cli/php -f ext/helloWorld/helloWorld.php 7. $ vi ext/helloWorld/helloWorld.c 8. $ make Repeat steps 3-6 until you are satisfied with ext/helloWorld/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.
如上所示,ext_skel幫我們生成了helloWorld拓展的框架,里面包含了一個配置文件config.m4, c語言的頭文件php_helloWorld.h, 以及函數文件helloWorld.c(這個文件就是寫入c函數體的地方)。找到這些文件:
[root@localhost~/tools/php-5.5.38/ext/helloWorld]> ll total 32 -rw-r--r--. 1 root chuji001 2178 Oct 30 02:54 config.m4 -rw-r--r--. 1 root chuji001 324 Oct 30 02:54 config.w32 -rw-r--r--. 1 root chuji001 10 Oct 30 02:54 CREDITS -rw-r--r--. 1 root chuji001 0 Oct 30 02:54 EXPERIMENTAL -rw-r--r--. 1 root chuji001 5296 Oct 30 02:54 helloWorld.c -rw-r--r--. 1 root chuji001 514 Oct 30 02:54 helloWorld.php -rw-r--r--. 1 root chuji001 2962 Oct 30 02:54 php_helloWorld.h drwxr-xr-x. 2 root chuji001 4096 Oct 30 02:54 tests
2.2 編輯文件
編輯config.m4這個配置文件,找到如下配置行,去掉前面的dnl, 目的是方便之后configure編譯新開發出來的模塊:
10 dnl PHP_ARG_WITH(helloWorld, for helloWorld support, 11 dnl Make sure that the comment is aligned: 12 dnl [ --with-helloWorld Include helloWorld support])
改為:
10 PHP_ARG_WITH(helloWorld, for helloWorld support, 11 Make sure that the comment is aligned: 12 [ --with-helloWorld Include helloWorld support])
接下來編寫c的頭文件,找到這一行:
PHP_FUNCTION(confirm_helloWorld_compiled); /* For testing, remove later. */
這一行是我們實際調用的函數名稱,讀者可以改成方便開發團隊調用的名稱,也可以不更改,這里筆者更改如下:
PHP_FUNCTION(helloWorld); /* For testing, remove later. */
接下來更改編譯文件helloWorld.c函數文件:
41 const zend_function_entry helloWorld_functions[] = { 42 PHP_FE(confirm_helloWorld_compiled, NULL) /* For testing, remove late r. */ 43 PHP_FE_END /* Must be the last line in helloWorld_functions[] */ 44 };
改為注冊好的函數名:
41 const zend_function_entry helloWorld_functions[] = { 42 PHP_FE(helloWorld, NULL) /* For testing, remove late r. */ 43 PHP_FE_END /* Must be the last line in helloWorld_functions[] */ 44 };
接下來就是編寫自己的業務邏輯函數,筆者這里寫入一個簡單的helloWorld,讀者可根據自己的需求來編寫調用的函數:
154 PHP_FUNCTION(helloWorld) 155 { 156 zend_printf("hello world\n"); 157 }
2.2 編譯生成拓展
編譯php:
[root@localhost~/tools/php-5.5.38/ext/helloWorld]> /application/php5.5.34/bin/phpize Configuring for: PHP Api Version: 20121113 Zend Module Api No: 20121212 Zend Extension Api No: 220121212
生成拓展:
這個時候觀察目錄,多了一個configure編譯文件
[root@localhost~/tools/php-5.5.38/ext/helloWorld]> ll total 1244 -rw-r--r--. 1 root chuji001 79850 Oct 30 03:39 acinclude.m4 -rw-r--r--. 1 root chuji001 310225 Oct 30 03:39 aclocal.m4 drwxr-xr-x. 2 root chuji001 4096 Oct 30 03:39 autom4te.cache drwxr-xr-x. 2 root chuji001 4096 Oct 30 03:39 build -rwxr-xr-x. 1 root chuji001 45079 Oct 30 03:39 config.guess -rw-r--r--. 1 root chuji001 1542 Oct 30 03:39 config.h.in -rw-r--r--. 1 root chuji001 2166 Oct 30 03:09 config.m4 -rwxr-xr-x. 1 root chuji001 35782 Oct 30 03:39 config.sub -rwxr-xr-x. 1 root chuji001 447850 Oct 30 03:39 configure
執行configure編譯,生成拓展, configure完成之后執行make(必要):
[root@localhost~/tools/php-5.5.38/ext/helloWorld]> ./configure --with-php-config=/application/php5.5.34/bin/php-config
查看array_square_sum目錄的module目錄,會發現里面生成helloWorld.so,這個就是我們需要的擴展。
[root@localhost~/tools/php-5.5.38/ext/helloWorld/modules]> ll total 28 -rw-r--r--. 1 root chuji001 823 Oct 30 03:46 helloWorld.la -rwxr-xr-x. 1 root chuji001 23351 Oct 30 03:46 helloWorld.so
編寫php.ini的配置文件,為Php加入拓展:
899 extension=helloWorld.so
將生成的拓展文件復制放入php默認的拓展文件目錄當中去:
[root@localhost~/tools/php-5.5.38/ext/helloWorld/modules]> cp helloWorld.so /application/php5.5.34/lib/php/extensions/no-debug-zts-20121212/
重啟httpd服務器,這個時候通過phpinfo你就可以看到自己編寫的拓展啦!如圖:
編寫Php腳本即可直接調用這個函數:
1 <?php 2 helloWorld(); 3 ?>
顯示如圖:
結語
用c來為Php編寫拓展是一個深入的課題,筆者這里只是給出了簡單的例子,如讀者有需要,需找更加詳細的資料,本文的目的僅為入門。
原創文章,作者:21期王逸凡,如若轉載,請注明出處:http://www.www58058.com/55578