http://www.nowamagic.net/librarys/veda/special/PHP%E5%86%85%E6%A0%B8%E6%8E%A2%E7%B4%A2 关注PHP 源代码 Zend\zend.h
------------------------------------------------------
变量的值由一个结构体构成
struct _zval_struct{ zvalue_value value; /*变量的值 */
zend_uint refcount_gc;/*指向的次数*/
zend_uchar type; /*变量类型*/
zend_uchar is_ref_gc;/*是否引用*/ } type字段值为以下常量(8种数据类型)
IS_NULL,IS_BOOL,IS_LONG,IS_DOUBLE
IS_STRING,IS_ARRAY,IS_OBJECT,IS_RESOURCE
----------------------------------
zvalue_value:类型的结构union typedef union _zvalue_value{ long lval double dval struct{
char *
int len;
}str; HashTable * ht; //数组类型 zend_object_value obj;
} zvalue_value; PHP中有8种数据类型,为什么zvalue_value->value联合体中,只有5种?
答:
1:NULL直接zval->type=IS_NULL,就可以表示不必设置vaLue的值
2:BOOL型 ,zval->type=IS_BOOL,再设置 zval.value.lval=1/0
3:Resoure型,资源型,往往是服务器上打开的一个接口,如 文件读取接口
zval->type=IS_RESOURCE,zval.value.lval=服务器上打的接口的编号 PHP字符串类型,长度是已经缓存的,调用STRLEN 时系统可直接返加其长度,不必计算 ----------------------------------------
zvalue_zvalue: 值内容
lval
dval
struct str
*ht
obj type: 值类型 refgc_count is_ref_gc
----------------------------------------------
php底层变量的实现
eg:
<?php $a=3; /*
{ union_zvalue{long 3}
type IS_LONG
refcount_gc:1
is_ref_gc:0
} */ $b='hello'
/* { {char:'hello'
len:5
} type:IS_STRING
refcount_gc:1
ls_ref_gc:0 } */
> --------------------------------------------------------------------- 符号表:symbol_table 符号表是一张哈希表,里面存储了变量名->变量的ZVAL结构体的地址
zeng/zend_globals.h中的HashTable symbol_table定义 eg:
<?php $a=3
$b=4.321
$c='hello'; /*****
生成了3个结构体,
同时,全局符号表中,多了3条记录
a----->0x123---->结构体{3}
b----->ox21d---->结构体{4.321}
c----->0x3A0---->结构体{HELLO}
***/ > 变量的赋值与引用 <?php $a=3;
$b=$a; /*****
产生一个结构体 ****
/ ------------------------------------------------------
当变量a赋值
$a=3
当前结构体:
zvalue:3
type:IS_LONG
refcont_gc:1
is_ref_gc:0 当变量$a给$b赋值时
$b=$a 结构体变为:
zvalue:3
type:IS_LONG
recount_gc:2
is_ref_gc:0 这样没有发声结构体复制,省空间,
两个变量指向同一个结构体,refcount_gc值从1变为2 -----------------------------------------------------
写时复制copy on write <?php $a=3;
$b=$a; /*****
产生一个结构体 ****/ $b=5
/**** 符号表中$a指向下面结构体
zvalue:3
type:IS_LONG
recount_gc:1
is_ref_gc:0
---------------------------------------------------------------------
符号表$b,指向另外一个结构体(一开始共用,到某一方要修改值时才分裂:copy on write)
zvalue:5
type:IS_LONG
recount_gc:1
is_ref_gc:0 ****/ echo $a,$b;3,5 没有干扰到对方
------------------------------------------- 引用复制特点
引用时,is_ref_gc=1,说是这个结构体与变量是引用关系,改的时候,不分裂
直接修改什,所有指向此结构体的变量,值都变化 EG:
$a=3 zvalue:3
type:IS_LONG
refcount_gc:1
is_ref_gc:0 当$b=&a //引用 $b与$a同时指向一个结构体
zvalue:3
type:IS_LONG
refcount_gc:2
is_ref_gc:1 $b=5 :结构体不分裂
结构体还是如下 zvalue:3
type:IS_LONG
refcount_gc:2
is_ref_gc:1
-----------------------------------------------------------------------
<?php
//强制分裂 $a=3; /***
{
value:3
refcount_gc:1
is_ref_gc:0
}
**/ $b=$a; /***
{
value:3
refcount_gc:2
is_ref_gc:0 }
**/ $c=&a;
//不会是如下这样变,否则,$b将会受干扰
/***
{
value:3
refcount_gc:3
is_ref_gc:1 }
**/ //如果ls_ref_gc 0->的过程中,recount_gc>1,将会强制分裂
$b分烈一份结构体
{ value:3
refcount_gc:1
is_ref_gc:0 } $a,$c结构体如下
{
value:3
refcount_gc:2
is_ref_gc:1
} $c=5 echo $a,$b,$c 5,3,5
------------------------------------------------------------------- <?php
$arr=array(0,1,2,3);
$tmp=$arr; $arr[1]=11;
echo $tmp[1]; //1 分析:
$arr=array(0,1,2,3)
结构体: zvalue:*ht ---------->0 addr1------->zval:0
type:IS_ARRAY 1 addr2-------->zval:1
refcount_gc:1 2 addr3--------->zval:2
is_ref-gc:0 3 addr4---------zval:3
|
|
$tmp=$arr----------------- $tmp 结构体
zvalue:*ht
type:IS_ARRAY
refcount_gc:2
is_ref-gc:0 --------------------------------------------------------------------
$arr[1]=11 此时结构 zvalue:*ht ---------->0 addr1------->zval:0
type:IS_ARRAY 1 addr2-------->zval:11
refcount_gc:1 2 addr3--------->zval:2
is_ref-gc:0 3 addr4---------zval:3 些时的$tmp结构: zvalue:*ht ---------->0 addr1 //指向arr
type:IS_ARRAY 1 addr2-------->zval:1(自已创建的)
refcount_gc:1 2 addr3 //指定arr
is_ref-gc:0 3 addr4 //指定arr -------------------------------------------------------------------------------------------- $arr=array(0,1,2,3)
$x=&arr[1];
$tmp=$arr; $arr[1]=999
echo $tmp[1] //999
------------------------------------------------------ 查看PHP函数的C语言实现:
cd php-src
查找 grep -rn "PHP_FUNCTION(socket_accept)" ./ext
返回 ./ext/sockets/sockets.c:938:PHP_FUNCTION(socket_accept)
查找 grep -rn "PHP_FUNCTION(array_merge)" ./ext
返回 ./ext/standard/array.c:2266:PHP_FUNCTION(array_merge)
可以看出,PHP库函数的基本都在php-src/ext目录下,里面有具体函数库比如socket,一般的函数基本都在标准库standard. PHP源码的几个重要目录:
ext(扩展) 108M
Zend(引擎) 9.2M
sapi(cli/cgi/mod_php/fpm) 3.1M
php内核探索的更多相关文章
-
php内核探索 [转]
PHP内核探索:从SAPI接口开始 PHP内核探索:一次请求的开始与结束 PHP内核探索:一次请求生命周期 PHP内核探索:单进程SAPI生命周期 PHP内核探索:多进程/线程的SAPI生命周期 PH ...
-
PHP内核探索之变量(7)- 不平凡的字符串
切,一个字符串有什么好研究的. 别这么说,看过<平凡的世界>么,平凡的字符串也可以有不平凡的故事.试看: (1) 在C语言中,strlen计算字符串的时间复杂度是?PHP中呢? ...
-
PHP内核探索之变量(6)- 后续内核探索系列大纲备忘
年前因为工作比较饱和,现在又忙着换工作的事情,基本停止了对博文的更新.后续的博文,还是慢慢补上吧. 为了不至于过于发散,先搞个未成形的大纲,如下: PHP内核探索之变量 不平凡的字符串 PHP内核探 ...
-
PHP内核探索之变量(5)- session的基本原理
这次说说session. session可以说是当前互联网提到的最多的名词之一了.它的含义很宽泛,可以指任何一次完整的事务交互(会话):如发送一次HTTP请求并接受响应,执行一条SQL语句都可以看做一 ...
-
PHP内核探索之变量(4)- 数组操作
上一节(PHP内核探索之变量(3)- hash table),我们已经知道,数组在PHP的底层实际上是HashTable(链接法解决冲突),本文将对最常用的函数系列-数组操作的相关函数做进一步的跟踪. ...
-
PHP内核探索之变量(3)- hash table
在PHP中,除了zval, 另一个比较重要的数据结构非hash table莫属,例如我们最常见的数组,在底层便是hash table.除了数组,在线程安全(TSRM).GC.资源管理.Global变量 ...
-
PHP内核探索之变量(2)-理解引用
本文主要内容: 引论 符号表与zval 引用原理 回到最初的问题 一.引论 很久之前写了一篇关于引用的文章,当时写的寥寥草草,很多原理都没有说清楚.最近在翻阅Derick Rethans(home: ...
-
PHP内核探索之变量(1)Zval
作为数据的容器,我们常常需要跟变量打交道,不管这个变量是数字.数组.字符串.对象还是其他,因而可以说变量是构成语言的不可或缺的基础.本文是PHP内核探索之变量的第一篇,主要介绍zval的基本知识,包括 ...
-
PHP内核探索:哈希碰撞攻击是什么?
最近哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现. 哈希表碰撞攻击的基本 ...
-
24小时学通Linux内核--内核探索工具类
寒假闲下来了,可以尽情的做自己喜欢的事情,专心待在实验室里燥起来了,因为大二的时候接触过Linux,只是关于内核方面确实是不好懂,所以十天的时间里还是希望能够补充一下Linux内核相关知识,接下来继续 ...
随机推荐
-
.NET 基础一步步一幕幕[out、ref、params]
out.ref.params out: 如果你在一个方法中,返回多个相同类型的值的时候,可以考虑返回一个数组. 但是,如果返回多个不同类型的值的时候,返回数组就不行了,那么这个时候, 我们可以考虑使用 ...
-
Python 学习---------Day4
第十章 Python语句简介Python的代码书写要求,以及换行等语句可以扩越多行,只要将其封闭在圆括号内,方括号内或大括号内即可,可以使用分号终止.用\可以允许我们跨越多行一个简单的交互式循环whi ...
-
常用的几种 SQLServer 分页查询方式实现
SQLServer 的数据分页: 假设现在有这样的一张表:CREATE TABLE test( id int primary key not null identity, names varchar( ...
-
《转》高级Unix命令
原文链接:http://coolshell.cn/articles/1044.html 在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thi ...
-
工厂方法模式 - OK
工厂方法模式(Factory Method),定义了一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到子类. 工厂方法模式在实现时,客户端需要决定实例化哪一个工厂来实现运 ...
-
[ACM] POJ 3686 The Windy&;#39;s (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
-
Linux开机启动(bootstrap)上
Linux开机启动(bootstrap) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 计算机开机是一个神秘的过程.我们只是 ...
-
EOF \n \0 NULL 之间的区别
\n 是换行符 \0 是字符串的结束标志 EOF是流的结束标志 FILE* 这种流 NULL 是指针为空 第一个问题是EOF 它是end of file的缩写,表示"文字流"(s ...
-
scrapy抓取拉勾网职位信息(二)——拉勾网页面分析
网站结构分析: 四个大标签:首页.公司.校园.言职 我们最终是要得到详情页的信息,但是从首页的很多链接都能进入到一个详情页,我们需要对这些标签一个个分析,分析出哪些链接我们需要跟进. 首先是四个大标签 ...
-
1.windows下GIT 服务安装
本章介绍简单在windows 安装git 服务方法.服务器端采用的是Bonobo Git Server,一款用ASP.NET MVC开发的Git源代码管理工具,界面简洁,基于Web方式配置,简单易用. ...