>  기사  >  백엔드 개발  >  PHP 커널 SAPI 탐색 예제 공유

PHP 커널 SAPI 탐색 예제 공유

小云云
小云云원래의
2018-03-08 10:57:411355검색

PHP는 간단하고 강력한 언어로서 웹에 적합한 다양한 언어 기능을 제공할 수 있습니다. 연습부터 시작해 약한 유형의 변수의 원리를 살펴본 후 Wang Shuai는 계속해서 PHP 커널의 몇 가지 공통 부분을 명확히 설명할 것입니다. 이번 문제는 SAPI에 대한 심층적인 이해입니다.

SAPI는 Server Application Programing Interface의 약어입니다. PHP는 애플리케이션과 PHP 커널 간의 데이터 상호 작용을 위해 SAPI를 통해 인터페이스 세트를 제공합니다.

간단히 말하면 함수의 입력 및 출력과 마찬가지로 Linux 명령줄을 통해 PHP 코드 조각을 실행합니다. 핵심은 Linux Shell이 ​​Zend 엔진이 실행된 후 일련의 매개변수를 전달한다는 것입니다. , 쉘에 표시된 프로세스로 돌아갑니다. 마찬가지로 Apache를 통해 PHP가 호출되고, Zend 엔진이 실행된 후 Apache로 데이터가 반환되고, Apache가 이를 페이지에 표시합니다.

그림 1. PHP 아키텍처 다이어그램

PHP는 apache, apache2filter, apache2handler, caudium, cgi, cgi-fcgi, cli, cli-server, 연속성, embed, isapi, litespeed, milter, nsapi를 포함한 다양한 형태의 인터페이스를 제공합니다. , phttpd pi3web, roxen, thttpd, tux 및 webjames. 그러나 일반적으로 사용되는 형식은 CLI/CGI(명령줄), Multiprocess(다중 프로세스), Multithreaded(다중 스레드), FastCGI 및 Embedded(임베디드)의 5가지뿐입니다.

PHP는 현재 SAPI 인터페이스 유형을 볼 수 있는 기능을 제공합니다:

string php_sapi_name ( void )

PHP 실행 및 로드

어떤 SAPI가 사용되든 관계없이 PHP가 스크립트를 실행하기 전후에는 일련의 이벤트가 포함됩니다: 모듈의 초기화(MINT) 및 종료(MSHUTDOWN), 요청의 Init(RINT) 및 종료(RSHUTDOWN). 첫 번째 단계는 확장된 내부 변수를 초기화하고, 리소스를 할당하고, 리소스 프로세서를 등록할 수 있는 PHP 모듈 초기화 단계(MINT)입니다. 이 프로세스는 전체 PHP 인스턴스 수명 주기 동안 한 번만 실행됩니다.

PHP 모듈이란 무엇인가요? 위의 PHP 아키텍처 다이어그램을 통해 PHP의 get_loaded_extensions 함수를 사용하여 컴파일되고 로드된 모든 모듈/확장을 볼 수 있습니다. 이는 CLI 모드의 php -m과 동일합니다.

PHP의 Memcached 확장 소스 코드를 예로 들어 보겠습니다.

