php脚本cli 模式运行
参考文章 http://rapheal.sinaapp.com/2013/11/20/php_zend_hello_world/
http://www.douban.com/note/337885681/
5.3 与以前版本的不同 http://my.oschina.net/mickelfeng/blog/201382
php添加新语法 http://www.it165.net/pro/html/201208/3477.html
http://nikic.github.io/2012/07/27/How-to-add-new-syntactic-features-to-PHP.html
http://zsong.me/posts/1
http://www.laruence.com/2009/02/21/662.html
http://www.verydemo.com/cm.jsp?c=14&u=shen-ru-li-jie-php-yuan-li-zhi
http://bbs.phpchina.com/thread-100825-1-1.html
static http://www.nowamagic.net/librarys/veda/detail/1402
cli方式运行php脚本
$PHPSRC/sapi/cli/php_cli.c中的do_cli函数里边接收了命令行的参数输入
zend_execute_scripts() $PHPSRC/main/main.c里边有定义
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);
zend_execute(EG(active_op_array) TSRMLS_CC);
通过zend_compile_file(实际上为compile_file()<定义在Zend/zend_language_scanner.c的555行>)把脚本文件编译出opcode,
ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */
{
va_list files;
int i;
zend_file_handle *file_handle;
zend_op_array *orig_op_array = EG(active_op_array);
zval **orig_retval_ptr_ptr = EG(return_value_ptr_ptr);
long orig_interactive = CG(interactive); va_start(files, file_count);
for (i = ; i < file_count; i++) {
file_handle = va_arg(files, zend_file_handle *);
if (!file_handle) {
continue;
} if (orig_interactive) {
if (file_handle->filename[] != '-' || file_handle->filename[]) {
CG(interactive) = ;
} else {
CG(interactive) = ;
}
} EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);
if (file_handle->opened_path) {
int dummy = ;
zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path) + , (void *)&dummy, sizeof(int), NULL);
}
zend_destroy_file_handle(file_handle TSRMLS_CC);
if (EG(active_op_array)) {
EG(return_value_ptr_ptr) = retval ? retval : NULL;
zend_execute(EG(active_op_array) TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
if (EG(exception)) {
if (EG(user_exception_handler)) {
zval *orig_user_exception_handler;
zval **params[], *retval2, *old_exception;
old_exception = EG(exception);
EG(exception) = NULL;
params[] = &old_exception;
orig_user_exception_handler = EG(user_exception_handler);
if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, , params, , NULL TSRMLS_CC) == SUCCESS) {
if (retval2 != NULL) {
zval_ptr_dtor(&retval2);
}
if (EG(exception)) {
zval_ptr_dtor(&EG(exception));
EG(exception) = NULL;
}
zval_ptr_dtor(&old_exception);
} else {
EG(exception) = old_exception;
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
}
} else {
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
}
}
destroy_op_array(EG(active_op_array) TSRMLS_CC);
efree(EG(active_op_array));
} else if (type==ZEND_REQUIRE) {
va_end(files);
EG(active_op_array) = orig_op_array;
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
CG(interactive) = orig_interactive;
return FAILURE;
}
}
va_end(files);
EG(active_op_array) = orig_op_array;
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
CG(interactive) = orig_interactive; return SUCCESS;
} zend_compile_file = compile_file;
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
zend_lex_state original_lex_state;
zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
zend_op_array *original_active_op_array = CG(active_op_array);
zend_op_array *retval=NULL;
int compiler_result;
zend_bool compilation_successful=;
znode retval_znode;
zend_bool original_in_compilation = CG(in_compilation); retval_znode.op_type = IS_CONST;
retval_znode.u.constant.type = IS_LONG;
retval_znode.u.constant.value.lval = ;
Z_UNSET_ISREF(retval_znode.u.constant);
Z_SET_REFCOUNT(retval_znode.u.constant, ); zend_save_lexical_state(&original_lex_state TSRMLS_CC); retval = op_array; /* success oriented */ if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
if (type==ZEND_REQUIRE) {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
zend_bailout();
} else {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
}
compilation_successful=;
} else {
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); //初始化op_array
CG(in_compilation) = ;
CG(active_op_array) = op_array;
zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
zend_init_compiler_context(TSRMLS_C);
compiler_result = zendparse(TSRMLS_C);//对于非函数,都是设置opline的各个属性,对于函数,要额外分配一个op_array
zend_do_return(&retval_znode, TSRMLS_CC);
CG(in_compilation) = original_in_compilation;
if (compiler_result==) { /* parser error */
zend_bailout();
}
compilation_successful=;
} if (retval) {
CG(active_op_array) = original_active_op_array;
if (compilation_successful) {
pass_two(op_array TSRMLS_CC);//循环遍历op_array中的opcodes,设置每一个opline中的属性hanlder
zend_release_labels(TSRMLS_C);
} else {
efree(op_array);
retval = NULL;
}
}
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
return retval;
}
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
{
zend_execute_data *execute_data;
zend_bool nested = ;
zend_bool original_in_execution = EG(in_execution); if (EG(exception)) {
return;
} EG(in_execution) = ; zend_vm_enter:
/* Initialize execute_data */
execute_data = (zend_execute_data *)zend_vm_stack_alloc(
ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) +
ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? : )) +
ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)));
memset(EX(CVs), , sizeof(zval**) * op_array->last_var);
EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? : )));
EX(fbc) = NULL;
EX(called_scope) = NULL;
EX(object) = NULL;
EX(old_error_reporting) = NULL;
EX(op_array) = op_array;
EX(symbol_table) = EG(active_symbol_table);
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = execute_data;
EX(nested) = nested;
nested = ; if (op_array->start_op) {
ZEND_VM_SET_OPCODE(op_array->start_op);
} else {
ZEND_VM_SET_OPCODE(op_array->opcodes);
} if (op_array->this_var != - && EG(This)) {
Z_ADDREF_P(EG(This)); /* For $this pointer */
if (!EG(active_symbol_table)) {
EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
*EX(CVs)[op_array->this_var] = EG(This);
} else {
if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
Z_DELREF_P(EG(This));
}
}
} EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL; while () {
int ret;
#ifdef ZEND_WIN32
if (EG(timed_out)) {
zend_timeout();
}
#endif if ((ret = EX(opline)->handler(execute_data TSRMLS_CC)) > ) {
switch (ret) {
case :
EG(in_execution) = original_in_execution;
return;
case :
op_array = EG(active_op_array);
goto zend_vm_enter;
case :
execute_data = EG(current_execute_data);
default:
break;
}
} }
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
}
zendparse (LALR1 将代码分隔成token,再解析后存放在opcode的数组中)
pass_two解析opcode的每一行,将其handler绑定到op上
complie之后会得到一个op_array,在execute之前创建一个zend_execute_data的数据结构
struct _zend_execute_data {
struct _zend_op *opline;
zend_function_state function_state;
zend_op_array *op_array;
zval *object;
HashTable *symbol_table;
struct _zend_execute_data *prev_execute_data;
zval *old_error_reporting;
zend_bool nested;
zval **original_return_value;
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zval *current_this;
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
call_slot *call_slots;
call_slot *call;
};
在zend_execute中最重要的一句
ret = OPLINE->handler(execute_data TSRMLS_CC)
调用在op上绑定的handler,完成对opcode的执行
//zend_opcode.c
ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
{
zend_op *opline, *end;
if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
return 0;
}
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
zend_update_extended_info(op_array TSRMLS_CC);
}
if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC);
}
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) {
op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var);
CG(context).vars_size = op_array->last_var;
}
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) {
op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
CG(context).opcodes_size = op_array->last;
}
if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) {
op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
CG(context).literals_size = op_array->last_literal;
}
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
if (opline->op1_type == IS_CONST) {
opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
}
if (opline->op2_type == IS_CONST) {
opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
}
switch (opline->opcode) {
case ZEND_GOTO:
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
}
/* break omitted intentionally */
case ZEND_JMP:
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_JMP_SET_VAR:
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);
opline++;
}
op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return 0;
}
//zend_vm_execute.h
ZEND_API void zend_vm_set_opcode_handler(zend_op* op)
{
op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op);
}
php脚本cli 模式运行的更多相关文章
- ****CodeIgniter使用cli模式运行,把php作为shell编程
shell简介 在计算机科学中,Shell俗称壳(用来区别于核).而我们常说的shell简单理解就是一个命令行界面,它使得用户能与操作系统的内核进行交互操作. 常见的shell环境有:MS-DOS.B ...
- Jmeter系列(40)- 详解 Jmeter CLI 模式
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 什么是 CLI 模式 CLI = Co ...
- 『动善时』JMeter基础 — 55、JMeter非GUI模式运行
目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.怎样使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模 ...
- 『动善时』JMeter基础 — 55、使用非GUI模式运行JMeter(命令行模式)
目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模式运 ...
- ThinkPHP3.1.2 使用cli命令行模式运行
ThinkPHP3.1.2 使用cli命令行模式运行 标签(空格分隔): php 前言 thinkphp3.1.2 需要使用cli方法运行脚本 折腾了一天才搞定 3.1.2的版本真的很古老 解决 增加 ...
- 获取当前PHP运行环境是否cli模式
需要用到系统函数php_sapi_name() 或者 系统常量 PHP_SAPI,返回 cli 或 cli_server /* 判断当前的运行环境是否是cli模式 */ function is_cli ...
- 通过no-gui模式运行jmeter脚本与生成报告
说明:使用NO-GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资源. 步骤:在GUI(图形化界面)模式调整好脚本,通过FTP工具将需要测试的.jmx文件传输到linux ...
- PHP CLI模式开发
PHP CLI模式开发不需要任何一种Web服务器(包括Apache或MS IIS等),这样,CLI可以运行在各种场合.有两种方法可以运行PHP CLI脚本. 第一种方法是使用 # php /path/ ...
- php CLI 模式下的传参方法
在CLI模式(命令行界面 Command Line Interface)下,传入参数有如下3种方法: 一. getopt函数(PHP 4 >= 4.3.0, PHP 5) getopt - 从命 ...
随机推荐
- JSFF或JSF页面加载时触发JavaScript之方法
现象一 最近在项目中遇到这么一个问题,有些页面元素是在页面加载时通过JavaScript动态渲染而成.当生成这些元素的JavaScript脚本被放置于JSPX文件中时,界面渲染没有问题.但是当我们把生 ...
- 一篇很好的关于mysqld_safe脚本源码解读的文章,收藏了!!
#!/bin/sh # 一些状态变量的定义 KILL_MYSQLD=; # 试图kill多余的mysqld_safe程序,1表示需要kill MYSQLD= # mysqld二进制可执行文件的名称 n ...
- [模板]LIS(最长上升子序列)
转载自:最长上升子序列(LIS)长度的O(nlogn)算法 最长上升子序列nlogn算法 在川大oj上遇到一道题无法用n^2过于是,各种纠结,最后习得nlogn的算法 最长递增子序列,Longest ...
- chorme 浏览器记住密码后input黄色背景处理方法(两种)
使用chrome浏览器选择记住密码的账号,输入框会自动加上黄色的背景,有些设计输入框是透明背景的,需要去除掉这个黄色的背景: 方法1:阴影覆盖 input:-webkit-autofill { - ...
- 深入浅出谈数据挖掘zz
编者的话:本文对数据挖掘概念的产生,数据挖掘与常规数据分析的主要区别,所能解决的几大类问题和所应用的领域都有着非常清晰的论述.作者在此篇文章中认为数据挖掘最重要的要素是分析人员的相关业务知识和思维模式 ...
- Oracle学习笔记(四)
六.约束 1.约束的作用 定义规则:什么数据可以输入,什么不可以 确保完整性:数据的精确性和可靠性 2.Oracle五个重要的约束: 非空约束.主键约束.外键约束.检查约束.唯一约束. (1)非空约束 ...
- linux下mysql安装和调优
1.yum yum -y install mysql-server mysql 2.RPM安装 http://dev.mysql.com/downloads/ 下载RPM包,请确认服务器版本,我的是红 ...
- swift -pop的简单动画
//1.新建空文件 命名Podfile //2.写入 pod ‘pop’,’~>1.0’ 保存 //3.打开终端,进入项目路径 执行pod install //4.新建桥接头文件 导入#im ...
- Codeforces766A Mahmoud and Longest Uncommon Subsequence 2017-02-21 13:42 46人阅读 评论(0) 收藏
A. Mahmoud and Longest Uncommon Subsequence time limit per test 2 seconds memory limit per test 256 ...
- Mac提示App已损坏 你应该将它移到废纸篓的解决方案
现象 "Elmedia Player.app"已损坏,打不开. 您应该将它移到废纸篓. 原因 很多朋友们在安装软件时Mac OS系统出现提示"XXXApp 已损坏&quo ...