php内核探索
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内核相关知识,接下来继续 ...
随机推荐
- Java 类型信息
<Thinking in Java 4th>第14章 类型信息 运行时类型信息(Run-Time Type Identification)使得你可以在程序运行时发现和使用类型信息. 14. ...
- Hadoop概念学习系列之常见的分布式文件系统(二十六)
常见的分布式文件系统有,GFS.HDFS.Lustre .Ceph .GridFS .mogileFS.TFS.FastDFS等.各自适用于不同的领域.它们都不是系统级的分布式文件系统,而是应用级的分 ...
- Javascript函数柯里化(curry)
函数柯里化currying,是函数式编程非常重要的一个标志.它的实现需要满足以下条件,首先就是函数可以作为参数进行传递,然后就是函数可以作为返回值return出去.我们依靠这个特性编写很多优雅酷炫的代 ...
- KMP(http://acm.hdu.edu.cn/showproblem.php?pid=1711)
http://acm.hdu.edu.cn/showproblem.php?pid=1711 #include<stdio.h> #include<math.h> #inclu ...
- 时隔3年,再次折腾BlackBerry 8830!
2010年手头换得8830,之后就是好几番刷机.解SPC.倒腾各种软件..算软件注册码..那个时候记得最难弄的注册码就是crunchSMS.需要运行虚拟机来从内存地址读取注册码..不过黑莓真的很经得起 ...
- H3C远程登陆配置
1.配置本地用户(默认权限 level 1) [H3C]local-user admin [H3C-luser-admin]password cipher [H3C]super password le ...
- 使用MSSQL,连接oracle,对oracle数据进行操作
EXEC sp_addlinkedserver--创建链接服务器.链接服务器让用户可以对 OLE DB 数据源进行分布式异类查询. @server = 'Mktg',--要创建的链接服务器的名称.s ...
- c++中指针类型在c#中怎么对应?
int[] a=new int[5]; //取a[3]的地址 IntPtr addr=System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinned ...
- 使用java发送邮件sp自动发送邮件方法
注意:将jar包复制到web-info文件夹下lib: activation.jar mail.jar //发送邮箱 public static String sendEmail(String sen ...
- Spring REST实践之REST基本介绍
REST是什么 REST(REpresentational State Transfer)是一个设计分布式web应用的框架风格,有六个基本原则: Client-Server:应用的参独立与者可分为Cl ...