目次
1. RTLD_GLOBAL モードで PHP ダイナミック ライブラリを開きます
1. PHP ソース コード パッケージをダウンロードし、手動でコンパイルします。上記の組み込み使用と連携するには、?enable-embed オプション
ホームページ バックエンド開発 PHPチュートリアル PHP 拡張機能の開発に失敗した

PHP 拡張機能の開発に失敗した

Jun 23, 2016 pm 01:44 PM

失敗した PHP 拡張機能開発の旅

By warezhou 2014.11.19


Origin

継続的な反復の後、私たちの部門のコルーチンバージョンネットワークフレームワーク(CoSvr)フレーム)がついにリリースされました!これは元々は素晴らしいことでしたが、新しいサービスが継続的にアクセスされるにつれて、多くの固有の欠陥が徐々に表面化しました。 「過負荷保護」をサポートしていません

「ホットリスタート」をサポートしていません

  • 「64ビット」をサポートしていません
  • ... ...
  • 上級バックエンド開発者にとって、上記の問題はほとんどのそれらを識別するのは難しく、それらが問題になる理由は、「カエルをお湯でゆでる」ようなものです。反復プロセスにはマクロなビジョンが欠けており、導入されるビジネス機能が多すぎるため、全体的なアーキテクチャが不合理になります。最近の「コルーチン バージョン」は、元々は私の個人的なアマチュア作品で、ビジネス コードを楽しく書き、作業をすぐに終了するために、最下層はオリジナルの SvrFrame を直接再利用しました。結果はご想像のとおり、基盤が強力ではありません。大地が揺れる!最も極端な 64Bit を例に挙げると、誰もが数秒で理解できると思います。
  • 多くの調査と議論を経て、最終的に次のような方向性を出しました:
  • 社内オープンソース SPP3.0 フレームワークを導入し、基本的な周辺機能を吸収し、二次的なビジネス開発を行う

    SPP を拡張し、PHP をサポートする埋め込みプログラミング用のスクリプト言語であり、C 拡張機能の形で PHP にコルーチン機能を提供します (今後、PHPer は非同期コードを喜んで作成できるようになり、母はもう私のコールバックについて心配する必要がなくなりました!)

    難しい? 長くなりましたが、本題に入りましょう: C++/PHP 混合プログラミングを実装するにはどうすればよいでしょうか?

  • 免責事項:
  • 私は途中の修道士なので、丸一週間 PHP 拡張機能の開発に携わっていないため、「WHY」については触れず、「HOW」については記録目的のみにとどめることができれば幸いです。専門家なら許してくれるでしょう!
  • オープニング

    組み込み

    PHP 業界における C++/PHP の組み合わせは一般に「パフォーマンス」の考慮事項に基づいており、特定のパフォーマンスのボトルネック (PB シリアル化など) を解決するために PHP コード内で C/C++ 拡張機能を呼び出します。 )。

    C/C++ 開発者としては、「パフォーマンス」よりも「開発効率」の誘惑が明らかに大きいため、私たちのアイデアは、PHP をスクリプト言語として使用して、ビジネス ロジックを迅速に開発し、それを SPP フレームワークに挿入して実行することです。 。

    1. RTLD_GLOBAL モードで PHP ダイナミック ライブラリを開きます

    void *php_handler = dlopen("libphp5.so", RTLD_LAZY | RTLD_GLOBAL);if (!php_handler) {    base->log_.LOG_P_PID(LOG_FATAL, "%s\n", dlerror());    return -1; }   dlclose(php_handler);
    ログイン後にコピー

    2. php_embed_init を通じて初期化します

    php_embed_module.php_ini_path_override = "../php/php.ini";php_embed_init(0, NULL);
    ログイン後にコピー

    3. zend_eval_string は PHP スクリプトを導入します

    すごいです

    4. call_user_function による PHP 関数のコールバック

    zend_first_try {    char exec_str[256];    snprintf(exec_str, sizeof(exec_str), "include '%s';", "../php/demo_handler.php");    if (int ret = zend_eval_string(exec_str, NULL, exec_str TSRMLS_CC)) {        base->log_.LOG_P_PID(LOG_FATAL, "zend_eval_string fail. ret=%d\n", ret);        return -1;     }    base->log_.LOG_P_PID(LOG_DEBUG, "zend_eval_string succ.\n");} zend_catch {    base->log_.LOG_P_PID(LOG_FATAL, "zend_eval_string catch.\n");} zend_end_try ();
    ログイン後にコピー

    5. php_embed_shutdown によるクリーンアップ

    zval z_funcname;ZVAL_STRING(&z_funcname, "EchoDemo::init", 1);zval *zp_svr;MAKE_STD_ZVAL(zp_svr);ZVAL_LONG(zp_svr, (long)base);zval *zp_etc;MAKE_STD_ZVAL(zp_etc);ZVAL_STRING(zp_etc, etc, 1);zval z_retval;zval *z_params[] = {zp_svr, zp_etc};int call_ret = call_user_function(CG(function_table), NULL, &z_funcname, &z_retval, sizeof(z_params) / sizeof(z_params[0]), z_params TSRM convert_to_long(&z_retval);int func_ret = Z_LVAL_P(&z_retval);zval_ptr_dtor(&zp_etc);zval_dtor(&z_funcname);zval_dtor(&z_retval);if (call_ret < 0 || func_ret < 0) {    base->log_.LOG_P_PID(LOG_FATAL, "call_user_function fail. call_ret=%d func_ret=%d\n", call_ret, func_ret);    return -1;}
    ログイン後にコピー

    PHP

    PHP C 拡張機能の開発に関する記事はインターネット上にあります。興味のある読者は記事末尾の付録を詳しく読んでみてください。

    1. PHP ソース コード パッケージをダウンロードし、手動でコンパイルします。上記の組み込み使用と連携するには、?enable-embed オプション

    php_embed_shutdown(TSRMLS_C);
    ログイン後にコピー

    2 をオンにする必要があります。 PHP ソース コード パッケージの ext ディレクトリに入り、ext_skel ツールがプラグイン シェルフ コードを生成します

    ./configure --enable-embedmakemake install(可选)
    ログイン後にコピー

    3. config.m4 を編集し、PHP_ARG_WITH または PHP_ARG_ENABLE オプションをオンにします (正直に言うと、違いはまだ明確ではありません。アドバイスをお願いします)、C++ サポート、依存関係パスなどを追加します。

    cd ext./ext_skel --extname=demo
    ログイン後にコピー

    4.demo.cpp を編集し、拡張定義と実装 (関数、クラス、変数など) を追加します。 ) ここに挙げるのは関数定義の例だけです。クラスに興味のある読者は、付録に従って調べてください。ここで示した sendrecv 関数の定義は比較的代表的なもので、3 番目のパラメーター rsp は、受信したデータを PHP 呼び出し元に返す責任があります

    PHP_ARG_ENABLE(demo, whether to enable demo support,    [  --enable-demo           Enable demo support])if test "$PHP_DEMO" != "no"; then  PHP_REQUIRE_CXX()  PHP_ADD_LIBRARY(stdc++, 1, EXTRA_LDFLAGS)  PHP_ADD_INCLUDE(/root/spp/module/include/)  PHP_ADD_INCLUDE(/root/spp/module/include/spp_incl/)  PHP_NEW_EXTENSION(demo, demo.cpp, $ext_shared)fi
    ログイン後にコピー
    ZEND_BEGIN_ARG_INFO_EX(arginfo_sendrecv, 0, 0, 7)    ZEND_ARG_INFO(0, req)    ZEND_ARG_INFO(0, req_len)    ZEND_ARG_INFO(1, rsp)    ZEND_ARG_INFO(0, rsp_len)    ZEND_ARG_INFO(0, ip)    ZEND_ARG_INFO(0, port)    ZEND_ARG_INFO(0, timeout)ZEND_END_ARG_INFO()PHP_FUNCTION(sendrecv){    char *req = NULL;    int req_str_len = 0;    long req_len = 0;    zval *rsp = NULL;    long rsp_len = 0;    char *ip = NULL;    int ip_str_len = 0;    long port = 0;    long timeout = 0;if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slzlsll", &req, &req_str_len,&req_len, &rsp, &rsp_len, &ip, &ip_str_len, &port, &timeout) == FAILURE) {        return;}       struct sockaddr_in addr;    memset(&addr, 0, sizeof(addr));    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr(std::string(ip, ip_str_len).c_str());    addr.sin_port = htons(port);    char *rsp_buf = (char *)emalloc(rsp_len);    int rsp_buf_len = rsp_len;    if (int ret = mt_udpsendrcv(&addr, req, req_len > req_str_len ? req_str_len : req_len, rsp_buf, rsp_buf_len, timeout)) {        efree(rsp_buf);        RETURN_LONG(ret);    }    zval_dtor(rsp);    ZVAL_STRINGL(rsp, rsp_buf, rsp_buf_len, 0);    RETURN_LONG(0);}
    ログイン後にコピー

    5。私は個人的には動的コンパイルを好みます (静的コンパイルには php ソース コードの再コンパイルが必要ですが、これは非常に時間がかかり、手間がかかります)。 6. php.ini ファイルを編集し、新しい拡張機能を追加すると、PHP コードで新しい拡張機能を呼び出すことができます

    クライマックス

    いよいよ、EchoDemo をいくつかプレイしてみました。 telnetとsaw エコーが一行ずつ表示されるので非常に気持ちいいです。

    const zend_function_entry demo_functions[] = {    PHP_FE(sendrecv, arginfo_sendrecv)    PHP_FE_END  /* Must be the last line in demo_functions[] */};
    ログイン後にコピー

    ここで最も優れているのは、プロセス関数の sendrecv への拡張呼び出しです。非同期ネットワーク インタラクションは、バックグラウンドでコルーチンを介して実装されています。同期 CGI のようなロジック コードを作成できるだけでなく、それを簡単に楽しむこともできます。非同期の高い同時実行性。

    願いは美しいけど現実は残酷!

    私は突然アイデアを思いつきました。パフォーマンスのストレス テストを行って、ネイティブ C++ コードと比較してどの程度パフォーマンスが低下するかを確認してみましょう。 1KB の単一リクエストが適用され、1w/s の圧力が適用されました。しばらくすると、コアダンプが抑制されました。

    メモリリーク?コルーチンスタックオーバーフロー? ...

    期間中色々紆余曲折あり、GDB、コルーチンのスタックサイズ変更、Google、PHPerの相談…

    すぐに夜になり、確認すべきことは確認した、質問は全て完了それは尋ねる必要がありますが、私にできることは何もありません。わかりました。お茶を飲みに立ち寄ってください。「call_user_function は再入可能ですか?」このレベルを考えると、コルーチンの性質を理解している兄弟ならすぐに理解できると思います。「くそー、Zend を実装するとき、呼び出し元のスレッドがユーザー モード スケジューリングのためにコルーチンを実行することをどのようにして知ることができるのでしょうか。これではすべてが可能です。」ブラックボックス。 !グローバル変数、静的変数...

    さて、sendrecv などのコルーチンベースの拡張機能を削除して、テストを再負荷します。単一のワーカーは、ストレスなく 3w/s のエコーを処理できます。

    エンディング

    今回の最大の魅力の一つは結局実現には至りませんでしたが、考えることは一人で行動するよりも100倍効率的であるという視点を改めて確認できたのでとても満足しています

    特に難しい問題に対処する場合、頭のないハエが飛び回るのは報われないことがよくあります。このとき、落ち着いて既存の知識の蓄えを収集することに全力を尽くすことができれば、もしかしたらインスピレーションが訪れるかもしれません。

    今後の可能性のある方向性: PHP はバージョン 5.5 から yield を導入しました。Zend の yield サポートの詳細を掘り下げれば、それを C フレームワークとうまく統合できるかもしれないと感じていますが、これには大きな穴があるといつも感じています。それは埋めることができません。他の要因を差し置いても、私はやはり Golang のような言語を選択して goroutine の利点を直接享受したいと思うかもしれません (笑)。 付録

    PHP 拡張機能の開発とカーネル アプリケーション

    http://www.walu.cc/phpbook/preface.md

    PHP 拡張機能をコンパイルする 2 つの方法

    http://521-wf.com/archives/ 227 .html

    C++ を使用して PHP 拡張機能を開発する方法 (パート 1)

    http://521-wf.com/archives/241.html

    C++ を使用して PHP 拡張機能を開発する方法 (パート 2)

    http ://521-wf.com/archives/245.html

    PHP 拡張機能での C++ クラスのラップ


    http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension /

    🎜
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    Video Face Swap

    Video Face Swap

    完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    PHPのさまざまなエラータイプを説明します(通知、警告、致命的なエラー、解析エラー)。 PHPのさまざまなエラータイプを説明します(通知、警告、致命的なエラー、解析エラー)。 Apr 08, 2025 am 12:03 AM

    PHPには4つの主要なエラータイプがあります。1。notice:わずかなものは、未定義の変数へのアクセスなど、プログラムを中断しません。 2。警告:通知よりも深刻で、ファイルを含むなど、プログラムを終了しません。 3。ファタラー:最も深刻なのは、機能を呼び出すなど、プログラムを終了します。 4。ParseError:構文エラーは、エンドタグの追加を忘れるなど、プログラムの実行を防ぎます。

    PHPとPython:2つの一般的なプログラミング言語を比較します PHPとPython:2つの一般的なプログラミング言語を比較します Apr 14, 2025 am 12:13 AM

    PHPとPythonにはそれぞれ独自の利点があり、プロジェクトの要件に従って選択します。 1.PHPは、特にWebサイトの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンス、機械学習、人工知能に適しており、簡潔な構文を備えており、初心者に適しています。

    PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? Apr 17, 2025 am 12:06 AM

    PHPでは、Password_hashとpassword_verify関数を使用して安全なパスワードハッシュを実装する必要があり、MD5またはSHA1を使用しないでください。 1)password_hashセキュリティを強化するために、塩値を含むハッシュを生成します。 2)password_verifyハッシュ値を比較して、パスワードを確認し、セキュリティを確保します。 3)MD5とSHA1は脆弱であり、塩の値が不足しており、最新のパスワードセキュリティには適していません。

    アクション中のPHP:実際の例とアプリケーション アクション中のPHP:実際の例とアプリケーション Apr 14, 2025 am 12:19 AM

    PHPは、電子商取引、コンテンツ管理システム、API開発で広く使用されています。 1)eコマース:ショッピングカート機能と支払い処理に使用。 2)コンテンツ管理システム:動的コンテンツの生成とユーザー管理に使用されます。 3)API開発:RESTFUL API開発とAPIセキュリティに使用されます。パフォーマンスの最適化とベストプラクティスを通じて、PHPアプリケーションの効率と保守性が向上します。

    HTTPリクエストメソッド(取得、投稿、配置、削除など)とは何ですか?それぞれを使用する必要がありますか? HTTPリクエストメソッド(取得、投稿、配置、削除など)とは何ですか?それぞれを使用する必要がありますか? Apr 09, 2025 am 12:09 AM

    HTTPリクエストメソッドには、それぞれリソースを取得、送信、更新、削除するために使用されるGET、POST、PUT、および削除が含まれます。 1. GETメソッドは、リソースを取得するために使用され、読み取り操作に適しています。 2. POSTメソッドはデータの送信に使用され、新しいリソースを作成するためによく使用されます。 3. PUTメソッドは、リソースの更新に使用され、完全な更新に適しています。 4.削除メソッドは、リソースの削除に使用され、削除操作に適しています。

    PHP:Web開発の重要な言語 PHP:Web開発の重要な言語 Apr 13, 2025 am 12:08 AM

    PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

    PHPは、ファイルを安全に処理する方法をどのように処理しますか? PHPは、ファイルを安全に処理する方法をどのように処理しますか? Apr 10, 2025 am 09:37 AM

    PHPは、$ \ _ファイル変数を介してファイルのアップロードを処理します。セキュリティを確保するための方法には次のものが含まれます。1。アップロードエラー、2。ファイルの種類とサイズを確認する、3。ファイル上書きを防ぐ、4。ファイルを永続的なストレージの場所に移動します。

    PHP OOPで、self ::、parent ::、and static ::の違いを説明します。 PHP OOPで、self ::、parent ::、and static ::の違いを説明します。 Apr 09, 2025 am 12:04 AM

    Phpoopでは、self ::は現在のクラスを指し、親::は親クラスを指し、静的::は後期静的結合に使用されます。 1.Self ::静的方法と一定の呼び出しに使用されますが、後期静的結合をサポートしていません。 2.Parent ::サブクラスには、親クラスのメソッドを呼び出すために使用され、プライベートメソッドにアクセスできません。 3.Static ::継承と多型に適した後期静的結合をサポートしますが、コードの読みやすさに影響を与える可能性があります。

    See all articles