2023-11-16 分類: 網站建設
1.WEb服務器調用pHp接口
以服務端為例,看看服務端是如何啟動pHp并調用pHp中的方法的。服務器啟動運行pHp時,一般以模塊的形式集成(如果是php5.*版本,則是模塊,模塊的后綴取決于php版本)。結構如下(源碼路徑為php/sapi//.c):
Ap_MODULE_DECLARE_DATA module php7_module = {
STANDARD20_MODULE_STUFF,/* 宏,包括版本,版本,模塊索引,模塊名,下個模塊指針等信息 */
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, /* 模塊定義的所有指令 */
php_ap2_register_hook /* register hooks */
};
當你需要在 pHp 中調用一個方法時,你只需要通過模塊將請求傳達給 pHp。 pHp層處理完數據后,返回數據,整個過程就結束了。 (另外:服務器啟動pHp的時候,其實有兩種加載方式,一種是靜態加載,一種是動態加載。剛才討論的模塊加載方式可以理解為靜態加載,即服務端需要重新啟動加載pHp;
動態加載不需要重啟服務器。只需通過發送信號將固定的pHp模塊加載到服務器即可達到pHp啟動的目的。但是在動態加載之前,需要將加載模塊編譯成動態鏈接庫。然后將其配置到服務器配置文件中)。上面已經給出了pHp中的結構,下面給出了服務器端對應的結構,如下(中間是源碼,下同):
struct module_struct {
int version;
int minor_version;
int module_index;
const char *name;
void *dynamic_load_handle;
struct module_struct *next;
unsigned long magic;
void (*rewrite_args) (process_rec *process);
void *(*create_dir_config) (apr_pool_t *p, char *dir);
void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf);
void *(*create_server_config) (apr_pool_t *p, server_rec *s);
void *(*merge_server_config) (apr_pool_t *p, void *base_conf, void *new_conf);
const command_rec *cmds;
void (*register_hooks) (apr_pool_t *p);
}
可以看出and還是有很大區別的,但是如果你看到.UFF宏的定義,你可能會覺得這兩個結構很相似。其實這個宏定義了前8個參數,定義如下:
#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMbER_MAJOR,
MODULE_MAGIC_NUMbER_MINOR,
-1,
__FILE__,
NULL,
NULL,
MODULE_MAGIC_COOKIE,
NULL /* rewrite args spot */
那么。定義了模塊的所有指令集php獲取apache版本,具體定義內容如下(代碼路徑為php/sapi//.c):
const command_rec php_dir_cmds[] =
{
Ap_INIT_TAKE2("php_value", php_apache_value_handler, NULL, OR_OpTIONS, "pHp Value Modifier"),
Ap_INIT_TAKE2("php_flag", php_apache_flag_handler, NULL, OR_OpTIONS, "pHp Flag Modifier"),
Ap_INIT_TAKE2("php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, "pHp Value Modifier (Admin)
"),
Ap_INIT_TAKE2("php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, "pHp Flag Modifier (Admin)"),
Ap_INIT_TAKE1("pHpINIDir", php_apache_phpini_set, NULL, RSRC_CONF, "Directory containing the php.ini file"),
{NULL}
};
也就是說pHp層只提供了以上5條指令,每條指令的源碼也在.c文件中。最后是.k,其定義如下(代碼路徑為php/sapi //.c):
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);
}
.k 函數包含 4 個鉤子和相應的處理函數,是啟動鉤子。它們在服務器啟動時被調用。鉤子是一個請求鉤子。在發出服務器請求時調用它。通過這些鉤子,你可以通過服務器啟動pHp。
我會來的。我想你已經知道WEb服務器如何啟動pHp并調用pHp中的方法了。下面我就給大家講講pHp是如何調用WEb服務器接口的。
2.pHp 調用WEb服務器接口 在我們講這個問題之前,我們需要了解什么是SApI。 SApI 實際上是與服務器抽象層觀察到的通用協議。很容易理解,當pHp需要調用服務端的某個方法時,比如清除緩存,清除緩存的實現方法是在服務端實現的,pHp層根本不知道。服務端的方法怎么調用,怎么做?
這時候需要雙方做一個約定,然后服務器向pHp提供一套約定好的接口。我們將這些與服務器抽象層的通用協議稱為 SApI 接口。
問題來了。對于服務器php獲取apache版本,我們可以提供一套SApI,但是如果下次有其他服務器或其他“第三方”來,我們是否還需要為它們提供單獨的SApI?毛布?
我們聰明的pHp開發者一定想到了這個,就是為所有“第三方”提供一套通用的SApI接口,但是你可能會問,如果新的“第三方”需要這些接口,你的通用SApI不支持,怎么辦?我的理解是,在 pHp 的通用 SApI 接口中添加新功能只是個人意見。一般的SApI結構如下(源碼路徑:php/main/SApI.h):
struct _sapi_module_struct {
char *name; // 名字
char *pretty_name; // 更好理解的名字
int (*startup)(struct _sapi_module_struct *sapi_module); // 啟動函數
int (*shutdown)(struct _sapi_module_struct *sapi_module); // 關閉函數
int (*activate)(TSRMLS_D); // 激活
int (*deactivate)(TSRMLS_D); // 停用
void (*flush)(void *server_context); // flush
char *(*read_cookies)(TSRMLS_D); //read Cookies
//...
};
這個結構的變量很多,就不一一列舉了。我簡單解釋一下里面的變量:SApI初始化時調用的函數,該函數用于釋放SApI的數據結構和內存。它在 SApI 中激活。調用時,則將該函數得到的值賦給SG()。
那么對于pHp提供的通用SApI,服務端如何自定義自己的接口呢?具體結構如下(源碼路徑為php/sapi//.c):
static sapi_module_struct apache2_sapi_module = {
"apache2handler",
"Apache 2.0 Handler",
php_apache2_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
NULL, /* activate */
NULL, /* deactivate */
php_apache_sapi_ub_write, /* unbuffered write */
php_apache_sapi_flush, /* flush */
php_apache_sapi_get_stat, /* get uid */
php_apache_sapi_getenv, /* getenv */
php_error, /* error handler */
php_apache_sapi_header_handler, /* header handler */
php_apache_sapi_send_headers, /* send headers handler */
NULL, /* send header handler */
php_apache_sapi_read_post, /* read pOST data */
php_apache_sapi_read_cookies, /* read Cookies */
php_apache_sapi_register_variables,
php_apache_sapi_log_message, /* Log message */
php_apache_sapi_get_request_time, /* Request Time */
NULL, /* Child Terminate */
STANDARD_SApI_MODULE_pROpERTIES
};
在上述源碼目錄php/sapi//中,php/sapi目錄放在通過SApI調用的“第三方”下。目錄結構如下圖所示,目錄php/sapi/都是與pHp交互的接口,.c是pHp與約定的SApI之間的接口文件。
看到這里,大家應該對pHp層如何調用服務層接口有了基本的了解。為了鞏固以上知識,下面來個栗子,即在服務器環境下閱讀:
SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
對于任何一個在加載的時候,我們都會指定它的方法是一個函數,這樣就實現了pHp層調用的接口。是不是很簡單?
進階階段總會有一些問題和瓶頸。寫太多業務代碼沒有方向感。我不知道從哪里開始改進。我整理了一些這方面的資料,包括但不限于:分布式架構、高擴展性、高性能、高并發、服務器性能調優、Tp6、YII2、、、、、優化、腳本、微服務等進階知識點都可以與您免費分享。需要點這里
最后,祝你在面試中一切順利,得到你最喜歡的。如果你想和一群3-8年的資深開發者交流學習,你需要
請點擊這里 .im
本文名稱:看看該服務器是怎樣啟動pHp,并運行pHp中的方法
文章出自:http://m.newbst.com/news39/294689.html
成都網站建設公司_創新互聯,為您提供全網營銷推廣、服務器托管、企業網站制作、ChatGPT、微信公眾號、外貿建站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯
猜你還喜歡下面的內容