PHP7内核(六):变量之zval】的更多相关文章

本文总结自: <PHP7 内核剖析 - 变量的内部实现> 一:变量的实现 - 变量是一个语言实现的基础. - 在PHP中,变量的组成部分为 变量名(zval) 变量值(zend_value) - zval结构比较简单,内嵌一个union类型的zend_value保存具体变量类型的值或指针 //zend_types.h typedef struct _zval_struct zval; typedef union _zend_value { zend_long lval; //int整形 dou…
记得网上流传甚广的段子"PHP是世界上最好的语言",暂且不去讨论是否言过其实,但至少PHP确实有独特优势的,比如它的弱类型,即只需要$符号即可声明变量,使得PHP入手门槛极低,成为大家所青睐的Web服务端语言.那么它的变量是如何实现的呢?我们今天就来学习一下PHP的基本变量. 一.引言 PHP的变量存储在zval结构体中,在执行阶段中编译为op_array时就能看到zval的身影.结构体定义在Zend/zend_types.h中,定义内容如下所示: struct _zval_struc…
记得网上流传甚广的段子"PHP是世界上最好的语言",暂且不去讨论是否言过其实,但至少PHP确实有独特优势的,比如它的弱类型,即只需要$符号即可声明变量,使得PHP入手门槛极低,成为大家所青睐的Web服务端语言.那么它的变量是如何实现的呢?我们今天就来学习一下PHP的基本变量. 一.引言 PHP的变量存储在zval结构体中,在执行阶段中编译为op_array时就能看到zval的身影.结构体定义在Zend/zend_types.h中,定义内容如下所示: struct _zval_struc…
上篇文章讲述了变量的存储结构zval,今天我们就来学习一下几个常见变量类型的基本结构. 一.类型一览 zval中的u1.v.type用来存储变量的类型,而zval.value存储的是不同类型对应的值,所以type决定value取值的地方,以下是PHP7所定义的所有类型. #define IS_UNDEF 0 /* 标记未使用类型 */ #define IS_NULL 1 /* NULL */ #define IS_FALSE 2 /* 布尔类型false */ #define IS_TRUE 3…
简介 PHP的变量使用起来非常方便,其基本结构是底层实现的zval,PHP7采用了全新的zval,由此带来了非常大的性能提升,本文重点分析PHP7的zval的改变. PHP5时代的ZVAL typedef struct _zval_struct { zvalue_value value; // (长度16字节,具体看下面的分析) zend_uint refcount__gc; // unsigned int (长度4字节) zend_uchar type; // unsigned char (长…
上篇文章讲述了变量的存储结构zval,今天我们就来学习一下几个常见变量类型的基本结构. 一.类型一览 zval中的u1.v.type用来存储变量的类型,而zval.value存储的是不同类型对应的值,所以type决定value取值的地方,以下是PHP7所定义的所有类型. #define IS_UNDEF 0 /* 标记未使用类型 */ #define IS_NULL 1 /* NULL */ #define IS_FALSE 2 /* 布尔类型false */ #define IS_TRUE 3…
在前面大致预览了常用变量的结构之后,我们今天来仔细的剖析一下字符串的具体实现. 一.字符串的结构 struct _zend_string { zend_refcounted_h gc; /* 字符串类别及引用计数 */ zend_ulong h; /* 字符串的哈希值 */ size_t len; /* 字符串的长度 */ char val[1]; /* 柔性数组,字符串存储位置 */ }; zend_refcounted_h对应的结构体: typedef struct _zend_refcou…
在前面大致预览了常用变量的结构之后,我们今天来仔细的剖析一下字符串的具体实现. 一.字符串的结构 struct _zend_string { zend_refcounted_h gc; /* 字符串类别及引用计数 */ zend_ulong h; /* 字符串的哈希值 */ size_t len; /* 字符串的长度 */ char val[1]; /* 柔性数组,字符串存储位置 */ }; zend_refcounted_h对应的结构体: typedef struct _zend_refcou…
原文链接:http://www.orlion.ga/246/ 在PHP中,常量的名字是一个简单值的标识符,在脚本执行期间该值不能改变.和变量一样,常量默认为大小写敏感,但是通常是大写的. 常量是在变量的zval结构的基础上添加了一额外的元素.如下所示为PHP中常量的内部结构. 一.常量的内部结构 typedef struct _zend_constant {     zval value; /* zval结构,PHP内部变量的存储结构,在第一小节有说明 */     int flags;  /*…
原文链接:http://www.orlion.ga/238/ 编程语言的类型可以分为强类型和弱类型两种,PHP是弱类型语言,但是C语言是强类型语言.在官网PHP实现内部,所有变量使用同一种数据结构(zval)来保存,这个结构表示PHP中的各种数据类型,它不仅包含变量的值,也包含变量的类型.这就是PHP弱类型的核心. 那zval结构是如何实现弱类型的呢? 一.PHP变量类型及存储结构   PHP在声明和使用变量的时候,并不需要指明其数据类型,PHP是弱类型语言,但是PHP有类型,PHP有八中数据类…
1.现实生活中我们会找一个小箱子来存放物品,一来显得不那么凌乱,二来方便以后找到.计算机也是这个道理,我们需要先在内存中找一块区域,规定用它来存放数据,并起一个好记的名字,方便以后查找.这块区域就是“小箱子”,我们可以把数据放进去了. 2.数据类型用来说明数据的类型,确定了数据的解释方式,同时指明了数据的长度,也就是数据占用的字节数 3.变量名就是给那块内存区域起了个名字,方便使用 4..从类型划分 1)静态类型语言:比如c/java,类型检查在编译器确定 2)动态类型语言: 比如PHP/pyt…
原文链接:http://www.orlion.ga/251/ 通常静态变量是静态分配的,他们的生命周期和程序的生命周期一样长,只有在程序退出后才结束生命周期,这和局部变量相反,有的语言中全局变量也是静态分配的,例如PHP和js中的全局变量. 静态变量可以分为: 静态全局变量,PHP中的全局变脸也可以理解为静态全局变量,因为除了明确unset释放,在程序运行过程中始终存在. 静态局部变量,也就是在函数内部定义的静态变量,函数在执行时对变量的操作会保持到下一次函数被调用 静态成员变量,这是在类中定义…
原文链接:http://www.orlion.ga/249/ PHP脚本在执行的时候用户全局变量(在用户空间显示定义的变量)会保存在一个HashTable数据类型的符号表中(symbol_table)中,在PHP中有一些比较特殊的全局变量例如:$_GET.$_POST.$_SERVER等变量,我们并没有在程序中定义这些变量,并且这些变量也同样保存在符号表中,PHP是在脚本运行之前就将这些特殊的变量加入到了符号表中了. 一.预定义变量$GLOBALS的初始化 我们以cgi模式为例说明$GLOBAL…
一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) { echo $var; } 1.词法分析 在Zend/zend_language_scanner.l中我们找到如下所示的代码: <ST_IN_SCRIPTING>"function" { return T_FUNCTION; } 它所表示的含义是function将会生成T_FUNCTION标记.在获取这个标记后,我们开始语法分析. 2.语法分析 在Zend/zend_…
上一章我们对PHP的源码目录结构有了初步了解,本章我们继续从生命周期的维度对PHP进行剖析. 一.概览 生命周期是什么呢?你可以把它看作执行过程,PHP的生命周期也就是它从开始执行到结束执行的过程. PHP生命周期有五个阶段,分别为模块初始化阶段.请求初始化阶段.执行阶段.请求关闭阶段.模块关闭阶段.只是不同SAPI模式下,请求的情况略有不同,比如FastCGI下只经历了一次模块初始化阶段,接下来所有请求只经历请求初始化.执行脚本.请求关闭阶段. 在初步了解生命周期的五个阶段之后,我们先来讲述在…
上篇文章我们已经介绍了源码分析工具的安装.配置以及调试方法,本文我们来讲述一下PHP源码的目录结构. 一.目录概览 以php-7.0.12为例,看过源码的同学们应该发现源码目录多达十多个,下面是每个目录的说明. 目录 说明 TSRM 线程相关安全的实现 Zend PHP解析器的核心实现 build linux下编译相关的目录 ext PHP的扩展 main PHP的主要代码 netware 网络目录,socket的定义与实现 pear PHP扩展及应用的代码仓库 sapi PHP的应用层接口 s…
PHP7 为什么这么快? 全新的zval 更节约的空间,栈上分配内存 zend_string 存储字符串的Hash值,数组查询的时候不需要进行Hash计算 在HashTable桶内直接存数据,减少了内存的申请次数,提升了cache命中率和内存访问速度 zend_parse_parameters改为了宏实现,性能提升5% 增加opcode指令 call_user_function,is_init/string/array,strlen,defined函数变成opcode指令,速度更快 排序算法的改…
上一章我们对PHP的源码目录结构有了初步了解,本章我们继续从生命周期的维度对PHP进行剖析. 一.概览 生命周期是什么呢?你可以把它看作执行过程,PHP的生命周期也就是它从开始执行到结束执行的过程. PHP生命周期有五个阶段,分别为模块初始化阶段.请求初始化阶段.执行阶段.请求关闭阶段.模块关闭阶段.只是不同SAPI模式下,请求的情况略有不同,比如FastCGI下只经历了一次模块初始化阶段,接下来所有请求只经历请求初始化.执行脚本.请求关闭阶段. 在初步了解生命周期的五个阶段之后,我们先来讲述在…
上篇文章我们已经介绍了源码分析工具的安装.配置以及调试方法,本文我们来讲述一下PHP源码的目录结构. 一.目录概览 以php-7.0.12为例,看过源码的同学们应该发现源码目录多达十多个,下面是每个目录的说明. 目录 说明 TSRM 线程相关安全的实现 Zend PHP解析器的核心实现 build linux下编译相关的目录 ext PHP的扩展 main PHP的主要代码 netware 网络目录,socket的定义与实现 pear PHP扩展及应用的代码仓库 sapi PHP的应用层接口 s…
上篇文章讲述了模块初始化阶段之前的准备工作,本篇我来详细介绍PHP生命周期的五个阶段. 一.模块初始化阶段 我们先来看一下该阶段的每个函数的作用. 1.1.sapi_initialize_request_empty函数 // main/SAPI.c SAPI_API void sapi_initialize_empty_request(void) { SG(server_context) = NULL; SG(request_info).request_method = NULL; SG(req…
在php5.3之前,为某变量分配内存是用宏 MAKE_STD_ZVAL; 737 #define MAKE_STD_ZVAL(zv) \ # /Zend/zend.h738 ALLOC_ZVAL(zv); \739 INIT_PZVAL(zv); 165 #define ALLOC_ZVAL(z) \ # /Zend/zend_alloc.h166 (z) = (zval *) emalloc(sizeof(zval)) 727 #define INIT_PZVAL(z) \          …
本文主要介绍分析源码的方式,其中包含环境的搭建.分析工具的安装以及源码调试的基本操作. 一.工具清单 PHP7.0.12 GDB CLion 二.源码下载及安装 $ wget http://php.net/distributions/php-7.0.12.tar.gz $ tar zxvf php-7.0.12.tar.gz $ cd php-7.0.12/ $ ./configure --prefix=/usr/local/php7 --enable-debug --enable-fpm $…
PHP1 1994年,一位名叫Rasmus lerdorf的兄台为了在网上展示自己的履历和网页流量的统计,用Perl开发了一套脚本,后来因与日俱增的需求无法得到满足,lerdorf便使用c语言进行了重写,重写后的程序支持数据库的访问,以及web应用程序的简单开发,备受好评,随后便以Personal Home Page Tools为名发布了第一个版本. PHP2 为了PHP的改进和快速发展,lerdorf在1995年6月8日将其开源,于是PHP2.0问世,并被命名为PHP/FI.随后,在经历了数次…
本文主要介绍分析源码的方式,其中包含环境的搭建.分析工具的安装以及源码调试的基本操作. 一.工具清单 PHP7.0.12 GDB CLion 二.源码下载及安装 $ wget http://php.net/distributions/php-7.0.12.tar.gz $ tar zxvf php-7.0.12.tar.gz $ cd php-7.0.12/ $ ./configure --prefix=/usr/local/php7 --enable-debug --enable-fpm $…
上篇文章讲述了模块初始化阶段之前的准备工作,本篇我来详细介绍PHP生命周期的五个阶段. 一.模块初始化阶段 我们先来看一下该阶段的每个函数的作用. 1.1.sapi_initialize_request_empty函数 // main/SAPI.c SAPI_API void sapi_initialize_empty_request(void) { SG(server_context) = NULL; SG(request_info).request_method = NULL; SG(req…
PHP1 1994年,一位名叫Rasmus lerdorf的兄台为了在网上展示自己的履历和网页流量的统计,用Perl开发了一套脚本,后来因与日俱增的需求无法得到满足,lerdorf便使用c语言进行了重写,重写后的程序支持数据库的访问,以及web应用程序的简单开发,备受好评,随后便以Personal Home Page Tools为名发布了第一个版本. PHP2 为了PHP的改进和快速发展,lerdorf在1995年6月8日将其开源,于是PHP2.0问世,并被命名为PHP/FI.随后,在经历了数次…
====================================================== LIST_ENTRY PsLoadedModuleList; [定  义] wrk\wrk-v1.2\base\ntos\mm\Sysload.c [初始化] wrk\wrk-v1.2\base\ntos\mm\Sysload.c  [MiInitializeLoadedModuleList()] [引  用] l  NtQuerySystemInformation()         …
原文链接:http://www.orlion.ga/253/ PHP是弱类型语言,向方法传递参数时也并不严格检查数据类型.不过有时候需要判断传递到方法中的参数,为此PHP中提供了一些函数来判断数据的类型,比如is_numeric()判断是否是一个数值或者可转换为数值的字符串,比如用于判断对象的类型运算符:instance of.instance of用来测定一个给定的对象是否来自指定的对象类.instance of运算符是PHP5引进的,在此之前是使用is_a(). 为了避免对象类型不规范引起的…
原文链接:http://www.orlion.ga/241/ 一.哈希表(HashTable) 大部分动态语言的实现中都使用了哈希表,哈希表是一种通过哈希函数,将特定的键映射到特定值得一种数据 结构,它维护键和值之间一一对应关系. 键(key):用于操作数据的标示,例如PHP数组中的索引或者字符串键等等. 槽(slot/bucket):哈希表中用于保存数据的一个单元,也就是数组真正存放的容器. 哈希函数(hash function):将key映射(map)到数据应该存放的slot所在位置的函数.…
原子变量: arch/arm/include/asm/atomic.h 定义并初始化 atomic_t v = ATOMIC_INIT(0); 写 void atomic_set(atomic_t *v, int i); 读 int atomic_read(atomic_t *v); 自增, 并返回新值是否为0 int atomic_inc_and_test(atomic_t *v); 自减, 并返回新值是否为0 int atomic_dec_and_test(atomic_t *v); ===…