深入理解PHP内核[读书笔记]--第一章准备工作和背景知识

##第一节:环境搭建

编译安装的关键点:配置编译安装环境,build-essential环境。

1.1 准备编译环境

针对于ubuntu16.04 下面建设编译安装环境:

apt-get install build-essential

1.2 编译

cd ~/php-src

./buildconf

./configure --help #查看可用参数

./configure --disable-all #编译最精简的php文件

make && make install 即可进行安装,

然后通过php -v 查看相应信息。

##第二节:源码结构、阅读代码方法

2.1 目录结构

build     编译相关文件

ext          扩展相关文件

main          php核心文件

Zend          引擎实现目录

pear          PHP扩展与应用仓库

sapi          服务器抽象层代码

TSRM          线程安全

tests          测试脚本集合

win32          window 平台的相关实现

2.1 查看源码

任何编辑器均可

##第三节:常用代码

3.1 “##”和"#"

3.1.1 双井号(##)【就是连接两个一起】

在C语言的宏中,"##"被称为连接符(concatenator),它是一种预处理运算符,用来把两个语言符号(Token)组合成单个语言符号。这里的语言符号不一定是宏的变量。并且双井号不能作为第一个或最后一个元素存在。如下所示源码:

#define PHP_FUNCTION ZEND_FUNCTION

#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))

#define ZEND_FN(name) zif_##name

#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)

#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value,

zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC

PHP_FUNCTION(count);

// 预处理器处理以后,PHP_FUNCTION(count);就展开为如下代码

void zif_count(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)

宏ZEND_FN(name)中有一个“##”,它的作用一如之前所说,是一个连接符,将zif和宏的变量name的值连接起来。以这种连接方式为基础,多次使用这种宏形式,可以将它作为一个代码生成器,这样可以在一定程度上减少代码密度,我们可以将它理解为一种代码重用的手段,间接地减小不小心所造成的错误。

3.1.2 单井号(#)【表示后面的是字符串】

“#”是一种预处理运算符,它的功能是将其后面的宏参数进行字符串化操作,简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号,用比较官方的话说就是将语言符号(Token)转化为字符串。例如:

#define STR(x) #x

int main(int argc, char** argv)

{

printf("%s\n",STR(It is a long string));// 输出 it is a long string

return 0;

}

如前文所说, it is long string 是宏 STR 的参数,在展开后被包裹成一个字符串了。所以 printf

函数能直接输出这个字符串,当然这个使用场景不是很合适,因为这种用法并没有实际的意义,实际中在宏中可能包裹其它的逻辑,比如对字符串进行封装等等。

3.2  关于宏定义中的do-while循环【多行宏使用方式】

通用php内宏调用的用法,因为while(0),也就是仅仅执行一遍。这样方便编译,考虑到平台移植性和不同的系统配置。

#define ALLOC_ZVAL(z)

do{

(z) = (zval*)emalloc(sizeof(zval_gc_info));

GC_ZVAL_INIT(z);

}while(0)

因为通常的预处理方式,会导致不同的语法结构出错。例如下面情况:

#define TEST(a,b) a++;b++;

if(expr)

TEST(a,b);

else

do_else();

经过预处理后,会变成:

if(expr)

a++;b++;

else

do_else();

这样就会导致逻辑错误,b++就没有正常执行了。如果要正常的话,需要我们添加{}才能正常执行。

还有另外的一个问题就是:

为了更好的兼容平台,需要定义部分“空操作”

方式1:

#ifdef SERIALIZE_HEADERS

#define VEC_FREE() smart_str_free(&vec_str)

#else

#define VEC_FREE() do{}while(0)

#endif

方式2:

#ifdef DEBUG

#     define LOG_MSG printf

#else

#     define LOG_MSG()

#endif

////////////////////////////////////////////////

等待更新

///////////////////////////////////////////////

3.3 \#line预处理

#line 838 "Zend/zend_language_scanner.c"

#line

预处理用于改变当前的行号(__LINE__)和文件名(__FILE__)。如上所示代码,将当前行号改变为838,文件名Zend/zend_language_scanner.c

它的作用体现在编译器的编写中,我们知道编译器对C源码编译器过程中会产生一些中间文件、通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行调试分析。

3.4 php中的全局变量宏

在PHP代码中经常能看到一些类似PG()、EG()之类的函数,他们都是PHP中定义的宏,这系列宏主要的作用是解决线程安全所写的全局变量包裹宏,如果$PHP_SRC/main/php_globals.h文件中就包含了很多这类的宏。例如PG这个PHP的核心全局变量的宏。如下所示代码为其定义。

#ifdef ZTS // 编译时开启线程安全则使用线程安全库

#define PG(v) TSRMG(core_globals_id,php_core_gloabls *,v)

extern PHPAPI int core_globals_id;

#else

#define PG(V) (core_global.v)// 否则这其实就是一个普通的全局变量

extern ZEND_API struct _php_core_globals core_globals;

#endif

下面是php运行时全局变量的情况:

struct _php_core_globals{

zend_bool magic_quotes_gpc;//是否对输入的GET/POST/Cookie 数据使用自动字符串

zend_bool magic_quotes_runtimes;//是否对运行时从外部资源产生的数据使用自动字符串转义

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 long_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_appedn_file;//指定在主文件之后自动解析的文件名

arg_separators arg_separator;//PHP所产生的URL中用来分隔参数的分隔符。

char *variables_order;//PHP注册Enviroment,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_list 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 acrivated_auto_globals[8];

zend_bool modules_activated;//是否已经激活模块

zend_bool file_uploads;//是否允许HTTP文件上传

zend_bool during_request_startup;//是否在请求初始化过程中

zend_bool alwasys_populate_raw_post_data;//是否总是生成$HTTP_RAW_POST_DATA变量(原始POST数据)

zend_bool report_zend_debug;//是否打开zend debug,仅在main/main.c文件中有使用

int last_error_tyep;//最后的错误类型

char *last_error_message;//最后的错误信息

char *last_error_file;//最后的错误文件

char 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和 ini_set及ini_get进行设置处理。

##第四节:小结

php初学者---千锋php课堂笔记

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 内存是计算机非常关键的部件之一,是暂时存储程序以及数据的空间,CPU只有有限的寄存器可以用于 存储计算数据,而大部...
    dreamer_lk阅读 1,192评论 2 10
  • php.ini设置,上传大文件: post_max_size = 128Mupload_max_filesize ...
    bycall阅读 6,743评论 3 64
  • 一、php可以做什么 php是一种可以在服务器端运行的编程语言,可以运行在Web服务器端。 php是一门后台编程语...
    空谷悠阅读 3,091评论 4 97
  • php性能分析工具xhprof分析 facebook,做为世界上最大的php应用网站,为php贡献出了hhvm x...
    meng_philip123阅读 1,310评论 0 4
  • 想一想自己2016年的目标,不知道实现了多少。。。 1 工作,攒钱 2 变美,变瘦 3 脱单 4 考资格证 ...
    readeatplay阅读 303评论 0 0