>  기사  >  백엔드 개발  >  PHP 모듈 개발 관련 지식 소개

PHP 모듈 개발 관련 지식 소개

伊谢尔伦
伊谢尔伦원래의
2017-06-22 13:55:391857검색

PHP 코드 아키텍처

PHP의 모든 부분은 TSRM이라는 레이어에 있습니다. TSRM 레이어는 스레드 보안 관리를 담당합니다. 맨 아래 SAPI는 명령줄 sapi와 같은 외부 서비스를 제공하는 인터페이스입니다. -fpm은 fastcgi의 sapi이고 apache의 모듈 모드도 sapi입니다.

PHP 커널 및 Zend 엔진은 요청 관리/네트워크 및 파일 작업을 담당하고 Zend 커널은 컴파일 및 작업을 담당합니다. 실행/메모리 및 리소스 할당

이 중 확장 계층이 있습니다. PHP의 대부분의 외부 인터페이스는 확장 계층을 통해 제공됩니다. 예를 들어 표준 및 문자열과 같은 언어 기반도 확장된 형태로 제공됩니다.

확장(나중에 모듈이라고 함)을 PHP에 로드하는 방법에는 정적 컴파일과 동적 링크의 두 가지가 있습니다. 정적 컴파일을 위해서는 PHP의 구성 스크립트를 다시 생성해야 하며, 이에 대해서는 여기서 설명하지 않습니다. 동적 링크 방법은 그런 다음 .so 파일을 동적으로 로드합니다.

.so 파일을 로드하는 방법에는 두 가지가 있습니다. 하나는 php.ini 파일에 쓰는 것입니다(예: Extension=apc.so). 코드('xxx.so')에서 dl을 사용합니다.

dl($library)

함수는 모듈을 로드하여 내부 기능을 사용할 수 있도록 하는 것입니다.

dl() 함수의 소스 코드는 다음과 같습니다. PHP 소스 코드 루트 디렉터리(약어로 PHP_SRC_HOME), PHP_SRC_HOME/ext/standard/dl.c, 주요 프로세스는 다음과 같습니다.

PHP_FUNCTION(dl)

PHPAPI PHP_FUNCTION(dl)  
{  
    //...  
    php_dl(filename, MODULE_TEMPORARY, return_value, 0 TSRMLS_CC);  
    //...   
}

php_dl

PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC)  
{  
    if (php_load_extension(file, type, start_now TSRMLS_CC) == FAILURE) {  
       //...  
}

php_load_extension

PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) {  
    //文件名解析相关  
      
    //加载动态链接库  
    handle = DL_LOAD(libpath);  
      
    //加载错误处理  
      
    //获取模块的get_module函数(重点, 模块初始入口)  
    get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");  
      
    //get_module函数获取错误处理  
      
    //那个get_module()得到struct zend_module_entry  
    module_entry = get_module();  
    //...  
      
    //注册模块(重点, 函数在这里被注册)  
    if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL) {  
        //错误处理  
    }  
      
    //模块启动(重点, PHP_MINIT_FUNCTION)  
    if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) {  
        //错误处理  
    }  
      
    //模块请求启动(重点, PHP_RINIT_FUNCTION)  
    if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {  
        //错误处理  
    }  
    return SUCCESS;  
}

process

get_module function

get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");

매크로 확장 후 이 코드는 다음과 같습니다.

get_module = (zend_module_entry *(*) (void)) dlsym(handle, "_get_module");

dlsym() 함수가 수행하는 작업은 이 코드를 쉽게 이해할 수 있습니다. 이는 방금 로드된 동적 링크 라이브러리에서

함수 포인터

를 얻는 것입니다. 우리가 모듈을 개발하는 이유는 당시 정의된 get_module 함수입니다.매크로 확장 후에는 다음과 같습니다(GNU의 속성과 C++의 extern "C"를 고려하지 않음).

zend_module_entry *get_module(void) { return &sample_module_entry; }

dl()을 넣어서 모듈 개발 중 정의에 연결됩니다. 모듈이 로드되면 사용자 정의된 zend_module_entry가 여기에서 전달되는 것을 볼 수 있습니다. module

module_entry = zend_register_module_ex(module_entry TSRMLS_CC)

위 코드는 php_load_extension 함수에서 추출되었습니다. 우리는 관심 있는 함수 등록을 찾기 위해 계속해서 zend_register_module_ex()를 드릴다운합니다.

if (module->functions && zend_register_functions(NULL, module->functions, NULL, module-> ;type TSRMLS_CC)==FAILURE) {

zend_register_functions 함수를 계속해서 살펴보세요:

ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ {  
    //...  
      
    //重点 如果没有函数符号表, 取全局函数符号表  
    if (!target_function_table) {  
        target_function_table = CG(function_table);  
    }  
      
    //...  
      
    //重点 循环zend_function_entry[]  
    while (ptr->fname) {  
        //向函数符号表增加函数  
        if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)?_function) == FAILURE) {  
            //错误处理  
        }  
      
        //...  
      
        //准备遍历zend_function_entry[]下一个元素  
        ptr++;  
      
        //...  
    }  
    //...  
      
    return SUCCESS;  
}

함수 기호 테이블을 얻을 때 CG 매크로가 사용됩니다. :

target_function_table = CG(function_table);

우리는 이를 두 가지 상황으로 나눕니다. 이 매크로를 잠금 해제합니다:

//非线程安全  
compiler_globals.function_table  
      
//线程安全  
(((zend_compiler_globals *) (*((void ***) tsrm_ls))[ compiler_globals_id - 1])-> function_table)

결국 그들이 얻는 것은 zend_compiler_globals에 있는 전역

struct struct

function_table 요소인 HashTable입니다.

다음 루프는 모듈을 개발할 때 zend_function_entry에 넣으면 이해하기 쉽습니다. 함수 탐색이 HashTable에 추가되어 괜찮습니다. 모듈 시작/모듈 요청 시작

이 두 부분은 이해하기 쉽습니다. 모듈 개발에서 각각 PHP_MINIT_FUNCTION() 및 PHP_RINIT_FUNCTION()에 해당

위 내용은 PHP 모듈 개발 관련 지식 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.