当前位置:首页 > 日记 > 正文

PHP内核介绍与扩展开发指南-基础知识

PHP内核介绍与扩展开发指南-基础知识
1。基本知识
本章简要介绍了Zend引擎内部的一些机制,以扩展密切相关,帮助我们写出更高效的PHP代码。
1.1 PHP变量存储
1.1.1 zval结构
Zend使用zval结构存储PHP变量的值,如下所示:
复制代码代码如下所示:
_zvalue_value { typedef联盟
长语句长值; / * * /
双双双值; / * * /
struct {
字符*;
Int len;
STR };
哈希表*哈希表值; / * * /
zend_object_value obj;
zvalue_value };
结构_zval_struct {
变量信息
zvalue_value值; / * * /
zend_uint引用计数;
zend_uchar型活跃型; / * * /
zend_uchar is_ref;
};
_zval_struct zval结构定义;
Zend决定价值的成员访问基于型值和有效值如下:

is_nulln /

is_long对应value.lval

is_double对应value.dval

is_string对应value.str

is_array对应value.ht

is_object对应value.obj

is_bool对应value.lval。

is_resource对应value.lval

根据此表可以在两个地方感兴趣的发现:首先是PHP数组实际上是一个哈希表,这也解释了为什么PHP支持关联数组;其次,资源是一个长期的价值,它包含了通常是一个指针,指数或其他只有你知道事情的创造者,一个内部数组,这可以看成是一个手柄

1.1.1参考计数

引用计数被广泛用于垃圾收集,存储池,和字符串,和Zend实现了一个典型的引用计数,多个PHP变量可以通过引用计数机制共享相同的变量共享,和剩余的两个成员变量,is_ref和引用计数,用来支持这个共享。

很显然,引用计数用于计数,当参考加值的增加和减少,因此,一旦它被减少到零,Zend将恢复机制。

那么,is_ref

1.1.2 zval状态

在PHP中,有两类变量的引用和非引用,它们存储在Zend引用计数的方式。对于非引用类型的变量,变量需要对方,修改一个变量,不能影响其他变量,使用copy-on-write机制可以解决冲突时写一个Zend的变量,如果发现变量指向变量的多变量共享,是一份原始变量1变量引用计数,并减少引用计数,这个过程叫做zval。然而,对于引用变量,要求不同于非引用类型。分配给作业的变量必须被捆绑。修改一个变量修改所有捆绑变量。

很明显,需要指出的是,机制的当前状态两种情况分别处理。is_ref是目的。指出是否指向变量的引用或未分配的所有变量。变量是在这个时候,修改,和Zend将执行写时复制只有当其机制的is_ref为0,即非参考。

1.1.3 zval状态切换

当所有的赋值操作在zval引用或不引用,一个is_ref足以应付。然而,世界将不会那么好。PHP不能限制用户。当我们引用引用和非引用赋值时,我们必须进行特殊处理。

案例I,看看下面的PHP代码:
整个过程如下:

的第一个三字代码将A,B和C的一个机制,is_ref = 1,引用计数= 3;第四是非引用赋值,通常只需要增加引用计数。然而zval属于参考变量的目标,增加引用计数显然是错误的,解决的办法是Zend单独产生复制机制D.

整个过程如下:
1.1.1参数传递

PHP函数的传递和变量的赋值是相同的。非引用转换等同于非引用赋值。参考转让相当于引用赋值,也可能导致机制状态切换的执行。这将在后面讲到。

1.2哈希表结构

哈希表是Zend引擎的最重要和最广泛使用的数据结构,用于存储几乎一切。

1.1.1数据结构

