PHP之所以发现这么迅速,有很大原因是因为数组数据非常好处理,而且它可以存储其他类型的数据
数组的值存储在zvalue_value.ht字段中,ht是一个HashTable的数据
有关于HashTable的知识请移步 >>HASH表和变量
我们来详细说一下数组
PHP里面所有的数据都离不开zval和HashTable,
一个PHP很简单的数组初始化,
在C语言里面实现的却没有那么简单.
经过简单分析,找到数组的初始化的opcode
在Zend/zend_vm_execute.h文件中
[c]
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
array_init(&EX_T(opline->result.u.var).tmp_var); //分配数组内存空间,初始化
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
} else {
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
#endif }
}
[/c]
初始化数组的函数是 array_init
看看它的定义
[c]
ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
{
ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg)); //分配内存
_zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
Z_TYPE_P(arg) = IS_ARRAY; //类型为数组
return SUCCESS;
}
[/c]
看到没有,Hash表初始化函数_zend_hash_init
如果对Hash表不清楚 ,猛点这里>>PHP内核研究第二步:HASH表和变量
下面我们实验一下,
用扩展创建一个空数组,然后用PHP var_dump;
至于如何扩展PHP这里不谈
关键代码
[c]
PHP_FUNCTION(confirm_siren_compiled)
{
zval *value;
MAKE_STD_ZVAL(value);
array_init(value);
ZEND_SET_SYMBOL(EG(active_symbol_table),"siren",value);
[/c]
PHP执行代码
[c]
<!--?php dl("siren.so"); confirm_siren_compiled(1); var_dump($siren); ?-->
[/c]
用命令执行 输出
s# /usr/local/php53/bin/php test.php
array(0) {
}
我们成功创建了一个空数组,如果看过 变量那一章的内容,应该会明白confirm_siren_compiled都做了什么
不懂的话 猛击>>PHP内核研究第二步:HASH表和变量
但是创建一个空数组 ,是没有意义的,如何添加键,值?
添加一个元素的关键代码
[c]
PHP_FUNCTION(confirm_siren_compiled)
{
zval *value;
zval *element;
char *s="this is a value";
char *key="a";
MAKE_STD_ZVAL(element);
MAKE_STD_ZVAL(value);
array_init(value);
ZVAL_STRING(element,s,strlen(s));
zend_hash_update(value->value.ht,key,strlen(key)+1,(void*)&element,sizeof(zval*),NULL);
ZEND_SET_SYMBOL(EG(active_symbol_table),"siren",value);
}
[/c]
执行PHP 结果如下
s# /usr/local/php53/bin/php test.php
array(1) {
["a"]=>
string(15) "this is a value"
}
zend_hash_update只是给数组添加元素的一种方法 ..
还有很多API可以用,
[c]
函数 说明
add_assoc_long(zval *array, char *key, long n); 添加一个长整型元素。
add_assoc_unset(zval *array, char *key); 添加一个 unset 元素。
add_assoc_bool(zval *array, char *key, int b); 添加一个布尔值。
add_assoc_resource(zval *array, char *key, int r); 添加一个资源。
add_assoc_double(zval *array, char *key, double d); 添加一个浮点值。
add_assoc_string(zval *array, char *key, char *str, int duplicate); 添加一个字符串。duplicate 用于表明这个字符串是否要被复制到 Zend 的内部内存。
add_assoc_stringl(zval *array, char *key, char *str, uint length, int duplicate); 添加一个指定长度的字符串。其余跟add_assoc_string () 相同。
add_assoc_zval(zval *array, char *key, zval *value); 添加一个 zval 结构。 这在添加另外一个数组、对象或流等数据时会很有用
add_index_long(zval *array, uint idx, long n); 添加一个长整型元素。
add_index_unset(zval *array, uint idx); 添加一个 unset 元素。
add_index_bool(zval *array, uint idx, int b); 添加一个布尔值。
add_index_resource(zval *array, uint idx, int r); 添加一个资源。
add_index_double(zval *array, uint idx, double d); 添加一个浮点值。
add_index_string(zval *array, uint idx, char *str, int duplicate); 添加一个字符串。duplicate 用于表明这个字符串是否要被复制到 Zend 的内部内存。
add_index_stringl(zval *array, uint idx, char *str, uint length, int duplicate); 添加一个指定长度的字符串。其余跟add_index_string () 相同。
add_index_zval(zval *array, uint idx, zval *value); 添加一个 zval 结构。 这在添加另外一个数组、对象或流等数据时会很有用。
add_next_index_long(zval *array, long n); 添加一个长整型元素。
add_next_index_unset(zval *array); 添加一个 unset 元素。
add_next_index_bool(zval *array, int b); 添加一个布尔值。
add_next_index_resource(zval *array, int r); 添加一个资源。
add_next_index_double(zval *array, double d); 添加一个浮点值。
add_next_index_string(zval *array, char *str, int duplicate); 添加一个字符串。duplicate 用于表明这个字符串是否要被复制到 Zend 的内部内存。
add_next_index_stringl(zval *array, char *str, uint length, int duplicate); 添加一个指定长度的字符串。其余跟add_next_index_string () 相同。
add_next_index_zval(zval *array, zval *value); 添加一个 zval 结构。 这在添加另外一个数组、对象或流等数据时会很有用。
[/c]
具体使用方法很简单,看参数名称就知道方法了,自己试验吧...
相关推荐
(3)利用内核模块编程,在 /proc 目录下用自己的学号创建一个目录,如 /proc/201300834101,然后在学号目录下创建一个 processinfo 文件,如 /proc/201300834101/processinfo,此文件为只读文件,用于显示所有内核...
ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程
《寒江独钓:Windows内核安全编程》是一本深入探讨Windows操作系统内核安全与编程技术的专业书籍,其中包含了光碟源码,特别是与“minifilter”相关的实践案例。在Windows系统中,内核安全编程是确保系统稳定、可靠和...
《寒江独钓:Windows内核安全编程》从Windows内核编程出发,全面系统地介绍了串口、键盘、磁盘、文件系统、网络等相关的Windows内核模块的编程技术,以及基于这些技术实现的输入密码保护、防毒引擎、文件加密、网络...
在"windows内核研究(部分微软内部资料)"这个压缩包中,我们可以期待找到深入探讨Windows内核机制和NT技术的专业资料。这些资料可能包括微软内部的培训文档、白皮书、技术论文和其他宝贵的教育资源。 1. **Windows...
《Windows内核研究》 Windows内核是操作系统的核心部分,负责管理硬件资源、调度进程、提供系统服务等关键任务。深入研究Windows内核对于理解操作系统的工作原理、优化系统性能、开发驱动程序以及进行系统安全分析...
【电子科技大学Linux内核课程课件】:这份资源是针对电子科技大学研究生级别的Linux内核技术课程精心准备的,旨在深入探讨Linux操作系统的核心机制。由知名作者Robert Love编著的教材,为学生提供了一套系统而全面的...
Linux内核提权攻击研究 Linux操作系统中,提权攻击是一种重要的攻击手段,针对Linux系统的安全性构成了严重的威胁。根据提权攻击所利用的漏洞类型,可以将其分为应用层提权攻击和内核提权攻击。内核提权攻击是指...
Linux 内核模块编程是 Linux 操作系统内核开发的核心组成部分,它允许开发者创建自定义的内核模块,从而扩展 Linux 内核的功能。 Linux 内核模块编程需要深入了解 Linux 内核的架构和机制,因此本指南提供了详细的...
Linux内核是开源的,这使得开发者和研究者能够深入理解其内部运作,进而优化和定制自己的系统。以下是对Linux内核一些关键知识点的详述: 1. **内核架构**:Linux内核采用微内核架构,主要负责进程管理、内存管理、...
7. Array与HashTable:介绍数组在PHP内核中的表现形式,如何操作HashTable以及在内核中操作PHP语言中的数组。 8. PHP中的资源类型:资源是PHP中用来表示外部资源的一种特殊类型,包括持久化资源和它们的引用计数...
《Linux内核研究与探索》是一本深入剖析Linux内核的专著,旨在帮助读者理解这个开源操作系统的核心机制。PDF格式使得这本书可以方便地在电子设备上阅读和查阅,为那些热衷于研究Linux内核的技术爱好者提供了丰富的...
光盘源代码则提供了实践学习的宝贵素材,让读者能够直观地理解并研究Windows内核的实际实现。以下是关于Windows内核的一些关键知识点: 1. **微内核架构**:Windows NT系列操作系统采用的是混合微内核架构,这意味...
编写本书是为了向学生和专业人员提供在Linux内核中实现网络功能时所需的基础知识,本书也适合所有希望深入理解操作系统内部网络特定进程的人。本书介绍了Linux内核的关键网络组件及机制,同时也介绍了通信系统的设计...
详细描述了linux2.4/2.6内核版本中的网络子系统。解释了协议的工作方式、建立了Linux网络体系结构中的多种重要概念——从设备驱动程序概念一直到应用程序接口的概念。能帮助读者更容易理解 Linux网络架构的进程和...
【Linux操作系统内核分析与研究】 Linux操作系统内核是整个操作系统的核心部分,负责管理和调度硬件资源,确保系统的高效运行。其主要功能包括: 1. **内存管理**:Linux内核负责内存的分配、释放和页面交换,以...
1. **哈希表(Hashtables)**:PHP内核中广泛使用哈希表存储数组、对象和变量。这是一种高效的数据结构,通过键值对进行查找和存储。哈希表的实现涉及到哈希函数、冲突解决策略以及内存管理。 2. **SAPI(Server ...
内核负责进程的创建、销毁、调度和同步。理解进程生命周期、上下文切换和信号机制是学习内核的重要部分。 3. **内存管理**:Linux内核通过虚拟内存系统实现了物理内存的高效利用。它包括页表、页缓存、内存分配策略...
Linux内核是一个开源的操作系统内核,由林纳斯·托瓦兹于1991年创建。它遵循GNU General Public License(GPL),鼓励全球开发者参与改进和扩展。Linux内核的模块化设计使得它可以根据不同的硬件平台进行定制,适用...