php 常量

常量存儲位置php

1 EG(zend_constants)

 

常量的內部結構
在Zend/zend_constants.h文件的33行能夠看到以下所示的結構定義。在常量的結構中,除了與變量同樣的zval結構,它還包括屬於常量的標記,常量名以及常量所在的模塊號app

typedef struct _zend_constant {
  zval value;/* zval結構,PHP內部變量的存儲結構,在第一小節有說明 */
  int flags; /* 常量的標記如 CONST_PERSISTENT | CONST_CS |CONST_CT_SUBST */
  char *name;/* 常量名稱 */
  uint name_len;
  int module_number;/* 模塊號 */ 
} zend_constant;

flags取值:
CONST_PERSISTENT:表示這個常量須要持久化。這裏的持久化內存申請時的持久化是一個概念,非持久常量會在請求結束時釋放該常量。若是是非持久常量,會在RSHUTDOWN階段就將該常量釋放,不然只會在MSHUTDOWN階段將內存釋放,在用戶空間,也就是用戶定義的常量都是非持久化的,一般擴展和內核定義的常量會設置爲持久化,由於若是常量被釋放了,而下次請求又須要使用這個常量,該常量就必須在請求時初始化一次,而對於常量這些不變的量來講就是個沒有意義的重複計算。函數

CONST_CT_SUBST: /* Allow compile-time substitution */(在編譯時可被替換)。ui

CONST_CS: /* Case Sensitive */ 大小寫敏感lua

define函數的實現
define是PHP的內置函數,在Zend/zend_builtin_functions.c文件中定義了此函數的實現spa

/* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
   Define a new constant */
ZEND_FUNCTION(define)
{
    char *name;
    int name_len;
    zval *val;
    zval *val_free = NULL;
    zend_bool non_cs = 0;
    int case_sensitive = CONST_CS; //  是否大小寫敏感,默認爲1
    zend_constant c;

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

    if(non_cs) {
        case_sensitive = 0;
    }

    /* class constant, check if there is name and make sure class is valid & exists */
    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);
    if (val_free) {
        zval_ptr_dtor(&val_free);
    }
    c.flags = case_sensitive; /* non persistent */
    c.name = zend_strndup(name, name_len);
    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;
    }
}
/* }}} */

其實現上是一個將傳遞的參數傳遞給新建的zend_constant結構,並將這個結構體註冊到常量列表中的過程。scala

例子:標準常量TRUE的定義code

/*聲明結構體*/
zend_constant c;
/*結構體賦值*/
c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
c.module_number = 0;
c.name = zend_strndup(ZEND_STRL("TRUE"));
c.name_len = sizeof("TRUE");
c.value.value.lval = 1;
c.value.type = IS_BOOL;
/*註冊結構體*/
zend_register_constant(&c TSRMLS_CC);

 

常量的銷燬blog

非持久化常量在request請求結束時銷燬,具體銷燬操做在:php_request_shutdown()->zend_deactivate()->shutdown_executor()->clean_non_persistent_constants()。內存

1 void clean_non_persistent_constants(TSRMLS_D)
2 {
3     if (EG(full_tables_cleanup)) {
4         zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
5     } else {
6         zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
7     }
8 }
相關文章
相關標籤/搜索