哈希表的数据结构定义如下:
复制代码代码如下所示:
typedef struct斗{
页H / /存储散列;
单位nkeylength;
void * pData; / /指针的值,是一份用户数据
void * pdataptr;
结构斗* plistnext; / / plistnext和plistlast。
结构斗* plistlast; / /双链表,哈希表
结构斗* pnext;一个散列 / / pnext和塑料
结构斗*塑料; / /双链表
字符都可以实现{ 1 }; / /关键
桶};
_hashtable { typedef struct
单位ntablesize;
Uint nTableMask;
单位nnumofelements;
nnextfreeelement页;
斗* pinternalpointer用于元素遍历; / * * /
plisthead斗*;
plisttail斗*;
斗* arbuckets; / /哈希数组
dtor_func_t pdestructor; / /指定的哈希表的初始化,叫斗的破坏
Zend_bool persistent; / / memory allocation routines whether the use of C
unsigned char napplycount;
zend_bool bapplyprotection;
如果zend_debug #
int一致;
# endif
哈希表};

In general, Zend's HashTable is a chain hash and is also optimized for linear traversal, which is illustrated as follows:
哈希表包含两个数据结构,一个列表的哈希和双链表。前者用于快速键值查询,便于线性遍历和排序,在两种数据结构中都存在一个桶。
对数据结构的几种解释:
为什么在L链散列中使用双向链表
一般的哈希链只需要操作的关键,只有单链表是必要的。然而,Zend有时需要从链表中删除一个给定哈希桶,和一个双链表的使用可以非常有效的。
我ntablemask做什么
这个值是使用的哈希值转换为arbuckets数组下标。初始化哈希表时,Zend首先将ntablesize大小的内存arbuckets阵列,和ntablesize不小于最小的2 ^ n由用户指定,即二进制的10。ntablemask = ntablesize u2013 1,即二进制的01 *,当H ntablemask正好落在{ 0,1 } ntablesize u2013,Zend使用它作为访问arbuckets数组索引。
我pdataptr做什么
通常情况下,用户插入一个键值对的时候,Zend拷贝一份价值点的数据到一个值复制。复制操作需要调用Zend内部常规emalloc分配内存,这是一个非常耗时的操作和消耗比价值更大的内存。(如果更多的内存用于存储cookie),如果值很小,这将导致更大的浪费。考虑到HashTable主要是用来存储指针的值,或者引入pdataptr。当价值是只要一个指针,它直接pdataptr Zend的副本,和点数据来pdataptr。这避免了emalloc操作,也有助于提高缓存命中率。
为什么只有1的大小都可以实现不使用指针来管理关键
ArKey是关键的一个数组,但其规模仅为1,不足以放下的关键。下面的代码可以在初始化函数找到HashTable:
1P =(桶*)pemalloc(sizeof(桶)- 1 + nkeylength,HT ->持续);
可以看出,Zend拨斗,足以放下本身,关键的一段记忆,
L的上半部分是斗,下部是关键,并且都可以实现是斗的最后一个元素,所以你可以使用都可以实现访问的关键。这种技术在内存管理程序是最常见的,而分配内存,实际上是分配的内存比指定的大小,上部常被称为饼干,存储内存的信息,如块的大小,一个指针,指针。百度用这种方法传输程序。
没有指针用于管理密钥,减少emalloc操作,同时也增加了缓存的命中率。另一个重要的原因是,关键是固定的,并不会重新分配整个斗因为更长时间的关键。这也解释了为什么价值分配不在一起为一个阵列,因为价值变量。
1.2.2 PHP数组
还有一个问题关于哈希表,没有回答,这是什么nnextfreeelement呢
不同于一般的哈希,哈希表可以允许用户指定的哈希值,而忽略了重点,甚至没有指定密钥(nkeylength这时0)。同时,HashTable也支持附加操作。用户不需要指定散列值。他们只需要提供价值。在这个时候,Zend采用nnextfreeelement作为哈希,然后nnextfreeelement增加。
Hashtable这种行为看起来很奇怪,因为它不能够通过密钥访问的价值,它不是一个哈希完全,对问题的理解的关键是,PHP数组是使用哈希表-关联数组使用哈希表实现正常的元素为K-V映射,用户指定的键字符串;非联想数组作为数组索引的哈希值,关键是不存在的;与相关和非相关混合阵列时,或使用array_push操作,你需要使用nnextfreeelement。
再看价值。PHP数组的值直接使用机制的通用结构。数据是指zval *。根据上一节的介绍,zval *将直接存储在pdataptr。因为机制直接使用,该数组的元素可以是任意PHP类型。
阵列,即foreach遍历操作,每个等,通过双链表,哈希表做。PInternalPointer作为一个指针记录当前位置。
1.2.3变量符号表
除了阵列,HashTable也用来储存大量的其他数据,如PHP函数,变量符号,加载的模块、类成员,等等。
变量符号表等效于关联数组。它的关键是变量名。(可见,用一个很长的变量名是不是一个好主意),价值机制*。
在任何一个时间的PHP代码,可以看到两个变量:symbol_table和active_symbol_table:符号表用于存储全局变量,称为全局符号表;后者是一个指针变量的符号表的当前活动,通常是全局符号表。然而,当进入一个PHP函数的时候,它是指利用PHP代码的用户创建的功能。Zend将创造和点active_symbol_table的局部符号表函数的局部变量符号表。Zend总是用active_symbol_table访问变量,从而实现局部变量的范围控制。
然而,如果函数的本地访问标记为全局变量,可以将做特殊处理,创造symbol_table在active_symbol_table在相同名称的变量的引用,如果在symbol_table没有命名空间变量,它将创造第一。
1.3内存和文件
程序拥有的资源通常包括内存和文件。对于正常程序,这些资源是面向过程的。当过程完成时,操作系统或C库将自动回收我们未显式释放的资源。
然而,PHP程序有其特殊性。它是基于页面的。当页面运行时,它也将应用于内存或文件等资源。然而,当页面运行时,操作系统或C库可能不知道它所需要的资源回收。例如,我们PHP编译成模块和运行在Apache prefork模式Apache或工人。在这种情况下,Apache进程或线程是可重复使用,并通过PHP页面分配的内存将保留在记忆中直到核心。
为了解决这个问题,可以提供一组内存分配API,它的功能就像C的相应功能。不同的是,这些函数分配内存,从Zend自己的内存池,可以实现基于页面的自动恢复。在我们的模块,分配的内存页面应该使用这些API而不是C例程。否则,Zend将饱和在页末我们的记忆力下降,结果通常是粉碎。
Emalloc()
依芙利特()
Estrdup()
Estrndup()
Ecalloc()
Erealloc()
此外,Zend还提供了一组宏,如vcwd_xxx,取代C库和相应的API操作系统。这些宏可以支持PHP的虚拟目录,他们应该使用模块代码。该宏的具体定义称为PHP源码TSRM / tsrm_virtual_cwd.h.maybe你会发现所有的宏不提供关闭操作,这是因为接近的对象是开放的资源,对文件路径不相关,那么你可以直接使用C或读/写操作系统例程;同样,这样的操作也是直接使用C或操作系统例程。

