`
dengbaoleng
  • 浏览: 1162921 次
文章分类
社区版块
存档分类
最新评论

原创:PHP内核研究 常量

 
阅读更多
声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。
博客地址:PHP技术博客在CSDN也会同步更新的哦.
欢迎转载,转载请注明出处

常量

什么是常量.

常量就是不变的量.
先看看常量的结构

[c]
typedef struct _zend_constant {
zval value;//zval类型
int flags;//标示 是否大小写敏感
char *name;//常量名称
uint name_len;//长度
int module_number;//标示是用户定义的常量 不是系统常量
} zend_constant;
[/c]


PHP定义常量如下

[php]

<?php

define('TEST',1);

[/php]

很简单 .定义了一个常量

那在内核里都做了什么?

打开 zend/zend_builtin_functions.c PHP的内置函数都在这里

找到 ZEND_FUNCTION(define)

代码如下

[c]

ZEND_FUNCTION(define)
{
char *name;
int name_len;
zval *val;
zval *val_free = NULL;
zend_bool non_cs = 0;
int case_sensitive = CONST_CS;
zend_constant c;//这个是常量的struct

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
return;
}

if(non_cs) {//define第三个参数的作用,大小写是否敏感 如果为真 大小写不敏感
case_sensitive = 0;
}

//PHP5.3新特性:类常量,暂不做介绍
if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
zend_error(E_WARNING, "Class constants cannot be defined or redefined");
RETURN_FALSE;
}

repeat:
//类型检测
switch (Z_TYPE_P(val)) {
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
case IS_BOOL:
case IS_RESOURCE:
case IS_NULL:
break;
case IS_OBJECT:
if (!val_free) {
if (Z_OBJ_HT_P(val)->get) {
val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
goto repeat;
} else if (Z_OBJ_HT_P(val)->cast_object) {
ALLOC_INIT_ZVAL(val_free);
if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
val = val_free;
break;
}
}
}
/* no break */
default:
zend_error(E_WARNING,"Constants may only evaluate to scalar values");
if (val_free) {
zval_ptr_dtor(&val_free);
}
RETURN_FALSE;
}

c.value = *val; //拷贝常量的值
zval_copy_ctor(&c.value);//完全拷贝 因为val是zval类型,除了value还有其他属性,用这个宏完全拷贝过来
if (val_free) {
zval_ptr_dtor(&val_free);
}
c.flags = case_sensitive; //大小写敏感?
c.name = zend_strndup(name, name_len); //拷贝name
c.name_len = name_len+1;
c.module_number = PHP_USER_CONSTANT; //标示是用户创建的常量而不是系统常量
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) { //添加到常量符号表里.
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
[/c]

既然说了define 那就肯定要说说defined了
defined用来检测 常量是否已经定义
这个其实很简单 代码如下

[c]
ZEND_FUNCTION(defined)
{
char *name;
int name_len;
zval c;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}

if (zend_get_constant_ex(name, name_len, &c, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {//找到了
zval_dtor(&c); //释放zval.value的内存
RETURN_TRUE;
} else {//没找到
RETURN_FALSE;
}
}
[/c]


主要的工作在 zend_get_constant_ex这个函数里

[c]
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
{
zend_constant *c; //常量类型
int retval = 1;
char *colon;
zend_class_entry *ce = NULL;
char *class_name;
zval **ret_constant;

/* Skip leading \\ */
if (name[0] == '\\') {
name += 1;
name_len -= 1;
}

if ((colon = zend_memrchr(name, ':', name_len)) &&
colon > name && (*(colon - 1) == ':')) { //类常量 暂不做介绍
int class_name_len = colon - name - 1;
int const_name_len = name_len - class_name_len - 2;
char *constant_name = colon + 1;
char *lcname;

class_name = estrndup(name, class_name_len);
lcname = zend_str_tolower_dup(class_name, class_name_len);
if (!scope) {
if (EG(in_execution)) {
scope = EG(scope);
} else {
scope = CG(active_class_entry);
}
}

if (class_name_len == sizeof("self")-1 &&
!memcmp(lcname, "self", sizeof("self")-1)) {
if (scope) {
ce = scope;
} else {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
retval = 0;
}
efree(lcname);
} else if (class_name_len == sizeof("parent")-1 &&
!memcmp(lcname, "parent", sizeof("parent")-1)) {
if (!scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
} else if (!scope->parent) {
zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
} else {
ce = scope->parent;
}
efree(lcname);
} else if (class_name_len == sizeof("static")-1 &&
!memcmp(lcname, "static", sizeof("static")-1)) {
if (EG(called_scope)) {
ce = EG(called_scope);
} else {
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
}
efree(lcname);
} else {
efree(lcname);
ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
}
if (retval && ce) {
if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
retval = 0;
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name, constant_name);
}
}
} else if (!ce) {
retval = 0;
}
efree(class_name);
goto finish;
}

//普通常量 colon为反斜线之前的字符串
if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
/* compound constant name */
int prefix_len = colon - name;
int const_name_len = name_len - prefix_len - 1;
char *constant_name = colon + 1;
char *lcname;
int found_const = 0;

lcname = zend_str_tolower_dup(name, prefix_len);
/* Check for namespace constant */

/* Concatenate lowercase namespace name and constant name */
lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
lcname[prefix_len] = '\\';
memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
//查找常量
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
found_const = 1;//找到了
} else {//没找到
//转换为小写重新查找
zend_str_tolower(lcname + prefix_len + 1, const_name_len);
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {//找到了
if ((c->flags & CONST_CS) == 0) {
found_const = 1;
}
}
}
efree(lcname);
if(found_const) {
*result = c->value;
zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
zval_copy_ctor(result);
Z_SET_REFCOUNT_P(result, 1);
Z_UNSET_ISREF_P(result);
return 1;
}
/* name requires runtime resolution, need to check non-namespaced name */
if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
name = constant_name;
name_len = const_name_len;
return zend_get_constant(name, name_len, result TSRMLS_CC);
}
retval = 0;
finish:
if (retval) {
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
*result = **ret_constant;
zval_copy_ctor(result);
INIT_PZVAL(result);
}

return retval;
}
return zend_get_constant(name, name_len, result TSRMLS_CC);
}
[/c]

define就是将创建的常量 放在EG(zend_constants)里
defined就是在EG(zend_constants)去递归查找


分享到:
评论

相关推荐

    ZendAPI:深入PHP内核编程

    ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程 ZendAPI:深入PHP内核编程

    [网络安全入门与提高.:Windows内核安全编程从入门到实践].林聚伟.扫描版.pdf

    [网络安全入门与提高.:Windows内核安全编程从入门到实践].林聚伟.扫描版.pdf

    寒江独钓:Windows内核安全编程

    资源名称:寒江独钓:Windows内核安全编程资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    基础实验:linux内核的编译与内核模块.doc

    【实验主题】:Linux内核编译与内核模块构建 【实验目的】: 1. 学习和理解Linux内核编译的基本流程。 2. 掌握内核模块的编写和动态加载。 3. 了解交叉编译环境的建立与使用。 4. 熟悉在嵌入式设备(如友善之臂MINI...

    寒江独钓:Windows内核安全编程(光碟源码 )

    寒江独钓:Windows内核安全编程(光碟源码 dp)

    《寒江独钓:Windows内核安全编程》源码

    《寒江独钓:Windows内核安全编程》从Windows内核编程出发,全面系统地介绍了串口、键盘、磁盘、文件系统、网络等相关的Windows内核模块的编程技术,以及基于这些技术实现的输入密码保护、防毒引擎、文件加密、网络...

    Windows内核研究

    《Windows内核研究》 Windows内核是操作系统的核心部分,负责管理硬件资源、调度进程、提供系统服务等关键任务。深入研究Windows内核对于理解操作系统的工作原理、优化系统性能、开发驱动程序以及进行系统安全分析...

    寒江独钓:Windows内核安全

    无论是从理论还是实践的角度来看,加强对Windows内核安全的理解和研究都是非常必要的。通过深入了解内核的工作原理、掌握相关的安全机制,并结合实际开发经验,我们可以在很大程度上提升系统的安全性,抵御潜在的...

    windows内核研究(部分微软内部资料)

    在"windows内核研究(部分微软内部资料)"这个压缩包中,我们可以期待找到深入探讨Windows内核机制和NT技术的专业资料。这些资料可能包括微软内部的培训文档、白皮书、技术论文和其他宝贵的教育资源。 1. **Windows...

    DesignWareDuet:处理器内核设计套件.pdf

    DesignWareDuet:处理器内核设计套件.pdf

    Linux内核提权攻击研究.pdf

    Linux内核提权攻击研究 Linux操作系统中,提权攻击是一种重要的攻击手段,针对Linux系统的安全性构成了严重的威胁。根据提权攻击所利用的漏洞类型,可以将其分为应用层提权攻击和内核提权攻击。内核提权攻击是指...

    电子科技大学linux内核课程课件:LINUX内核技术(第1份共2份)

    在深入学习Linux内核技术的道路上,电子科技大学提供的这门研究生课程课件是一份宝贵的资源。基于Robert Love的著作,这套课件为学生和自学者提供了全面而深入的Linux内核理解。本文将针对课件中的章节进行详细解析...

    电子科技大学linux内核课程课件:LINUX内核技术(第2份共2份)

    【电子科技大学Linux内核课程课件】:这份资源是针对电子科技大学研究生级别的Linux内核技术课程精心准备的,旨在深入探讨Linux操作系统的核心机制。由知名作者Robert Love编著的教材,为学生提供了一套系统而全面的...

    Linux内核完全注释:基于0.11内核(V5.0)_0.11内核_linux_linux内核完全注释_Linux内核注释_

    《Linux内核完全注释:基于0.11内核(V5.0)》是一部深入解析Linux内核的重要参考资料,它详细解读了Linux操作系统的核心机制,对于理解操作系统的工作原理以及进行系统级编程具有极大的帮助。这部书籍以0.11内核为...

    编译Linux内核及调试内核模块

    3. 编译内核:文章中讲述了如何编译内核,包括make menuconfig、make、make modules、make modules_install、make install等命令的使用。 知识点:Linux内核的编译过程,包括make menuconfig、make、make modules、...

    源码基于<<LINUX内核完全剖析:基于0.12内核>>

    通过研究这个版本的源码,我们可以了解到以下几个关键知识点: 1. **内核初始化**:Linux启动时,会执行bootloader传递的地址上的代码,即`start_kernel()`函数。这个过程包括设置内存管理、初始化中断处理、设备...

    php内核开发大全

    《PHP内核开发大全》是一份深度探讨PHP扩展内核开发的资料集合,涵盖了PHP的基础、 Zend引擎的工作原理以及如何构建和优化PHP扩展等核心内容。对于想深入了解PHP内部机制和提升开发技能的程序员来说,这是一份极其...

    linux 内核模块编程指导

    Linux 内核模块编程是 Linux 操作系统内核开发的重要组成部分,本指南提供了详细的 Linux 内核开发指导,对于 Linux 内核开发者和入门者都是非常有价值的参考资料。 Linux 内核模块编程的重要性 Linux 内核模块...

Global site tag (gtag.js) - Google Analytics