PHP内核两大流程之请求处理_PHP教程
程序员文章站
2024-02-10 10:25:52
...
PHP内核两大流程之请求处理
static int php_handler(request_rec *r) { /* Initiliaze the context */ php_struct * volatile ctx; void *conf; apr_bucket_brigade * volatile brigade; apr_bucket *bucket; apr_status_t rv; request_rec * volatile parent_req = NULL; TSRMLS_FETCH(); ...... zend_file_handle zfd; zfd.type = ZEND_HANDLE_FILENAME; zfd.filename = (char *) r->filename; zfd.free_filename = 0; zfd.opened_path = NULL; zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd); ...... } ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */ { ...... EG(active_op_array) = \ zend_compile_file(file_handle, type TSRMLS_CC); ...... zend_execute(EG(active_op_array) TSRMLS_CC); ...... } ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) { // 初始化执行上下文 zend_execute_data execute_data; // 如果有异常就退出执行 if (EG(exception)) { return; } /* Initialize execute_data */ EX(fbc) = NULL; // 初始化正在调用的函数 EX(object) = NULL; // 初始化正在调用的对象 EX(old_error_reporting) = NULL; // 初始化错误报告变量 // 为执行栈分配空间 if (op_array->T T); } else { EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); } // 为临时变量分配空间并初始化这些空间 EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; // 切换执行上下文 EX(original_in_execution) = EG(in_execution); EX(symbol_table) = EG(active_symbol_table); EX(prev_execute_data) = EG(current_execute_data); // 将当前全局变量中的执行数据压栈 EG(current_execute_data) = &execute_data; // 将当前执行上下文压栈 EG(in_execution) = 1; // 初始化第一个指令(opcode) /* #define ZEND_VM_SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ EX(opline) = new_op execute_data.opline 为当前执行的 opcode */ if (op_array->start_op) { ZEND_VM_SET_OPCODE(op_array->start_op); } else { ZEND_VM_SET_OPCODE(op_array->opcodes); } if (op_array->uses_this && EG(This)) { EG(This)->refcount++; /* For $this pointer */ if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { EG(This)->refcount--; } } // 将存储opline的内存地址赋给 executor_globals.online_ptr ,可以实时跟踪opcode的执行 EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array; EG(function_state_ptr) = &EX(function_state); #if ZEND_DEBUG /* function_state.function_symbol_table is saved as-is to a stack, * which is an intentional UMR. Shut it up if we're in DEBUG. */ EX(function_state).function_symbol_table = NULL; #endif while (1) { #ifdef ZEND_WIN32 if (EG(timed_out)) { zend_timeout(0); } #endif // 循环调用每个opline的 handler 函数,如果是推出函数的话,返回值大于0,就退出 if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) { return; } } zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); }