相关文章

是arupld32.exe过程有毒吗是arupld

是arupld32.exe过程有毒吗是arupld

过程,电脑软件,exe,点评:arupld32.exe会监视你的浏览行为。这个过程会在后台的工作来回报你的浏览习惯,为经营宗旨 进程文件:arupld32或arupld32.exe 进程名称:arupld32 过程类别:安全风险的过程 英文描述: arupld32.exe是过程监控你的上网习惯…

USB3.0驱动win7系统(AMDA68/A75芯片

USB3.0驱动win7系统(AMDA68/A75芯片

芯片组,系统,电脑软件,计算机处理器是AMD A68,主板是A75芯片组,如果用户使用Win7系统,USB3.0驱动没有安装好。USB3.0驱动与这个驱动程序共享,适用于Windows 7 32bit 位或64位。 USB3.0驱动百度的SkyDrive,点击这里下载。…

为了解决部分的出现并没有结束%端

为了解决部分的出现并没有结束%端

安装系统,多拉,结束,电脑软件,点评:Fedora安装在VMware虚拟机的今天,结果出现部分误差不结束%结束 如下: 当狗被搜查,发现我用VMware向导安装Fedora的。所以,如何解决它。 方法一:不使用VMware的操作系统安装向导 方法二:删除自动安装的CD-ROM…

MySQLbinlog二进制日志的详细解释

MySQLbinlog二进制日志的详细解释

解释,二进制日志,详细,电脑软件,MySQLbinlog,基本概念 定义 uff1a 二进制日志包含更新数据或潜在更新数据的所有语句(例如,不匹配任何行的删除)。 uff1a效应 1、二进制日志的主要目的是将数据库恢复到尽可能大的更新,因为二进制日志包含备份之…

AmethodofrefusingshutdownduringW

AmethodofrefusingshutdownduringW

电脑软件,AmethodofrefusingshutdownduringWinXPsystemlocking,点评:这篇文章主要介绍了拒绝关闭WinXP系统锁定在该方法中,需要的朋友可以参考一下。 作为上班族,在机器的过程中,经常被事务性的工作,需要暂时离开办公室去分发文件,方便和安全的需…

停在屏幕在Windows启动时win7启动(

停在屏幕在Windows启动时win7启动(

启动,解决方案,屏幕,停在,启动时,问题: 该系统使用U盘安装win7的笔记本。在安装过程中重新启动时,它停留在Windows引导屏幕上,并且不继续安装。同样,XP系统的安装非常顺利。原因何在 答案uff1a 根据这一点,它可能是GHOST版的系统有问题。因为G…

Oracle删除表字段和Oracle表以添加

Oracle删除表字段和Oracle表以添加

字段,删除表,电脑软件,Oracle,添加的字段的语法:tablename表添加(列数据类型的默认值} { {空/非空},…); 修改字段的语法:tablename表的修改(列数据类型的默认值} { {空/非空},…); 删除该字段的语法:去掉表(列); 添加、修改、删除多栏,用逗号隔开。 …

如何在Windows中启用自动登录是自

如何在Windows中启用自动登录是自

执行,启用,登录,自动登录,过程,注释:通过将密码和其他相关信息存储在注册表数据库中,Windows被配置为自动执行登录过程。此功能允许其他用户启动您的计算机并自动登录您的帐户,感兴趣的朋友可以理解它。 本文介绍如何配置Windows,通过在注册表…

深入理解linux页面缓冲区缓存

深入理解linux页面缓冲区缓存

缓存,页面,电脑软件,linux,评论:页面缓存和缓存缓存一直是两个混淆的概念,在这段时间内我工作,页面缓存和缓存缓存的概念让我困惑,如果您能理解两个缓存的本质,那么我们在分析IO问题时就更方便了。 页面缓存和缓冲区高速缓存已两混淆的概念,在互…

Linux用户相关的命令(passwd/苏)

Linux用户相关的命令(passwd/苏)

用户,命令,电脑软件,Linux,passwd,点评:passwd命令passwd命令来修改你的密码。 passwd命令 使用passwd命令来修改你的密码。 Grammar: 语法是 passwd命令开关} { 指令开关: - 显示密码属性的所有项。 l 锁定密码。 D 删除用户密码,登录将不…

解决方案,不能分区和分区不能格式化

解决方案,不能分区和分区不能格式化

安装,格式化,解决方案,过程中,电脑软件,点评:系统分区要求(如分区格式和空间大小)始终是关于用户的话题,相关的主题和我的XP怎么不能安装Windows 7,当用户安装它时,如果不能格式化,而重新创建分区就可以参考这个了。 在Windows XP推出之前,系统分区…

101MySQL优化技巧和技巧

101MySQL优化技巧和技巧

优化技巧,技巧,电脑软件,MySQL,MySQL服务器硬件和操作系统调整: 1,我们有足够的物理内存来加载整个InnoDB文件到内存。在内存中访问文件比在硬盘中访问要快。 2。不惜任何代价避免使用交换交换分区——它在切换时从硬盘读取,而且速度非常慢。…