作为一个已经工作很久的PHP程序员,对于PHP各种框架以及实现原理已经摸的很熟悉了,我之前是做java开发的,一直保留了java的开发思想,并且工作中也还在使用javaweb写项目,也使用比较成熟的IOC,AOP思想写了PHP框架,但是总感觉还是不够太了解PHP,于是有去了解了CGI,FastCGI,PHP-FPM,PHP-CGI,了解了他们的工作原理感觉还是不够,又去熟悉PHP与apache,nginx如何工作的其实就靠了个sapi进行来回工作,即使这样感觉还是不太了解PHP,当时做java的时候我经常去研究jvm里面是怎么工作的,所以PHP我感觉我也要去读下源码,毕竟PHP的源码是C写的,还是比较容易接受,于是就下载了PHP的源码开始阅读。
Day .No1
读取源码需要了解PHP的源码结构,PHP的源码结构比较清晰:
|_ ext php一些扩展存放目录
|_main
PHP的一些内建函数
|_pear
|_sapi
spai
提供了一个和外部通信的接口与apache,nginx进行协同工作
|_tests php的一些demo
|_TSRM
|_Zend
zend虚拟的实现
先从zend文件夹开始阅读
1.php的基本类型在C里面是如何实现的?
找到zend文件夹下面有一个头文件zend_types.h
typedef struct_zval_struct zval;
typedef struct_zend_class_entry zend_class_entry;
typedef struct_zend_refcounted zend_refcounted;
typedef struct_zend_string zend_string;
typedef struct_zend_array zend_array;
typedef struct_zend_object zend_object;
上面这些就是我们平常使用到的,对象,数组,变量,还有gc的结构体定义,看了之后发现PHP里面的任何类型都是C里面的一个结构体(struct)
typedef union _zend_value {
zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv;
void *ptr;
zend_class_entry *ce;
zend_function *func;
struct {
uint32_t w1;
uint32_t w2;
} ww;
} zend_value;
zend内部针对php的操作类型定义了一个union类型
我对C语言只是在学校期间学过简单语法,于是在看代码过程又学习这些语法什么意思。
typedef 意思是定义一个类型的别名
例子:
#include
void main()
{
typedef int Integer;
Integer x=1;
Integer y=2;
printf("sum= %d",x+y);
}
typedef 我理解起来就是为了方便我们写代码的习惯,我熟悉java习惯了Integer 所以可以定义别名,提高写代码的效率。
struct 是C语言里面的结构体
#include
typedef struct person{
char name[20];
int age;
}p;
void main()
{
p per;
per.name[4] = "gxx";
per.age = 12;
printf("姓名:%s,年龄:%d",per.name,per.age);
}
上面就是C语言里面的结构体定义以及对成员赋值,有点像我们平常使用的对象定义一些属性,并进行赋值。
ext文件夹下面存放的是php的扩展,里面有一个标准扩展 standard 文件夹,下面找到array.c文件是具体array里面方法操作的实现,找到php_array.h文件
PHP_FUNCTION(ksort);
PHP_FUNCTION(krsort);
PHP_FUNCTION(natsort);
PHP_FUNCTION(natcasesort);
PHP_FUNCTION(asort);
PHP_FUNCTION(arsort);
PHP_FUNCTION(sort);
PHP_FUNCTION(rsort);
PHP_FUNCTION(usort);
PHP_FUNCTION(uasort);
PHP_FUNCTION(uksort);列举一部分,就是定义的PHP里面的方法。
staticvoidphp_splice(HashTable*in_hash, zend_long offset, zend_long length, HashTable*replace, HashTable*removed)/* {{{ */
{
HashTable out_hash;
}
其实c语言针对php数组的操作是使用hashtable实现的。
PHP_FUNCTION(krsort)
{
zval*array;
zend_long sort_type= PHP_SORT_REGULAR;
compare_func_t cmp;
ZEND_PARSE_PARAMETERS_START(1,2)
Z_PARAM_ARRAY_EX(array,0,1)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(sort_type)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
cmp=php_get_key_compare_func(sort_type,1);
if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0)== FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}
在zend文件夹下面的zend_hash.h文件里面 就能找到
#definezend_hash_sort(ht, compare_func, renumber)宏定义
所以数组的操作都是hashtable实现的。
阅读的过程发现了一个do {...}while(0)的用法挺好奇的就查了下什么含义。
例子:
#define DOSOMETHING()\ foo1();\ foo2();
调用
if(a>0) DOSOMETHING()
宏的预处理会直接被展开
if(a>0) foo1(); foo2();
所以不是我们预期想要的结果。
我们这样定义之后再执行结果
#define DOSOMETHING() \ do{ \ foo1();\ foo2();\ }while(0)\
执行:
if(a>0)
{
foo1();
foo2();
};
这才是我们想要的结果。