亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

PHP內核探索 —— 嵌入式PHP:類似CLI

瀏覽:36日期:2022-09-16 13:04:22

從PHP源碼目錄結構的介紹以及PHP生命周期可知:嵌入式PHP類似CLI,也是SAPI接口的另一種實現。 一般情況下,它的一個請求的生命周期也會和其它的SAPI一樣:模塊初始化=>請求初始化=>處理請求=>關閉請求=>關閉模塊。 當然,這只是理想情況。因為特定的應用由自己特殊的需求,只是在處理PHP腳本這個環節基本一致。

對于嵌入式PHP或許我們了解比較少,或者說根本用不到,甚至在網上相關的資料也不多, 例如很多游戲中使用Lua語言作為粘合語言,或者作為擴展游戲的腳本語言,類似的, 瀏覽器中的Javascript語言就是嵌入在瀏覽器中的。只是目前很少有應用將PHP作為嵌入語言來使用, PHP的強項目前還是在Web開發方面。

PHP對于嵌入式PHP的支持以及PHP為嵌入式提供了哪些接口或功能呢?首先我們看下所要用到的示例源碼:

#include <sapi/embed/php_embed.h>#ifdef ZTS void ***tsrm_ls;#endif/* Extension bits */zend_module_entry php_mymod_module_entry = { STANDARD_MODULE_HEADER, 'mymod', /* extension name */ NULL, /* function entries */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ '1.0', /* version */ STANDARD_MODULE_PROPERTIES};/* Embedded bits */static void startup_php(void){ int argc = 1; char *argv[2] = { 'embed5', NULL }; php_embed_init(argc, argv PTSRMLS_CC); zend_startup_module(&php_mymod_module_entry);}static void execute_php(char *filename){ zend_first_try {char *include_script;spprintf(&include_script, 0, 'include ’%s’', filename);zend_eval_string(include_script, NULL, filename TSRMLS_CC);efree(include_script); } zend_end_try();}int main(int argc, char *argv[]){ if (argc <= 1) {printf('Usage: embed4 scriptfile';);return -1; } startup_php(); execute_php(argv[1]); php_embed_shutdown(TSRMLS_CC); return 0;}

以上的代碼可以在《Extending and Embedding PHP》在第20章找到(原始代碼有一個符號錯誤,有興趣的童鞋可以去圍觀下)。 上面的代碼是一個嵌入式PHP運行器(我們權當其為運行器吧),在這個運行器上我們可以運行PHP代碼。 這段代碼包括了對于PHP嵌入式支持的聲明,啟動嵌入式PHP運行環境,運行PHP代碼,關閉嵌入式PHP運行環境。 下面我們就這段代碼分析PHP對于嵌入式的支持做了哪些工作。 首先看下第一行:

#include <sapi/embed/php_embed.h>

在sapi目錄下的embed目錄是PHP對于嵌入式的抽象層所在。在這里有我們所要用到的函數或宏定義。 如示例中所使用的php_embed_init,php_embed_shutdown等函數。

第2到4行:

#ifdef ZTS void ***tsrm_ls;#endif

ZTS是Zend Thread Safety的簡寫,與這個相關的有一個TSRM(線程安全資源管理)的東東,這個后面的章節會有詳細介紹,這里就不再作闡述。

第6到17行:

zend_module_entry php_mymod_module_entry = { STANDARD_MODULE_HEADER, 'mymod', /* extension name */ NULL, /* function entries */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ '1.0', /* version */ STANDARD_MODULE_PROPERTIES};

以上PHP內部的模塊結構聲明,此處對于模塊初始化,請求初始化等函數指針均為NULL, 也就是模塊在初始化及請求開始結束等事件發生的時候不執行任何操作。 不過這些操作在sapi/embed/php_embed.c文件中的php_embed_shutdown等函數中有體現。 關于模塊結構的定義在zend/zend_modules.h中。

startup_php函數:

static void startup_php(void){ int argc = 1; char *argv[2] = { 'embed5', NULL }; php_embed_init(argc, argv PTSRMLS_CC); zend_startup_module(&php_mymod_module_entry);}

這個函數調用了兩個函數php_embed_init和zend_startup_module完成初始化工作。 php_embed_init函數定義在sapi/embed/php_embed.c文件中。它完成了PHP對于嵌入式的初始化支持。 zend_startup_module函數是PHP的內部API函數,它的作用是注冊定義的模塊,這里是注冊mymod模塊。 這個注冊過程僅僅是將所定義的zend_module_entry結構添加到注冊模塊列表中。

