ホームページ > バックエンド開発 > PHPの問題 > PHP拡張機能のカスタマイズ方法(2)フック関数

PHP拡張機能のカスタマイズ方法(2)フック関数

藏色散人
リリース: 2023-03-14 14:32:01
転載
2118 人が閲覧しました

前の記事 に続いて、php のライフサイクルについて説明し、どのフックが何を行うために拡張されているかを見てみましょう。 php ライフサイクルには、モジュール初期化ステージphp_module_startup、リクエスト初期化ステージphp_request_startup、スクリプト実行ステージphp_execute_script、リクエストシャットダウンステージの5つのステージがあります。 php_request_shutdown 、モジュールシャットダウンフェーズphp_module_shutdown、cliモードで以下に紹介します。

php_module_startup

まず、この段階で何が行われるかを見てみましょう。php エントリ ファイルがどこにあるかわからない場合は、gdb を使用してコール スタック、gdb ./ php

php_module_startup ブレーク ポイントで実行し、コール スタックを確認します。

b php_module_startup
(gdb) r test.php
bt
php_module_startup (sf=0x1406460 <cli_sapi_module>, 
    additional_modules=0x0, num_additional_modules=0)
    at /www/test/php/php-7.4.3/main/main.c:2098
#1  0x00000000008bae7c in php_cli_startup (
    sapi_module=0x1406460 <cli_sapi_module>)
    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:407
#2  0x00000000008bcc80 in main (argc=2, argv=0x1425af0)
    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:1323
ログイン後にコピー

はっきりとわかります。コール スタック内の実行プロセスを確認するには、/main/main.c ファイルに移動します。gdb を使用して、ステップごとに確認することもできます。ここでは、PHP 拡張機能に関連するいくつかの場所を示します。ガベージ コレクション、リクエストの初期化、登録された定数など、ここで実行されます。php.ini 設定ファイルの読み込みなど。

まずモジュールの読み込み方法を見てみましょう

/* startup extensions statically compiled in */
    if (php_register_internal_extensions_func() == FAILURE) {
        php_printf("Unable to start builtin modules\n");
        return FAILURE;
    }
ログイン後にコピー

ここで読み込みますphp の組み込みモジュールです。ここにはコア関数のみが掲載されています。最初に依存関係を確認してください

/* Check module dependencies */
    if (module->deps) {
        const zend_module_dep *dep = module->deps;

        while (dep->name) {
            if (dep->type == MODULE_DEP_CONFLICTS) {
                name_len = strlen(dep->name);
                lcname = zend_string_alloc(name_len, 0);
                zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);

                if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
                    zend_string_efree(lcname);
                    /* TODO: Check version relationship */
                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
                    return NULL;
                }
                zend_string_efree(lcname);
            }
            ++dep;
        }
    }
ログイン後にコピー
if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
        zend_hash_del(&module_registry, lcname);
        zend_string_release(lcname);
        EG(current_module) = NULL;
        zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
        return NULL;
    }
ログイン後にコピー

これが組み込みモジュールをロードする原則です。次に、ini に拡張機能をロードする方法を見てみましょう

php_ini_register_extensions();
ログイン後にコピー
zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb);
ログイン後にコピー

この関数を使用してロード

php_load_extension(char *filename, int type, int start_now)
ログイン後にコピー

これは、組み込みモジュールをロードする機能も実行します。

は、モジュール関数 function を登録するために module->functions を呼び出しています。これで、関数関数を helloworld_functions ここで

zend_module_entry helloworld_module_entry = {
    STANDARD_MODULE_HEADER,
    "helloworld",                    /* Extension name */
    helloworld_functions,            /* zend_function_entry */
    PHP_MINIT(helloworld),                            /* PHP_MINIT - Module initialization */
    NULL,                            /* PHP_MSHUTDOWN - Module shutdown */
    PHP_RINIT(helloworld),            /* PHP_RINIT - Request initialization */
    NULL,                            /* PHP_RSHUTDOWN - Request shutdown */
    PHP_MINFO(helloworld),            /* PHP_MINFO - Module info */
    PHP_HELLOWORLD_VERSION,        /* Version */
    PHP_MODULE_GLOBALS(pib),
    NULL,
    NULL,
    NULL,
    STANDARD_MODULE_PROPERTIES_EX
};
ログイン後にコピー
# に記述する必要がある理由がわかりました。 ##ここで、拡張機能のいくつかのフック関数を見てみましょう

/* start Zend extensions */
    zend_startup_extensions();
ログイン後にコピー
ここでの核心は

func(element->data)つまり、拡張機能の実行です

#PHP_MINIT

Function<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">element=l-&gt;head;     while (element) {         next = element-&gt;next;         if (func(element-&gt;data)) {             DEL_LLIST_ELEMENT(element, l);         }         element = next;     }</pre><div class="contentsignin">ログイン後にコピー</div></div>これで

PHP_MINIT

フックは多くの初期化関数を実行できることがわかりましたカスタム拡張関数クラスを登録する方法と拡張変数をphpに書き込む方法。 ini 、php の組み込み関数を書き換える方法、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">original = zend_hash_str_find_ptr(CG(function_table), &quot;var_dump&quot;, sizeof(&quot;var_dump&quot;)-1);     if (original != NULL) {         original-&gt;internal_function.handler = my_overwrite_var_dump;     }     zend_class_entry person;     INIT_CLASS_ENTRY(person,CLASS_NAME,person_functions);     zend_register_internal_class_ex(&amp;person,NULL);</pre><div class="contentsignin">ログイン後にコピー</div></div>ここでは var_dump 関数を書き換え、person クラスを登録します。まずここで紹介します。

次の記事

で php を渡す方法を紹介します。字句解析によるコード 構文解析により AST が生成され、zend 仮想マシンによる呼び出し用のオペコード命令がコンパイルされます。 推奨学習: 「

PHP ビデオ チュートリアル

以上がPHP拡張機能のカスタマイズ方法(2)フック関数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート