php sapi linux,PHP内核 - SAPI - Cli

一、Cli 基本常识

Cli(Command Line Interface),即命令行接口,用于在命令行下执行PHP脚本,它是执行PHP脚本最简便的一种方式。

Cli模式通过执行编译的PHP二进制程序即可启动,它定义了很多命令行参数,不同的参数对应不同的处理,比如:

(1)执行PHP脚本文件、直接执行PHP代码(-r参数)

(2)输出PHP版本(-v参数)

(3)输出已安装的扩展(-m参数)

(4)指定php.ini配置(-c参数)

二、Cli 执行流程

Cli 是单进程模式,处理完请求后就直接关闭了,生命周期先后经历module startup、request startup、request shutdown、module shutdown,其执行流程比较简单,关键的处理过程如下:

main() -> php_cli_startup() -> do_cli() -> php_module_shutdown()

Cli SAPI的main函数位于 /sapi/cli/php_cli.c中,执行时首先解析命令行参数,然后初始化sapi_module_struct,它是记录SAPI信息的主要结构,这个结构中有几个函数指针,它们是内核定义的操作接口的具体实现,用来告诉内核如何读取、输出数据。

staticsapi_module_struct cli_sapi_module={

"cli",/* name */

"Command Line Interface",/* pretty name */

php_cli_startup,/* startup */

php_module_shutdown_wrapper,/* shutdown */

// 请求初始化函数

NULL,/* activate */

// 请求收尾处理函数,Cli中:fflush(stdout)

sapi_cli_deactivate,/* deactivate */

sapi_cli_ub_write,/* unbuffered write */

sapi_cli_flush,/* flush */

NULL,/* get uid */

NULL,/* getenv */

php_error,/* error handler */

// 调用header()函数的处理handle

sapi_cli_header_handler,/* header handler */

// 发送header时的函数

sapi_cli_send_headers,/* send headers handler */

sapi_cli_send_header,/* send header handler */

// 获取POST数据的函数

NULL,/* read POST data */

sapi_cli_read_cookies,/* read Cookies */

// 向$_SERVER中注册变量的函数

sapi_cli_register_variables,/* register server variables */

sapi_cli_log_message,/* Log message */

NULL,/* Get request time */

NULL,/* Child terminate */

STANDARD_SAPI_MODULE_PROPERTIES

};

(1)在完成参数的解析及sapi_module_struct的基本初始化后,进入module_startup阶段。

if(sapi_module->startup(sapi_module)==FAILURE){

exit_status=1;

gotoout;

}

(2)前面定义的startup函数为php_cli_startup(),这个函数直接调用了php_module_startup()

staticintphp_cli_startup(sapi_module_struct*sapi_module)

{

if(php_module_startup(sapi_module,NULL,0)==FAILURE){

returnFAILURE;

}

returnSUCCESS;

}

(3)在module_startup阶段处理完后,接下来进入请求初始化阶段

zend_first_try{

if(sapi_module==&cli_sapi_module){

exit_status=do_cli(argc,argv);

}else{

exit_status=do_cli_server(argc,argv);

}

}zend_end_try();

(4)do_cli()将完成请求的处理,此函数一开始对使用到的命令行参数进行解析,如果是一些查询系统信息之类的请求(如-v,-m,-i),则不需要经历PHP请求的生命周期,这里会单独处理,下面看一下执行PHP脚本请求时的处理。

zend_file_handle file_handle;

...

if(script_file){

// fopen请求的脚本文件

if(cli_seek_file_begin(&file_handle,script_file,&lineno)!=SUCCESS){

gotoerr;

}else{

charreal_path[MAXPATHLEN];

if(VCWD_REALPATH(script_file,real_path)){

translated_path=strdup(real_path);

}

script_filename=script_file;

}

}else{

file_handle.filename="Standard input code";

file_handle.handle.fp=stdin;

}

// 输入类型为ZEND_HANDLE_FP,也就是FILE*

file_handle.type=ZEND_HANDLE_FP;

PHP 脚本执行时的输入形式有很多种,比如文件路径(filepath)、文件句柄(FILE)、文件描述符(fd)等,zend_file_handle结构就是用来定义不同输入形式的,这样可以统一PHP执行函数的输入参数。

Cli 中此处使用的是文件句柄,在Linux环境下也就是调用fopen()打开一个文件,这样内核就可以直接读取PHP脚本代码了,当然也可以直接把文件路径提供给内核。定义好请求的输入结构后,将进行请求初始化操作,即request startup阶段,然后开始PHP脚本的执行操作。

if(php_request_startup()==FAILURE){

*arg_excp=arg_free;

fclose(file_handle.handle.fp);

PUTS("Could not startup.\n");

gotoerr;

}

...

switch(behavior){

casePHP_MODE_STANDARD:

...

// 执行

php_execute_script(&file_handle);

...

break;

case...// 其他执行模式

}

(5)完成脚本的处理后进入request shutdown阶段:

out:

if(request_started){

php_request_shutdown((void*)0);

}

(6)do_cli() 完成后回到 main() 函数中,进入module shutdown阶段,最后进程退出,这就是 Cli 下执行一个脚本的生命周期。

out:

if(module_started){

php_module_shutdown();

}

if(sapi_started){

sapi_shutdown();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值