execute_php函數:

static void execute_php(char *filename){ zend_first_try {char *include_script;spprintf(&include_script, 0, 'include ’%s’', filename);zend_eval_string(include_script, NULL, filename TSRMLS_CC);efree(include_script); } zend_end_try();}

從函數的名稱來看,這個函數的功能是執行PHP代碼的。 它通過調用sprrintf函數構造一個include語句,然后再調用zend_eval_string函數執行這個include語句。 zend_eval_string最終是調用zend_eval_stringl函數,這個函數是流程是一個編譯PHP代碼, 生成zend_op_array類型數據,并執行opcode的過程。 這段程序相當于下面的這段php程序,這段程序可以用php命令來執行,雖然下面這段程序沒有實際意義, 而通過嵌入式PHP中,你可以在一個用C實現的系統中嵌入PHP,然后用PHP來實現功能。

<?phpif($argc < 2) die('Usage: embed4 scriptfile');include $argv[1];?>

main函數:

int main(int argc, char *argv[]){ if (argc <= 1) {printf('Usage: embed4 scriptfile';);return -1; } startup_php(); execute_php(argv[1]); php_embed_shutdown(TSRMLS_CC); return 0;}

這個函數是主函數,執行初始化操作,根據輸入的參數執行PHP的include語句,最后執行關閉操作,返回。 其中php_embed_shutdown函數定義在sapi/embed/php_embed.c文件中。它完成了PHP對于嵌入式的關閉操作支持。 包括請求關閉操作,模塊關閉操作等。

以上是使用PHP的嵌入式方式開發的一個簡單的PHP代碼運行器,它的這些調用的方式都基于PHP本身的一些實現, 而針對嵌入式的SAPI定義是非常簡單的,沒有Apache和CGI模式的復雜,或者說是相當簡陋,這也是由其所在環境決定。 在嵌入式的環境下,很多的網絡協議所需要的方法都不再需要。如下所示,為嵌入式的模塊定義。

sapi_module_struct php_embed_module = { 'embed', /* name */ 'PHP Embedded Library',/* pretty name */ php_embed_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ NULL, /* activate */ php_embed_deactivate, /* deactivate */ php_embed_ub_write, /* unbuffered write */ php_embed_flush,/* flush */ NULL, /* get uid */ NULL, /* getenv */ php_error, /* error handler */ NULL, /* header handler */ NULL, /* send headers handler */ php_embed_send_header, /* send header handler */ NULL, /* read POST data */ php_embed_read_cookies, /* read Cookies */ php_embed_register_variables, /* register server variables */ php_embed_log_message, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ STANDARD_SAPI_MODULE_PROPERTIES};/* }}} */

在這個定義中我們看到了若干的NULl定義,在前面一小節中說到SAPI時,我們是以cookie的讀取為例, 在這里也有讀取cookie的實現——php_embed_read_cookies函數,但是這個函數的實現是一個空指針NULL。

標簽: PHP
相關文章:
主站蜘蛛池模板: 国产日韩亚洲 | 777国产精品永久免费观看 | 日本vs欧美一区二区三区 | 欧美日韩亚洲一区二区 | 毛片大全高清免费 | 伊人色综合网一区二区三区 | 亚洲综合一二三区 | 毛片a级 | 日本xxxxx成年视频软件 | 韩国精品一区二区久久 | 国产黄色免费看 | 手机在线观看亚洲国产精品 | 亚洲国产系列 | 欧美精品v国产精品v日韩精品 | 免费黄色视屏网站 | 黄色毛片a | 久久香蕉国产在产线看观看 | 亚洲免费看片 | 男女自偷自拍视频免费观看篇 | 国产精品国产三级国产专不∫ | 永久免费影院 | 一本大道一卡2卡三卡4卡麻豆 | 欧美精品亚洲精品日韩1818 | 狠狠操精品视频 | 国产日韩欧美一区二区三区在线 | 欧美黑人性猛交╳xx╳动态图 | 久久综合九色综合国产 | 樱花草在线社区www韩国 | 邪恶工番口番大全全彩色 | 我要看欧美精品一级毛片 | 香港三级欧美国产精品 | 免费人成在线观看视频不卡 | 一级片生活片 | 777国产精品永久免费观看 | 国产aaaaaaa毛片| 久久99精品久久久久久久不卡 | 亚洲国产国产综合一区首页 | 一级特黄a大片免费 | 91高清视频在线观看 | 国产性猛交xx乱 | 国产精品天天看天天爽 |