`
wudikua123
  • 浏览: 61930 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

php杂七杂八

    博客分类:
  • php
 
阅读更多
PHP的启动
PHP的启动经历了
PHP_MINIT_FUNCTION->
PHP_RINIT_FUNCTION->
PHP_RSHUTDOWN_FUNCTION->
PHP_MSHUTDOWN_FUNCTION
4个阶段。
但是 这4个阶段会由于SAPI宿主的不同在不同阶段执行。
如果把PHP比作汽车,那么SAPI就是公路。
常见的SAPI可以是
CLI/CGI
一个请求过来,会执行以上4个阶段。
多进程模型
以APACHE的PRE-FORK为代表,在此模式下,APACHE会设定一个初始进程数量,然后请求增多以后,会以2的指数次方创建进程。
多线程模型
以APACHE的worker为代表,在这种模式下,只有一个服务器进程在运行着,但会同时运行很多线程,这样可以减少一些资源开销,向Module init和Module shutdown就只需要运行一遍就行了,一些全局变量也只需要初始化一次,因为线程独具的特质,使得各个请求之间方便的共享一些数据成为可能。
PHP的类型
struct _zval_struct {
    zvalue_value value; /* 变量的值 */
    zend_uint refcount__gc; //引用计数
    zend_uchar type;    /* 变量当前的数据类型 */
    zend_uchar is_ref__gc;  //是否被引用
};
typedef struct _zval_struct zval;

其中变量的值zvalue_value又是个union,具体如下
typedef union _zvalue_value {
    long lval;  /* long value */
    double dval;    /* double value */
    struct {
        char *val;
        int len;
    } str;       //可以看到php的str与c的用\0结束不同,而是用一个int表示他的长度
    HashTable *ht;  /* hash table value PHP数组的保存方式*/
    zend_object_value obj;
} zvalue_value;

如何判断PHP值的类型(zval->type),PHP定义了一些以IS_开头的常量
IS_NULL,IS_LONG,IS_DOUBLE,IS_STRING,IS_ARRAY,IS_OBJECT,IS_RESOURCE
还定义了三个检测变量类型的宏,分别接收zval,zval*,zval**类型的变量
define Z_TYPE(zval) (zval).type
define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp)
说明:本来也可以把zval->type和IS_开头的常量比较,但是如果以后PHP改变zval的定义,就不能保证兼容性。

如何操作PHP的值(zval->value)
PHP定义了基础宏获取zval->value
//操作整数的
#define Z_LVAL(zval)            (zval).value.lval
#define Z_LVAL_P(zval_p)        Z_LVAL(*zval_p)
#define Z_LVAL_PP(zval_pp)      Z_LVAL(**zval_pp)

//操作IS_BOOL布尔型的
#define Z_BVAL(zval)            ((zend_bool)(zval).value.lval)
#define Z_BVAL_P(zval_p)        Z_BVAL(*zval_p)
#define Z_BVAL_PP(zval_pp)      Z_BVAL(**zval_pp)

//操作浮点数的
#define Z_DVAL(zval)            (zval).value.dval
#define Z_DVAL_P(zval_p)        Z_DVAL(*zval_p)
#define Z_DVAL_PP(zval_pp)      Z_DVAL(**zval_pp)

//操作字符串的值和长度的
#define Z_STRVAL(zval)          (zval).value.str.val
#define Z_STRVAL_P(zval_p)      Z_STRVAL(*zval_p)
#define Z_STRVAL_PP(zval_pp)        Z_STRVAL(**zval_pp)

#define Z_STRLEN(zval)          (zval).value.str.len
#define Z_STRLEN_P(zval_p)      Z_STRLEN(*zval_p)
#define Z_STRLEN_PP(zval_pp)        Z_STRLEN(**zval_pp)

//操作数组的
#define Z_ARRVAL(zval)          (zval).value.ht
#define Z_ARRVAL_P(zval_p)      Z_ARRVAL(*zval_p)
#define Z_ARRVAL_PP(zval_pp)        Z_ARRVAL(**zval_pp)

对象和资源类型的暂时不考虑了。

PHP值的创建
第一步,通过MAKE_STD_ZVAL(pzv)初始化一个指向zval的指针pzv
第二步,通过之前学过的操作PHP类型的各种宏对zval->type,zval->value进行赋值。
比如:
Z_TYPE_P(pzv) = IS_LONG;
Z_LVAL_P(pzv) = l;
也可以用新的宏把它简化
ZVAL_LONG(pzv, l);
注意:字符串在php中的表示是
struct {
    char *val;
    int len;
} str; 
所以赋值时候要即赋值val 还要赋值len
比如:
Z_TYPE_P(pzv) = IS_STRING;
Z_STRLEN_P(pzv) = len;
if (dup)
    {Z_STRVAL_P(pzv) =estrndup(str, len + 1);} //estrndup重新申请内存,并复制字符串
else
    {Z_STRVAL_P(pzv) = str;}
也可以用新的宏把它简化
ZVAL_STRINGL(pzv,str,len,dup);

变量的存储
struct _zend_executor_globals {
    ...
    HashTable symbol_table;
    HashTable *active_symbol_table;
    ...
};  
    创建一个zval结构,并设置其类型。
    设置值为'bar'。
    将其加入当前作用域的符号表,只有这样用户才能在PHP里使用这个变量。

具体的代码为:
{
    zval *fooval;

    MAKE_STD_ZVAL(fooval);
    ZVAL_STRING(fooval, "bar", 1);
    ZEND_SET_SYMBOL( EG(active_symbol_table) ,  "foo" , fooval);
}      

上面解释了zval->type,zval->vale相关的,下面解释zval->refcount__gc,zval->is_ref_gc
相关文章检索copy-on-write

ZEND_FUNCTION返回值
ZEND_FUNCTION的宏展开是
void name(INTERNAL_FUNCTION_PARAMETERS) 展开INTERNAL_FUNCTION_PARAMETERS
#define INTERNAL_FUNCTION_PARAMETERS
int ht,
zval *return_value, //返回值的指针,给他赋值就行了。
zval **return_value_ptr,
zval *this_ptr,
int return_value_used TSRMLS_DC
返回值例子:
ZEND_FUNCTION(sample_long)
{
    ZVAL_LONG(return_value, 42); //前面讲过的如何给zval* 赋值。
    return;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics