今後 PHP 拡張機能を開発するには、PHP の実行シーケンスを理解する必要があります。この記事は、C で PHP 拡張機能を開発するための道を開くことを目的としています。
PHP をコンパイルするときは、Web 環境が Apache であることを前提としています。 、Apache に PHP をサポートさせるために、mod_php5.so モジュールを生成します。Apache はこのモジュールをロードします...
.php ファイルが URL でアクセスされると、mod_php5.so モジュールに転送されます。これは何ですか... よくあることです。 SAPI
英語名は、Server abstraction APIです。
SAPIは、実際には、ISAPI、CLI SAPI、CGIなどがある総称です。
それには、たとえば、APACHE、IIS、CGI などと簡単に対話できます。
さて、本題に戻ります。
Apache が起動すると、Apache ではない mod_pho5.so モジュールのフック ハンドラーが登録されます。今日は主人公なので詳細は説明しません。
アクセスされた URL が php ファイルであることを APACHE が検出すると、この時点で制御が sapi に渡されます。
sapi に入った後、 sapi/apache/mod_php5.c ファイルの php_init_handler 関数が最初に実行されます
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 ... void *) shutdown_for_exec);
if (!apache_php_initialized) {
tsrm_startup(1, 1、0、NULL); (&apache_sapi_module);
}
}
#endif
}
この関数は主に 2 つの関数を呼び出します
sapi_startup(&apache_sapi_module);php_apache_startup( &apache_sapi_module);
1
2
3
4
5
6
7
8
9
10
11
1213
14
15
SAPI_API void sapi_startup(sapi_module_struct *sf)
{
sf->ini_entries = NULL;
sapi_module = *sf;
...................
sapi_globals_ctor(&sapi_globals);
......
virtual_cwd_startup(); /* shutdown を使用してメイン cwd を解放することもできますが、CGI の速度が低下するだけです */
..................
reentrancy_startup() ;
}
sapi_startup创建一sapi_globals_struct構造体.
sapi_globals_struct保存apache请要求の基本情報、服务器情報、ヘッダー、编码など
1
2
3
4
5
6
static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
{
memset (sapi_globals, 0, sizeof (*sapi_globals));
zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);
php_setup_sapi_content_types(TSRMLS_C);
}
known_post_content_types は 1 つの HashTable、将その大小初期化は 5 です。 _setup_sapi_content_types関数数sapi_post_entryをsapi_globals里に追加
sapi_startup実行完了後に再実行php_apache_startup
1
2
3
4
5
6
7
8
static int php_apache_startup(sapi_module_struct *sapi_module)
{
if ( php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
return FAILURE;
} else {
成功を返します。
}
}
php_module_startup には内容が多すぎます。
1. zend_utility_functions 構造体を初期化します。この構造体は、エラー処理関数、出力関数、ストリーム操作関数などを設定します。
3. php.ini 設定をロードします。
4. PHP 組み込み拡張機能をロードします。
6. PHP 内部関数セットを登録します。
7. すべての外部拡張機能をロードします。拡張機能
9. クリーンアップ操作
3、4、7、8 に焦点を当てます
php.ini 設定をロードします
if (php_init_config(TSRMLS_C) == FAILURE) {return FAILURE;}
php_init_config 関数はすべてをチェックしますphp の ini 設定を実行し、ロードされたすべてのモジュールを見つけて php_extension_lists 構造体に追加します。
PHP 組み込み拡張機能をロードします
zend_register_standard_ini_entries を呼び出して、配列、mysql などのすべての PHP 組み込み拡張機能をロードします php_ini_register_extensions を呼び出して、すべての外部拡張機能をロードします
main/php_ini.c
2
3
4
5
6
7
8
void php_ini_register_extensions(TSRMLS_D)
{
php_load_zend_exテンション_cb TSRMLS_CC);
zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
zend_llist_destroy(&extension_lists.functions);}
zend_llist_apply 関数は extension_lists 実行会議を走査します。関数 php_load_php_extension_cb
php_load_php_extension_cb
1 2
3
static void php_load_zend_ex_cb( voidtension *arg TS RMLS_DC)
{
zend_load_extension(*(( char **) arg));
}
拡張機能をロードするには ext/standard/dl.c zend_load_extension を呼び出します。
この関数はスキップされます。この関数は最後に
if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL を呼び出します) {DL_UNLOAD (ハンドル);
return FAILURE;}拡張情報をハッシュテーブル module_registry に入れるZend/zend_API.c
1
2
3
5
の場合(zend_hash_add( & module_regization, LCName, name_len+1, (void *) module, sizeof (zend_module_entry), (void **) & module_ptr) {
(E_CORE_W Arning, "モジュール '%s' はすでにロードされています) ", module-& gt ;name);
efree(lcname); _C); // モジュールを並べ替えて、モジュールに登録されているかどうかを確認します_registry HASH テーブル
zend_startup_extensions () // 拡張機能の実行 -> スタートアップ(拡張機能);拡張機能を開始します...