PHP源码阅读 Day.1,源码目录结构分析

素颜马尾好姑娘i 2022-06-17 03:52 371阅读 0赞

作为一个已经工作很久的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

  1. typedef struct_zval_struct zval;
  2. typedef struct_zend_class_entry zend_class_entry;
  3. typedef struct_zend_refcounted zend_refcounted;
  4. typedef struct_zend_string zend_string;
  5. typedef struct_zend_array zend_array;
  6. typedef struct_zend_object zend_object;

上面这些就是我们平常使用到的,对象,数组,变量,还有gc的结构体定义,看了之后发现PHP里面的任何类型都是C里面的一个结构体(struct)

  1. typedef union _zend_value {
  2. zend_long lval; /* long value */
  3. double dval; /* double value */
  4. zend_refcounted *counted;
  5. zend_string *str;
  6. zend_array *arr;
  7. zend_object *obj;
  8. zend_resource *res;
  9. zend_reference *ref;
  10. zend_ast_ref *ast;
  11. zval *zv;
  12. void *ptr;
  13. zend_class_entry *ce;
  14. zend_function *func;
  15. struct {
  16. uint32_t w1;
  17. uint32_t w2;
  18. } ww;
  19. } zend_value;

zend内部针对php的操作类型定义了一个union类型

我对C语言只是在学校期间学过简单语法,于是在看代码过程又学习这些语法什么意思。

typedef 意思是定义一个类型的别名

例子:

  1. #include <stdio.h>
  2. void main()
  3. {
  4. typedef int Integer;
  5. Integer x=1;
  6. Integer y=2;
  7. printf("sum= %d",x+y);
  8. }

typedef 我理解起来就是为了方便我们写代码的习惯,我熟悉java习惯了Integer 所以可以定义别名,提高写代码的效率。

struct 是C语言里面的结构体

  1. #include <stdio.h>
  2. typedef struct person{
  3. char name[20];
  4. int age;
  5. }p;
  6. void main()
  7. {
  8. p per;
  9. per.name[4] = "gxx";
  10. per.age = 12;
  11. printf("姓名:%s,年龄:%d",per.name,per.age);
  12. }

上面就是C语言里面的结构体定义以及对成员赋值,有点像我们平常使用的对象定义一些属性,并进行赋值。

ext文件夹下面存放的是php的扩展,里面有一个标准扩展 standard 文件夹,下面找到array.c文件是具体array里面方法操作的实现,找到php_array.h文件

  1. PHP_FUNCTION(ksort);
  2. PHP_FUNCTION(krsort);
  3. PHP_FUNCTION(natsort);
  4. PHP_FUNCTION(natcasesort);
  5. PHP_FUNCTION(asort);
  6. PHP_FUNCTION(arsort);
  7. PHP_FUNCTION(sort);
  8. PHP_FUNCTION(rsort);
  9. PHP_FUNCTION(usort);
  10. PHP_FUNCTION(uasort);
  11. PHP_FUNCTION(uksort);列举一部分,就是定义的PHP里面的方法。
  12. staticvoidphp_splice(HashTable*in_hash, zend_long offset, zend_long length, HashTable*replace, HashTable*removed)/* {
  13. {
  14. { */
  15. {
  16. HashTable out_hash;
  17. }

其实c语言针对php数组的操作是使用hashtable实现的。

  1. PHP_FUNCTION(krsort)
  2. {
  3. zval*array;
  4. zend_long sort_type= PHP_SORT_REGULAR;
  5. compare_func_t cmp;
  6. ZEND_PARSE_PARAMETERS_START(1,2)
  7. Z_PARAM_ARRAY_EX(array,0,1)
  8. Z_PARAM_OPTIONAL
  9. Z_PARAM_LONG(sort_type)
  10. ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
  11. cmp=php_get_key_compare_func(sort_type,1);
  12. if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0)== FAILURE) {
  13. RETURN_FALSE;
  14. }
  15. RETURN_TRUE;
  16. }

在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)\

执行:

  1. if(a>0)
  2. {
  3. foo1();
  4. foo2();
  5. };

这才是我们想要的结果。

发表评论

表情:
评论列表 (有 0 条评论,371人围观)

还没有评论,来说两句吧...

相关阅读