PHP詳解php
一個php實例,當被調用的時候,都會一次通過Module init,Request init,Request shutdown,Module shutdown四個過程.執行次數由SAPI(server abstraction API,服務器抽象化程序接口)來決定。數組
1)Call each extension's MINIT這個過程在載入的時候被調用安全
PHP_MINIT_FUNCTION(擴展名稱){ /*註冊常量或者初始化操做*/ return SUCCESS; }
2)Request服務器
PHP_RINT_FUNCTION(擴展名稱){ /*處理請求*/ return SUCCESS; }
3)Execute函數
執行php階段,主要是把PHP文件編譯成Opcodes而後在php虛擬機下執行線程
ps:能夠安裝VLD擴展來查看php的opcode詳細內容翻譯
4)Call each extension's RESHUTDOWNcode
請求處理完進入結束狀態,通常腳本執行到結尾,或者經過調用exit()或者die()函數PHP將進入結束狀態,結束也分爲兩個環節,一個在請求後(RSHUTDOWN),一個在SAPI生命週期結束時候(MSHUTDOWN)server
PHP_RSHUTDOWN_FUNCTION{ return SUCCESS; } PHP_MSHUTDOWN_FUNCTION{ /*註銷持久化資源*/ return SUCCESS; }
在請求一個php頁面,php基本上按照這個流程來執行的。接口
ZEND引擎
Zend引擎是腳本語言引擎,主要工做是解析,翻譯和執行php腳本,主要執行兩個功能
當咱們執行./ext_skel --extname=擴展名稱的時候活建立你的擴展名稱.c文件
結構以下所示
#ifdef HAVE_CONFIG_H #include "config.h" #endif /** 包含頭文件引入所需的配置文件API等**/ #include "php.h" /*在php擴展中,必須包含php.h頭文件,它位於main目錄下,這個文件包含構建擴展時必須的各類宏和API定義*/ #include "php_ini.h" #include "ext/standard/info.h" #include "php_php_list.h" /* True global resources - no need for thread safety here */ static int le_php_list; /*聲明ZEND函數塊*/ /*ZEND 引擎經過zend_function_entry 結構數組把聲明的導出函數引入內部*/ const zend_function_entry php_list_functions[] = { PHP_FE(confirm_php_list_compiled, NULL) PHP_FE_END /*必須以PHP_FE_END結尾*/ /*早期的php是以{NULL,NULL,NULL}結尾,如今ZEND把這個和宏綁定在一塊兒了*/ /* #define PHP_FE_END ZEND_FE_END #define ZEND_FE_END { NULL, NULL, NULL, 0, 0 } */ }; /*聲明ZEND模塊*/ zend_module_entry php_list_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "php_list", php_list_functions, PHP_MINIT(php_list), PHP_MSHUTDOWN(php_list), PHP_RINIT(php_list), PHP_RSHUTDOWN(php_list), PHP_MINFO(php_list), #if ZEND_MODULE_API_NO >= 20010901 PHP_PHP_LIST_VERSION, #endif STANDARD_MODULE_PROPERTIES }; /*實現get_moudle()函數*/ #ifdef COMPILE_DL_PHP_LIST ZEND_GET_MODULE(php_list) #endif /*php的生命週期*/ PHP_MINIT_FUNCTION(php_list) { return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(php_list) { return SUCCESS; } PHP_RINIT_FUNCTION(php_list) { return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(php_list) { return SUCCESS; } /*此處配置的是顯示在phpinfo()擴展名下的內容*/ PHP_MINFO_FUNCTION(php_list) { php_info_print_table_start(); php_info_print_table_header(2,"first","second"); php_info_print_table_row(2,"mother","fucker"); php_info_print_table_row(2,"fill","fucker"); php_info_print_table_end(); } /*實現導出函數*/ PHP_FUNCTION(confirm_php_list_compiled) { char *str = NULL; //獲取輸入的個數 int argc = ZEND_NUM_ARGS(); int str_len; /* 字符串 長度*/ long n; char *result; char *ptr; int result_length; if(zend_parse_parameters(argc TSRMLS_CC,"sl",&str,&str_len,&n)==FAILURE) return ; //獲取字符的總長度(字符串長度 * 重複次數) result_length = (str_len)*n; //分配空間 result = (char *) emalloc(result_length+1); ptr = result; while(n--){ memcpy(ptr,str,str_len); ptr+=str_len; } *ptr ='\0'; RETURN_STRINGL(result,result_length,0); }
取得用戶傳遞的參數
php支持可變參數,能夠使用ZEND_NUM_ARGS(傳入參數的數量)宏實現,其實這個宏等於參數ht。
取得參數的實體
int zend_parse_parameters(int nums TSRMLS_CC,"char * type",....) /* 第一個參數 nums:表名要接受參數的個數 第二個參數 TSRMLS_CC:是否啓用線程安全 第三個參數:指定傳來參數的類型(字符串) 剩下的參數:根據第三個參數類型聲明不一樣的地址 注:字符串‘s’,須要使用兩個變量來保存 */
待續....