2012-10-10 66 views
1

好的,我有這個瘋狂的想法,因爲php不能和G-WAN一起玩,也許解決方法是使用phalanger將php代碼編譯爲c#單聲道程序集,然後在g-wan中使用它?G-WAN + Phalanger

任何人都有這種組合的經驗,可以幫助嗎?

也許我錯了,G灣可以運行PHP?

+0

這是一個好主意。新版本發佈後,我會試一試。 (當前版本沒有C#單聲道支持) –

+0

我知道,本月3.9。 – Programista

+0

因此,任何人或有人知道如何直接運行PHP,G灣站點缺乏文檔? – Programista

回答

1

好吧,我確實聯繫了Phalanger(以及其他一些解決方案)後面的人員來增加對PHP的支持。他們的答覆(當時)是Phalanger不再發展。

現在它已被重新實現爲CLR語言,這可能會給PHP帶來第二次生命。雖然我已經使用了G-WAN 3.9測試版,但我還沒有嘗試使用Mono運行時支持的各種語言。

至於真正的PHP庫,我寫了下面的代碼,使其運行:

// ---------------------------------------------------------------------------- 
// php.c: G-WAN using PHP scripts 
// 
// To build PHP5: 
// 
// CFLAGS="-O3" ./configure --enable-embed --enable-maintainer-zts --with-tsrm-pthreads --without-pear 
// make clean 
// make 
// sudo make install 
/* Installing PHP SAPI module:  embed 
     Installing PHP CLI binary:  /usr/local/bin/ 
     Installing PHP CLI man page:  /usr/local/php/man/man1/ 
     Installing PHP CGI binary:  /usr/local/bin/ 
     Installing build environment:  /usr/local/lib/php/build/ 
     Installing header files:   /usr/local/include/php/ 
     Installing helper programs:  /usr/local/bin/ 
     program: phpize 
     program: php-config 
     Installing man pages:    /usr/local/php/man/man1/ 
     page: phpize.1 
     page: php-config.1 
     Installing PEAR environment:  /usr/local/lib/php/ 
     [PEAR] Archive_Tar - already installed: 1.3.7 
     [PEAR] Console_Getopt - already installed: 1.3.0 
     [PEAR] Structures_Graph- already installed: 1.0.4 
     [PEAR] XML_Util  - already installed: 1.2.1 
     [PEAR] PEAR   - already installed: 1.9.4 
     Wrote PEAR system config file at: /usr/local/etc/pear.conf 
     You may want to add: /usr/local/lib/php to your php.ini include_path 
     /home/pierre/Downloads/PHP/php5.4-20/build/shtool install -c ext/phar/phar.phar /usr/local/bin 
     ln -s -f /usr/local/bin/phar.phar /usr/local/bin/phar 
     Installing PDO headers:   /usr/local/include/php/ext/pdo/  */ 
/*  
     enabling the 'thread safety' --enable-maintainer-zts option results in: 

      error: 'tsrm_ls' undeclared (first use in this function) 
*/  
/* 
tsrm_ls 
    TSRM local storage - This is the actual variable name being passed around 
    inside the TSRMLS_* macros when ZTS is enabled. It acts as a pointer to 
    the start of that thread's independent data storage block. 

TSRM 
    Thread Safe Resource Manager - This is an oft overlooked, and seldom if 
    ever discussed layer hiding in the /TSRM directory of the PHP source code. 
    By default, the TSRM layer is only enabled when compiling a SAPI which 
    requires it (e.g. apache2-worker). All Win32 builds have this layer 
    enabled enabled regardless of SAPI choice. 

ZTS 
    Zend Thread Ssafety - Often used synonymously with the term TSRM. 
    Specifically, ZTS is the term used by ./configure 
    (--enable-experimental-zts for PHP4, --enable-maintainer-zts for PHP5), 
    and the name of the #define'd preprocessor token used inside the engine 
    to determine if the TSRM layer is being used.  

TSRMLS_?? 
    A quartet of macros designed to make the differences between ZTS and 
    non-ZTS mode as painless as possible. When ZTS is not enabled, all 
    four of these macros evaluate to nothing. When ZTS is enabled however, 
    they expand out to the following definitions: 

     TSRMLS_C tsrm_ls 
     TSRMLS_D void ***tsrm_ls 
     TSRMLS_CC , tsrm_ls 
     TSRMLS_DC , void ***tsrm_ls  


    PHP relies on global variables from resource type identifiers, to 
    function callback pointers, to request specific information such as 
    the symbol tables used to store userspace variables. Attempting to 
    pass these values around in the parameter stack would be more than 
    unruly, it'd be impossible for an application like PHP where it's 
    often necessary to register callbacks with external libraries which 
    don't support context data. 

    So common information, like the execution stack, the function and 
    class tables, and extension registries all sit up in the global 
    scope where they can be picked up and used at any point in the 
    application.  

    For single-threaded SAPIs like CLI, Apache1, or even Apache2-prefork, 
    this is perfectly fine. Request specific structures are initialized 
    during the RINIT/Activation phase, and reset back to their original 
    values during the RSHUTDOWN/Deactivation phase in preparation for 
    the next request. A given webserver like Apache1 can serve up multiple 
    pages at once because it spawns multiple processes each in their own 
    process space with their own independant copies of global data.  

    The trouble starts with threaded webservers like Apache2-worker, or IIS 
    where two or more threads trying to run the a request at the same time. 
    Each thread wants to use the global scope to store its request-specific 
    information, and tries to do so by writing to the same 
    storage space. At the least, this would result in userspace variables 
    declared in one script showing up in another. In practice, it leads to 
    quick and disasterous segfaults and completely unpredictable behavior as 
    memory is double freed or written with conflicting information by separate 
    threads.   

*/ 
#pragma include "/usr/local/include/php" 
#pragma include "/usr/local/include/php/main" 
#pragma include "/usr/local/include/php/TSRM" 
#pragma include "/usr/local/include/php/Zend" 
#pragma link "/usr/local/lib/libphp5.so" 

#include "gwan.h" // G-WAN exported functions 

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/syscall.h> 

#include <php/sapi/embed/php_embed.h> 
#include <php/Zend/zend_stream.h> 

static pid_t gettid(void) { return syscall(__NR_gettid); } 

// PHP 
static int ub_write(const char *str, unsigned int str_len TSRMLS_DC) 
{ 
    puts(str); // this is the stdout output of a PHP script 
    return 0; 
} 

static void log_message(char * message) 
{ 
    printf("log_message: %s\n", message); 
} 

static void sapi_error(int type, const char * fmt, ...) { } 

static void php_set_var(char *varname, char *varval) 
{ 
    zval *var; 
    MAKE_STD_ZVAL(var); 
    ZVAL_STRING(var, varval, 1); 
    zend_hash_update(&EG(symbol_table), varname, strlen(varname) + 1, 
        &var, sizeof(zval*), NULL); 
} 

static char *php_get_var(char *varname) 
{ 
    zval **data = NULL; 
    char *ret = NULL; 
    if(zend_hash_find(&EG(symbol_table), varname, strlen(varname) + 1, 
        (void**)&data) == FAILURE) 
    { 
     printf("Name not found in $GLOBALS\n"); 
     return ""; 
    } 

    if(!data) 
    { 
     printf("Value is NULL (not possible for symbol_table?)\n"); 
     return ""; 
    } 

    ret = Z_STRVAL_PP(data); 
    return ret; 
} 

static int php_init(void) 
{ 
    static int once = 0; 
    if(once) return 0; 

    once = 1; 
    static char *myargv[2] = {"toto.php", NULL}; 
    php_embed_module.log_message = log_message; 
    php_embed_module.sapi_error = sapi_error; 
    php_embed_module.ub_write = ub_write; 
    if(php_embed_init(1, myargv PTSRMLS_CC) == FAILURE) 
    { 
     printf("php_embed_init error\n"); 
     return 1; 
    } 
    return 0; 
} 

static void php_shutdown() 
{ 
    php_embed_shutdown(TSRMLS_C); 
} 

static int php_exec(char *str) 
{ 
    zval ret_value; 
    int exit_status; 
    zend_first_try 
    { 
     PG(during_request_startup) = 0; 

     // run the specified PHP script file 
     // sprintf(str, "include (\"% s \ ");", scriptname); 

     zend_eval_string(str, &ret_value, "toto.php" TSRMLS_CC); 

     exit_status = Z_LVAL(ret_value); 
    } zend_catch 
    { 
     exit_status = EG(exit_status); 
    } 
    zend_end_try(); 
    return exit_status; 
} 

__thread char reply_num[8] = {0}; 
__thread pid_t tid = 0; 

int main(int argc, char *argv[]) 
{ 
    if(!tid) 
    { 
     tid = gettid(); 
     s_snprintf(reply_num, 8, "%u", tid); 
     php_init(); 
    } 

    xbuf_t *reply = get_reply(argv); 
    //php_set_var("argv", argv[0]); 
    php_set_var(reply_num, ""); 

    char fmt[] = //"print(\"from php [$test]\n\");\n" 
       "$reply%s = \"Hello World (PHP)\";\n"; 
    char php[sizeof(fmt) + sizeof(reply_num) + 2]; 
    s_snprintf(php, sizeof(php), fmt, reply_num); 

    php_exec(php); 

    xbuf_cat(reply, php_get_var(reply_num)); 
    return 200; 
} 

如果有人可以與多個工作線程此代碼的工作沒有崩潰的PHP runtime,然後PHP會添加到G-WAN。

這裏是G-WAN與一個單一的工作線程產生:

----------------------------------------------------- 
weighttp -n 100000 -c 100 -t 1 -k "http://127.0.0.1:8080/?php.c" 

finished in 0 sec, 592 millisec, **168744 req/s**, 48283 kbyte/s 
requests: 100000 total/started/done/succeeded, 0 failed/errored 
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx 
traffic: 29299985 bytes total, 27599985 bytes http, 
     1700000 bytes data 
----------------------------------------------------- 

這將是巨大的,解決這個PHP線程問題。感謝您幫助任何人!

+0

由於缺乏更好的解決方案,我已經將其設置爲答案,g-wan應該有自己的論壇。 如何獲得g-wan 3.9 beta吉爾?你在g-wan工作嗎?那麼請告訴Pierre,我們非常需要更多的代碼示例和g-wan示例。 – Programista

+0

G-WAN有一個由G-WAN用戶Paco主持的論壇,但他最近放棄了這個論壇。 Stackoverflow是一個體面的選擇。我是G-WAN開發團隊的一員,但公司註冊用戶也可以訪問beta版。對於「更多示例」請求(其中已有60個可用),請嘗試更具體:告訴您希望G-WAN展示如何操作。爲此,G-WAN網站上有一個聯繫表格。 – Gil

+0

Gil以前是G-WAN訂購的一部分,可以訪問「僅限會員」論壇。這仍然是計劃的一部分嗎? – Tim

2

有人試過PH7

PH7是一個PHP引擎,它允許宿主應用程序編譯和執行PHP腳本進程中

作爲一個嵌入式解釋器,它允許多個解釋器狀態在同一個程序中共存,而不會在它們之間產生任何干擾。

PH7是線程安全的

但爲了線程安全,PH7必須在定義PH7_ENABLE_THREADS編譯時指令的情況下編譯。