PHPのソースコードを入手する
PHPの実装を学ぶには、まずPHPのソースコードをダウンロードする必要があります。ソース コードをダウンロードする最初の選択肢は、公式 PHP Web サイト http://php.net/downloads.php からダウンロードすることです。svn/git などのバージョン管理ソフトウェアを使用したい場合は、svn/git を使用して入手することもできます。最新のソースコード。
# git 官方地址 git clone https://git.php.net/repository/php-src.git # 也可以访问github官方镜像 git clone git://github.com/php/php-src.git cd php-src && git checkout PHP-5.3 # 签出5.3分支
PHPソースコードのディレクトリ構造
格言にあるように、「重い剣には刃がなく、重い剣には鋭い刃がありません。」 PHP ソースコードの構造は非常に明確です。まず、PHP ソース コードのディレクトリ構造を簡単に紹介します。
ルートディレクトリ: / このディレクトリには、主にいくつかのドキュメントや設計計画など、多くのものが含まれています。 実際、プロジェクト内のこれらの README ファイルは非常に読む価値があります。例:
/README.PHP4-TO-PHP5-THIN-CHANGES このファイルには、PHP4 と PHP5 のいくつかの違いが詳細にリストされています。
さらに重要なファイル /CODING_STANDARDS もあります。PHP 拡張機能を作成したい場合は、インデントと中括弧の使用方法に関係なく、このファイルを読む必要があります。そのようなグループの場合は、自分や他の人がコードを読みやすくするために、そのような規範に適応する必要があります。
build 名前が示すように、ここには主に、ビルドを開始する前の buildconf スクリプトやその他のファイル、環境を確認するためのスクリプトなど、ソースコードのコンパイルに関連するいくつかのファイルが配置されます。
ext 公式拡張ディレクトリには、配列シリーズ、pdo シリーズ、spl シリーズ、その他の関数の実装など、ほとんどの PHP 関数の定義と実装がすべてこのディレクトリに含まれています。個人が作成した拡張機能も、テスト中にこのディレクトリに配置して、テストとデバッグを容易にすることができます。
main ここには、主に PHP の基本機能を実装する PHP のコア ファイルが格納されます。これは、主に言語のコア言語実行環境を実装する Zend エンジンとは異なります。
Zend Zend エンジンの実装ディレクトリ。スクリプトの字句解析や構文解析、オペコードの実行、拡張メカニズムの実装など。
pear「PHP拡張機能およびアプリケーションリポジトリ」には、PEARのコアファイルが含まれています。
sapi Apache の mod_php、cgi、fastcgi、fpm およびその他のインターフェイスなど、さまざまなサーバー抽象化レイヤーのコードが含まれています。
TSRM PHP のスレッド セーフは、TSRM ライブラリに基づいて構築されています。PHP 実装における一般的な *G マクロは、通常、TSRM (Thread Safe Resource Manager) スレッド セーフ リソース マネージャーのカプセル化です。
tests PHP のさまざまな機能のテスト ファイルを含む、PHP テスト スクリプトのコレクション
win32 このディレクトリには、主に Windows プラットフォームに関連するいくつかの実装が含まれます (Windows および Windows での sokcet の実装など)。 *Nix プラットフォーム Windows での PHP のコンパイルに関連するスクリプトも含まれています。
PHPのグローバル変数マクロ
PHP ソースコードのマクロやコードでよく見かけるいくつかの一般的なものソースコードに触れ始めたばかりの読者にとっては理解するのが困難です。 これらのコードは PHP ソース コードに非常に頻繁に出現し、基本的にすべてのモジュールに存在します。
在PHP代码中经常能看到一些类似PG(), EG()之类的函数,他们都是PHP中定义的宏,这系列宏主要的作用是解决线程安全所写的全局变量包裹宏, 如$PHP_SRC/main/php_globals.h文件中就包含了很多这类的宏。例如PG这个PHP的核心全局变量的宏。 如下所示代码为其定义。
#ifdef ZTS // 编译时开启了线程安全则使用线程安全库 # define PG(v) TSRMG(core_globals_id, php_core_globals *, v) extern PHPAPI int core_globals_id; #else # define PG(v) (core_globals.v) // 否则这其实就是一个普通的全局变量 extern ZEND_API struct _php_core_globals core_globals; #endif
如上,ZTS是线程安全的标记,这个在以后的章节会详细介绍,这里就不再说明。下面简单说说,PHP运行时的一些全局参数, 这个全局变量为如下的一个结构体,各字段的意义如字段后的注释:
struct _php_core_globals { zend_bool magic_quotes_gpc; // 是否对输入的GET/POST/Cookie数据使用自动字符串转义。 zend_bool magic_quotes_runtime; //是否对运行时从外部资源产生的数据使用自动字符串转义 zend_bool magic_quotes_sybase; // 是否采用Sybase形式的自动字符串转义 zend_bool safe_mode; // 是否启用安全模式 zend_bool allow_call_time_pass_reference; //是否强迫在函数调用时按引用传递参数 zend_bool implicit_flush; //是否要求PHP输出层在每个输出块之后自动刷新数据 long output_buffering; //输出缓冲区大小(字节) char *safe_mode_include_dir; //在安全模式下,该组目录和其子目录下的文件被包含时,将跳过UID/GID检查。 zend_bool safe_mode_gid; //在安全模式下,默认在访问文件时会做UID比较检查 zend_bool sql_safe_mode; zend_bool enable_dl; //是否允许使用dl()函数。dl()函数仅在将PHP作为apache模块安装时才有效。 char *output_handler; // 将所有脚本的输出重定向到一个输出处理函数。 char *unserialize_callback_func; // 如果解序列化处理器需要实例化一个未定义的类,这里指定的回调函数将以该未定义类的名字作为参数被unserialize()调用, long serialize_precision; //将浮点型和双精度型数据序列化存储时的精度(有效位数)。 char *safe_mode_exec_dir; //在安全模式下,只有该目录下的可执行程序才允许被执行系统程序的函数执行。 long memory_limit; //一个脚本所能够申请到的最大内存字节数(可以使用K和M作为单位)。 long max_input_time; // 每个脚本解析输入数据(POST, GET, upload)的最大允许时间(秒)。 zend_bool track_errors; //是否在变量$php_errormsg中保存最近一个错误或警告消息。 zend_bool display_errors; //是否将错误信息作为输出的一部分显示。 zend_bool display_startup_errors; //是否显示PHP启动时的错误。 zend_bool log_errors; // 是否在日志文件里记录错误,具体在哪里记录取决于error_log指令 long log_errors_max_len; //设置错误日志中附加的与错误信息相关联的错误源的最大长度。 zend_bool ignore_repeated_errors; // 记录错误日志时是否忽略重复的错误信息。 zend_bool ignore_repeated_source; //是否在忽略重复的错误信息时忽略重复的错误源。 zend_bool report_memleaks; //是否报告内存泄漏。 char *error_log; //将错误日志记录到哪个文件中。 char *doc_root; //PHP的”根目录”。 char *user_dir; //告诉php在使用 /~username 打开脚本时到哪个目录下去找 char *include_path; //指定一组目录用于require(), include(), fopen_with_path()函数寻找文件。 char *open_basedir; // 将PHP允许操作的所有文件(包括文件自身)都限制在此组目录列表下。 char *extension_dir; //存放扩展库(模块)的目录,也就是PHP用来寻找动态扩展模块的目录。 char *upload_tmp_dir; // 文件上传时存放文件的临时目录 long upload_max_filesize; // 允许上传的文件的最大尺寸。 char *error_append_string; // 用于错误信息后输出的字符串 char *error_prepend_string; //用于错误信息前输出的字符串 char *auto_prepend_file; //指定在主文件之前自动解析的文件名。 char *auto_append_file; //指定在主文件之后自动解析的文件名。 arg_separators arg_separator; //PHP所产生的URL中用来分隔参数的分隔符。 char *variables_order; // PHP注册 Environment, GET, POST, Cookie, Server 变量的顺序。 HashTable rfc1867_protected_variables; // RFC1867保护的变量名,在main/rfc1867.c文件中有用到此变量 short connection_status; // 连接状态,有三个状态,正常,中断,超时 short ignore_user_abort; // 是否即使在用户中止请求后也坚持完成整个请求。 unsigned char header_is_being_sent; // 是否头信息正在发送 zend_llist tick_functions; // 仅在main目录下的php_ticks.c文件中有用到,此处定义的函数在register_tick_function等函数中有用到。 zval *http_globals[6]; // 存放GET、POST、SERVER等信息 zend_bool expose_php; // 是否展示php的信息 zend_bool register_globals; // 是否将 E, G, P, C, S 变量注册为全局变量。 zend_bool register_long_arrays; // 是否启用旧式的长式数组(HTTP_*_VARS)。 zend_bool register_argc_argv; // 是否声明$argv和$argc全局变量(包含用GET方法的信息)。 zend_bool auto_globals_jit; // 是否仅在使用到$_SERVER和$_ENV变量时才创建(而不是在脚本一启动时就自动创建)。 zend_bool y2k_compliance; //是否强制打开2000年适应(可能在非Y2K适应的浏览器中导致问题)。 char *docref_root; // 如果打开了html_errors指令,PHP将会在出错信息上显示超连接, char *docref_ext; //指定文件的扩展名(必须含有’.')。 zend_bool html_errors; //是否在出错信息中使用HTML标记。 zend_bool xmlrpc_errors; long xmlrpc_error_number; zend_bool activated_auto_globals[8]; zend_bool modules_activated; // 是否已经激活模块 zend_bool file_uploads; //是否允许HTTP文件上传。 zend_bool during_request_startup; //是否在请求初始化过程中 zend_bool allow_url_fopen; //是否允许打开远程文件 zend_bool always_populate_raw_post_data; //是否总是生成$HTTP_RAW_POST_DATA变量(原始POST数据)。 zend_bool report_zend_debug; // 是否打开zend debug,仅在main/main.c文件中有使用。 int last_error_type; // 最后的错误类型 char *last_error_message; // 最后的错误信息 char *last_error_file; // 最后的错误文件 int last_error_lineno; // 最后的错误行 char *disable_functions; //该指令接受一个用逗号分隔的函数名列表,以禁用特定的函数。 char *disable_classes; //该指令接受一个用逗号分隔的类名列表,以禁用特定的类。 zend_bool allow_url_include; //是否允许include/require远程文件。 zend_bool exit_on_timeout; // 超时则退出 #ifdef PHP_WIN32 zend_bool com_initialized; #endif long max_input_nesting_level; //最大的嵌套层数 zend_bool in_user_include; //是否在用户包含空间 char *user_ini_filename; // 用户的ini文件名 long user_ini_cache_ttl; // ini缓存过期限制 char *request_order; // 优先级比variables_order高,在request变量生成时用到,个人觉得是历史遗留问题 zend_bool mail_x_header; // 仅在ext/standard/mail.c文件中使用, char *mail_log; zend_bool in_error_log; };
上面的字段很大一部分是与php.ini文件中的配置项对应的。 在PHP启动并读取php.ini文件时就会对这些字段进行赋值, 而用户空间的ini_get()及ini_set()函数操作的一些配置也是对这个全局变量进行操作的。
在PHP代码的其他地方也存在很多类似的宏,这些宏和PG宏一样,都是为了将线程安全进行封装,同时通过约定的 G 命名来表明这是全局的, 一般都是个缩写,因为这些全局变量在代码的各处都会使用到,这也算是减少了键盘输入。 我们都应该尽可能的懒不是么?
如果你阅读过一些PHP扩展话应该也见过类似的宏,这也算是一种代码规范,在编写扩展时全局变量最好也使用这种方式命名和包裹, 因为我们不能对用户的PHP编译条件做任何假设。
以上がPHPカーネル・ソースコードのインストールと導入の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。