程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP基礎知識 >> PHP源碼 — CLI 運行過程

PHP源碼 — CLI 運行過程

編輯:PHP基礎知識
 

PHP 運行模式

告知PHP是以一種什麼樣的方式執行,比如nginx是通過什麼和PHP進行交互,apache是通過什麼方式和PHP交互等等。

Php的運行模式有多種,從PHP源碼/sapi/目錄中我們可以看到php不同的運行模式。

運行模式詳解

Cli是php的命令行模式,可以把PHP看作類似shell的腳本語言,例如:

  #!/path/php/bin/php -q
  <?php
  echo "hello,i am cli";
  ?>

或者
   /path/php/bin/php index.php
  <?php
  echo "hello,i am cli";
  ?>

上述代碼是如何執行的?
為什麼能echo出hello,i am cli .

main函數開始

在 Sai/php_cli.c 中 的main 函數

第一步,獲取php 所在位置 一般都指path/php/bin/php,
sapi_module->executable_location = argv[0];

第二步,設置sapi 的cli模式
  sapi_module_struct *sapi_module = &cli_sapi_module;

sapi_module_struct 的結構定義,在/main/SAPI.h裡定義
  struct _sapi_module_struct {
   char *name;
   char *pretty_name;
  ...
  }

  我可以通過
  <?Php
  echo php_sapi_name();
  ?>

來獲取PHP的執行模式。
當然在sapi/php_cli.c 裡定義了
  static sapi_module_struct cli_sapi_module = {
   "cli", /* name */
   "Command Line Interface", /* pretty name */
  ...
  }

Do_cli 函數分析
  
第三步,執行 do_cli(argc, argv TSRMLS_CC);
比如執行 :
  /path/php/bin/php -i ,相當於是 phpinfo();
  /path/php/bin/php -v,獲取php的版本
  /path/php/bin/php -h,獲取php命令詳解

第四步,在do_cli(argc, argv TSRMLS_CC) 中有這麼一段
  if (script_file) {
  ...
  }

  /path/php/bin/php /index.php
  那麼script_file 就是/index.php
  
  if (script_file) {
  ...
  if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) {
   goto err;
  }
  ...
  }

  
  通過 cli_seek_file_begin 檢查文件是否存在,例如我們隨便執行

  /path/php/bin/php /xxx.php
  
  如果/xxx.php文件不存在的話。就會報 Could not open input file: /xxx.php

VCWD_FOPEN 函數分析

  在上述中已經提到通過 cli_seek_file_begin 去檢測PHP文件 是否存在。Php內核中定義了通過只讀的方式VCWD_FOPEN函數來

判斷文件是否存在,

  在/TSRM/tsrm_virtual_cwd.h頭文件中,宏定義如下:
#define VCWD_FOPEN(path, mode) fopen(path, mode)

  

VCWD_REALPATH 函數分析
  
如果通過2.1.1.3的VCWD_FOPEN函數判斷文件存在,就會執行VCWD_REALPATH來過濾script_file 的特殊字符,並且返回絕對路徑。
  例如:
  1、/path/php/bin/php index.php
  會得到
  /path/php/bin/php /path/index.php
  /path/php/bin/php .//index.php
會得到
  /path/php/bin/php /path/index.php

根據執行模式進行
  
  switch (behavior) {
   case PHP_MODE_STANDARD: //php的標准模式
   if (strcmp(file_handle.filename, "-")) {
   cli_register_file_handles(TSRMLS_C);
   }
  //判斷如果是php -a 這樣的交互模式
   if (interactive && cli_shell_callbacks.cli_shell_run) {
   exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C);
   } else {
   php_execute_script(&file_handle TSRMLS_CC);
   exit_status = EG(exit_status);
   }
   break;
  ......
 

php_execute_script

  在文件main/php_main.h裡定義了
  PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC);

zend_execute_scripts

  在文件Zend/zend_compile.h裡定義
  ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...);  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved