摘要:模塊加載原理的模塊可以以靜態(tài)方式編譯到可執(zhí)行程序中,也可以在運(yùn)行過程中動(dòng)態(tài)加載以動(dòng)態(tài)鏈接庫的方式。這樣在進(jìn)程運(yùn)行時(shí)一有請求,就可以加載動(dòng)態(tài)鏈接庫文件形式的模塊,用來處理請求。
1、PHP與Apache工作模式
在傳統(tǒng)的LAMP架構(gòu)中,PHP與Apache交互時(shí),至少有兩種方式『運(yùn)行PHP』:
使用CGI:Apache發(fā)送請求至php-cgi進(jìn)程,php-cgi進(jìn)程調(diào)用PHP解釋器,然后由PHP解釋器進(jìn)程解釋php腳本代碼。
使用mod_php作為Apache的一個(gè)模塊:PHP解釋器作為Apache的一個(gè)內(nèi)置模塊,即不存在外部的PHP進(jìn)程,而是由Apache(中的mod_php模塊)進(jìn)程解釋執(zhí)行PHP腳本 - 這意味著PHP與Apache通信更方便快捷。
其中,『運(yùn)行PHP』是指調(diào)用PHP解釋器解釋執(zhí)行PHP腳本。
通過php的"php_sapi_name()’函數(shù)可知道,當(dāng)前系統(tǒng)采用哪種工作模式。如當(dāng)值為’apache2handler’時(shí)即表示:mod_php模式。
2、Apache模塊加載原理Apache的模塊可以以靜態(tài)方式編譯到可執(zhí)行程序中,也可以在Apache運(yùn)行過程中動(dòng)態(tài)加載(以動(dòng)態(tài)鏈接庫的方式)。這意味著:可以對Apache服務(wù)器程序進(jìn)行擴(kuò)展而無需重新源碼編譯它,甚至無需重啟它。
所需要做的就是:向服務(wù)器發(fā)送HUP或者AP_SIG_GRACEFUL信號,通知服務(wù)器重新加載模塊。
關(guān)于向Apache發(fā)送HUP信號:
"Sending the HUP or restart signal to the parent causes it to kill off its children like in TERM, but the parent doesn"t exit. It re-reads its configuration files, and re-opens any log files. Then it spawns a new set of children and continues serving hits.
回到mod_php模塊,Apache動(dòng)態(tài)加載模塊的過程:
首先,在Apache配置文件http.conf中增加:LoadModule php7_module libexec/apache2/libphp7.so,表示運(yùn)行過程中加載PHP模塊的動(dòng)態(tài)鏈接庫文件:libphp7.so。
然后,通過Apache的內(nèi)部函數(shù)(以Hook的方式)獲取動(dòng)態(tài)鏈接庫的內(nèi)容,并將PHP模塊的內(nèi)容加載到內(nèi)存中指定的變量中。
其中PHP7源碼中,PHP模塊(php7_module)的數(shù)據(jù)結(jié)構(gòu)為:
‘
AP_MODULE_DECLARE_DATA module php7_module = { STANDARD20_MODULE_STUFF, /*宏,包括了module結(jié)構(gòu)的前8個(gè)字段:版本號、小版本號、模塊索引、模塊名、當(dāng)前模塊指針、下一個(gè)動(dòng)態(tài)加載的模塊指針、魔數(shù)、rewrite_args函數(shù)指針*/ create_php_config, /* create per-directory config structure */ merge_php_config, /* merge per-directory config structures */ NULL, /* create per-server config structure */ NULL, /* merge per-server config structures */ php_dir_cmds, /* command apr_table_t */ php_ap2_register_hook /* register hooks */ };
其中,php_ap2_register_hook是一系列的hook調(diào)用:
void php_ap2_register_hook(apr_pool_t *p) { ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE); #ifdef ZEND_SIGNALS ap_hook_child_init(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE); #endif ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE); }
pre_config、post_config、child_init是啟動(dòng)時(shí)執(zhí)行的鉤子,它們會在Apache服務(wù)器啟動(dòng)時(shí)調(diào)用。其中,在post_config鉤子中啟動(dòng)PHP解釋器模塊(由php_apache_server_startup函數(shù)實(shí)現(xiàn):"通過調(diào)用sapi_startup啟動(dòng)sapi, 并通過調(diào)用php_apache2_startup來注冊sapi module struct(此結(jié)構(gòu)在本節(jié)開頭中有說明), 最后調(diào)用php_module_startup來初始化PHP, 其中又會初始化ZEND引擎,以及填充zend_module_struct中 的treat_data成員(通過php_startup_sapi_content_types)等")。
handler是請求時(shí)執(zhí)行的鉤子,它會在Apache服務(wù)器處理請求時(shí)調(diào)用。
3、Apache Hooking機(jī)制:在Apache2.4中如果需要處理請求時(shí),你只需要?jiǎng)?chuàng)建一個(gè)鉤子(Hook),掛于請求處理程序上。
一個(gè)鉤子,本質(zhì)上是一條信息:告訴服務(wù)器它要么服務(wù)用戶發(fā)起的請求要么只是瞥一眼該請求。Apache所有的模塊(包括mod_rewrite, mod_authn_*, mod_proxy等)均是將鉤子掛于請求程序的各個(gè)部分來實(shí)現(xiàn)的 - are hooked into specific parts of the request process。
modules serve different purposes; Some are authentication/authorization handlers, others are file or script handlers while some third modules rewrite URIs or proxies content.
Apache服務(wù)器本身無需知道每個(gè)模塊具體負(fù)責(zé)處理哪個(gè)部分以及處理什么,它只需要:在客戶端請求達(dá)到的時(shí)候詢問下哪個(gè)模塊對這個(gè)請求『感興趣』即可,而每個(gè)模塊只需選擇要還是不要,如果要那按照鉤子定義的內(nèi)容處理然后返回接口。
圖片來源于Apache官網(wǎng)。
Apache允許外部模塊可以將自定義的函數(shù)注入到自己的請求處理循環(huán)中,從而參與Apache的請求處理過程。
通過Hook機(jī)制,PHP模塊可以在Apache請求處理流程中負(fù)責(zé)處理那些關(guān)于php腳本的請求(即負(fù)責(zé)解釋、執(zhí)行php腳本)。
具體實(shí)現(xiàn)方式可以詳見在PHP源碼中實(shí)現(xiàn)Apahce的ap_hook_post_config鉤子:PHP以模塊方式注冊到Apache的掛鉤上去。這樣在Apache進(jìn)程運(yùn)行時(shí)一有php請求,就可以加載動(dòng)態(tài)鏈接庫(libphp7.so文件)形式的PHP模塊,用來處理php請求。
1、http://stackoverflow.com/ques...
2、http://www.phppan.com/2011/01...
3、https://github.com/php/php-sr...
4、https://github.com/php/php-sr...
5、https://httpd.apache.org/docs...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/29620.html
摘要:模塊加載原理的模塊可以以靜態(tài)方式編譯到可執(zhí)行程序中,也可以在運(yùn)行過程中動(dòng)態(tài)加載以動(dòng)態(tài)鏈接庫的方式。這樣在進(jìn)程運(yùn)行時(shí)一有請求,就可以加載動(dòng)態(tài)鏈接庫文件形式的模塊,用來處理請求。 1、PHP與Apache工作模式 在傳統(tǒng)的LAMP架構(gòu)中,PHP與Apache交互時(shí),至少有兩種方式『運(yùn)行PHP』: 使用CGI:Apache發(fā)送請求至php-cgi進(jìn)程,php-cgi進(jìn)程調(diào)用PHP解釋器,然...
摘要:到此為止,我們就基本講清楚了中的中間件洋蔥模型是如何自動(dòng)執(zhí)行的。 koa被認(rèn)為是第二代web后端開發(fā)框架,相比于前代express而言,其最大的特色無疑就是解決了回調(diào)金字塔的問題,讓異步的寫法更加的簡潔。在使用koa的過程中,其實(shí)一直比較好奇koa內(nèi)部的實(shí)現(xiàn)機(jī)理。最近終于有空,比較深入的研究了一下koa一些原理,在這里會寫一系列文章來記錄一下我的學(xué)習(xí)心得和理解。 在我看來,koa最核心...
摘要:介紹每有一個(gè)用戶請求,都會先要?jiǎng)?chuàng)建的子進(jìn)程,然后處理請求,處理完后結(jié)束這個(gè)子進(jìn)程,這就是模式。當(dāng)子進(jìn)程關(guān)閉連接時(shí),請求便告處理完成。子進(jìn)程接著等待并處理來自進(jìn)程管理器的下一個(gè)連接。運(yùn)行在模式時(shí),提供的方法。 本文介紹,PHP運(yùn)行在FastCGI模式時(shí),F(xiàn)PM提供的方法:fastcgi_finish_request。 在說這個(gè)方法之前,我們先了解PHP有哪些常用的運(yùn)行模式? PHP運(yùn)行模...
摘要:而之后,我們得到的是一個(gè)是一個(gè)對象,我們可以使用語句定義回調(diào)函數(shù),函數(shù)的內(nèi)容呢,則是將讀取到的返回給并繼續(xù)讓從斷點(diǎn)處執(zhí)行。 在上一篇中我們梳理了koa當(dāng)中中間件的洋蔥模型執(zhí)行原理,并實(shí)現(xiàn)了一個(gè)可以讓洋蔥模型自動(dòng)跑起來的流程管理函數(shù)。這一篇,我們再來研究一下koa當(dāng)中異步回調(diào)同步化寫法的原理,同樣的,我們也會實(shí)現(xiàn)一個(gè)管理函數(shù),是的我們能夠通過同步化的寫法來寫異步回調(diào)函數(shù)。 1. 回調(diào)金字...
摘要:許多公司都投資于或之類的靜態(tài)分析安全測試,解決方案。用靜態(tài)分析方法確保編程安全一書詳細(xì)描述了靜態(tài)分析技術(shù)的基本原理。博士將靜態(tài)分析無法找出的諸多安全問題歸為瑕疵,而非程序錯(cuò)誤。 靜態(tài)分析安全測試(SAST)是指不運(yùn)行被測程序本身,僅通過分析或者檢查源程序的語法、結(jié)構(gòu)、過程、接口等來檢查程序的正確性,那么采用靜分析安全測試的方法有什么優(yōu)缺點(diǎn)呢,且讓小編給你說道說道。 許多公司都投資于 H...
閱讀 1989·2021-11-22 14:45
閱讀 2609·2021-10-12 10:11
閱讀 776·2021-09-22 10:02
閱讀 1222·2019-08-30 15:55
閱讀 1147·2019-08-30 15:54
閱讀 3258·2019-08-30 15:54
閱讀 1193·2019-08-29 17:16
閱讀 3090·2019-08-28 17:55