PHP_MINIT_FUNCTION(memcached) { 	
	zend_class_entry ce;  	
	memcpy(&memcached_object_handlers,zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 	
memcached_object_handlers.clone_obj = NULL;  	/* 执行了一些类似的初始化操作 */  	
return SUCCESS; 
}

두 번째 단계는 RINT(요청 초기화 단계)입니다. 모듈이 초기화되고 활성화되면 PHP 실행 환경이 생성되고 RINT 기능이 모두 등록됩니다. 모듈은 동시에 호출되어 특정 환경 변수를 설정하거나 리소스를 할당하거나 감사와 같은 다른 작업을 수행합니다.

PHP_RINIT_FUNCTION(memcached) { 	
	/* 执行一些关于请求的初始化 */  	
	return SUCCESS; 
}

3단계에서는 요청 처리가 완료된 후 재활용을 위해 PHP_RSHUTDOWN_FUNCTION이 호출됩니다. 이는 최종 정리 작업을 수행하기 위한 각 확장의 요청 닫기 함수입니다. Zend 엔진은 정리 프로세스, 가비지 수집을 수행하고 이전 요청 중에 사용된 모든 변수를 설정 해제합니다. 요청은 스크립트를 실행하거나 die() 또는 exit() 함수를 호출하여 완료할 수 있습니다. 네 번째 단계에서는 PHP 수명 주기가 종료되면 PHP_MSHUTDOWN_FUNCTION이 각 확장 모듈을 종료합니다. 자체 커널 하위 시스템을 종료하는 데 사용됩니다.

PHP_MSHUTDOWN_FUNCTION(memcached) { /* 执行关于模块的销毁工作 */ UNREGISTER_INI_ENTRIES(); return SUCCESS; }

공통 작동 모드

5가지 공통 SAPI 모드가 있습니다:

    CLI 및 CGI 모드(단일 프로세스 모드)
  • 다중 프로세스 모드
  • 다중 스레드 모드
  • FastCGI 모드
  • Embedded
  • 1. CLI/CGI 모드

CLI와 CGI 모두 단일 프로세스 모드이며, PHP의 수명 주기는 한 번의 요청으로 완료됩니다. 즉, PHP 스크립트가 실행될 때마다 두 번째 부분에서 언급한 4개의 INT 및 Shutdown 이벤트가 실행됩니다.

그림 2. CGI/CLI 수명 주기


2. 다중 프로세스 모드(Multiprocess)

다중 프로세스 모드는 PHP를 웹 서버에 구축할 수 있으며, PHP는 Apache 이후의 prefork MPM 모드 및 APXS 모듈로 컴파일될 수 있습니다. 시작되면 많은 하위 프로세스가 분기되고 각 하위 프로세스는 자체의 독립적인 프로세스 주소 공간을 갖습니다.

그림 3. 다중 프로세스 모드 수명 주기


자식 프로세스에서 PHP의 수명 주기는 MINT를 호출하여 여러 요청(RINT/RSHUTDOWN)을 시작하고 실행하는 것입니다. Apache가 종료될 때까지 호출되지 않습니다. 그렇지 않으면 MSHUTDOWN이 재활용 단계로 진행됩니다.

그림 4. 다중 프로세스의 수명 주기


다중 프로세스 모델에서는 각 하위 프로세스가 코드와 데이터를 공유하지 않고 독립적으로 실행됩니다. 따라서 하나의 하위 프로세스가 종료, 종료 및 재생성되더라도 영향을 받지 않습니다. 다른 하위 프로세스의 안정성.

3. 멀티스레드 모드(Multithreaded)

Apache2의 Worker MPM은 멀티스레딩 모델을 채택하여 하나의 프로세스에서 여러 스레드를 생성하고 동일한 프로세스 주소 공간에서 실행합니다.

그림 5. 멀티 스레드 수명 주기

4. FastCGI 모드

우리가 사용하는 Nginx+PHP-FPM에서는 FastCGI 모드를 사용하며 이는 CGI의 상주 프로세스 유형입니다. 동적으로 시간을 소비하지 않고 실행 후 여러 프로세스를 분기합니다. 하위 프로세스를 분기하므로 모든 요청에 ​​대해 MINT/MSHUTDOWN을 호출할 필요가 없습니다. PHP는 PHP-FPM을 통해 FastCGI의 프로세스 풀을 관리하고 예약합니다. Nginx와 PHP-FPM은 로컬 TCP 소켓과 Unix 소켓을 통해 통신합니다.

그림 6. FastCGI 모드 수명 주기

PHP-FPM进程管理器自身初始化,启动多个CGI解释器进程等待来自Nginx的请求。当客户端请求达到PHP-FPM,管理器选择到一个CGI进程进行处理,Nginx将CGI环境变量和标准输入发送到一个PHP-CIG子进程。PHP-CGI子进程处理完成后,将标准输出和错误信息返回给Nginx,当PHP-CGI子进程关闭连接时,请求处理完成。PHP-CGI子进程等待着下一个连接。

可以想象CGI的系统开销有多大。每一个Web 请求PHP都必须重新解析php.ini、载入全部扩展并始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。另外,对于数据库和Memcache的持续连接可以工作。

5. 内嵌模式(Embedded)

Embed SAPI是一种特殊的SAPI,允许在C/C++语言中调用PHP提供的函数。这种SAPI和CLI模式一样,按照Module Init => Request Init => Request => Request Shutdown => Module Shutdown的模式运行。

Embed SAPI可以调用PHP丰富的类库,也可以实现高级玩法,比如可以查看PHP的OPCODE(PHP执行的中间码,Zend引擎的指令,由PHP代码生成)。

详细请见: http://www.laruence.com/2008/09/23/539.html

SAPI的运行机制

我们以CGI为例,看一下SAPI的运行机制。

static sapi_module_struct cgi_sapi_module = {     
	"cgi-fcgi",                     /* 输出给php_info()使用 */     "CGI/FastCGI",                  /* pretty name */      
	php_cgi_startup,                /* startup 当SAPI初始化时,首先会调用该函数 */     
	php_module_shutdown_wrapper,    /* shutdown  关闭函数包装器,它用来释放所有的SAPI的数据结构、内存等,调用php_module_shutdown */      
	sapi_cgi_activate,              /* activate  此函数会在每个请求开始时调用,它会做初始化,资源分配 */     
	sapi_cgi_deactivate,            /* deactivate  此函数会在每个请求结束时调用,它用来确保所有的数据都得到释放 */      
	sapi_cgi_ub_write,              /* unbuffered write  不缓存的写操作(unbuffered write),它是用来向SAPI外部输出数据 */     
	sapi_cgi_flush,                 /* flush  刷新输出,在CLI模式下通过使用C语言的库函数fflush实现*/     NULL,                           /* get uid */     
	sapi_cgi_getenv,                /* getenv 根据name查找环境变量 */      
	php_error,                      /* error handler 注册错误处理函数  */      
	NULL,                           /* header handler PHP调用header()时候被调用 */     
	sapi_cgi_send_headers,          /* send headers handler 发送头部信息*/     
	NULL,                           /* send header handler 发送一个单独的头部信息 */      
	sapi_cgi_read_post,             /* read POST data  当请求的方法是POST时,程序获取POST数据,写入$_POST数组 */     
	sapi_cgi_read_cookies,          /* read Cookies 获取Cookie值  */      
	sapi_cgi_register_variables,    /* register server variables 给$_SERVER添加环境变量 */     
	sapi_cgi_log_message,           /* Log message 输出错误信息 */     
	NULL,                           /* Get request time */     
	NULL,                           /* Child terminate */      
	STANDARD_SAPI_MODULE_PROPERTIES 
};

由上面代码可见,PHP的SAPI像是面向对象中基类,SAPI.h和SAPI.c包含的函数是抽象基类的声明和定义,各个服务器用的SAPI模式,则是继承了这个基类,并重新定义基类方法的子类。

总结

PHP的SAPI是Zend引擎提供的一组标准交互接口,通过注册初始化、析构、输入、输出等接口,我们可以将应用程序运行在Zend引擎上,也可以把PHP嵌入到类似Apache的Web Server中。PHP常见的SAPI模式有五种,CGI/CLI模式、多进程模式、多线程模式、FastCGI模式和内嵌模式。

了解PHP的SAPI机制意义重大,帮助我们理解PHP的生命周期,并了解如何更好的通过C/C++为PHP编写扩展,并在生命周期中找到提高系统性能的方式。

相关推荐:

详解PHP内核解释器的执行

PHP内核-简单讲解PHP灵魂HashTble

PHP内核--探究内存管理与缓存机制的图文详解

위 내용은 PHP 커널 SAPI 탐색 예제 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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