小编给大家分享一下PHP底层内核源码之变量的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
PHP变量的四个基本特征:
1.变量命名
变量命名上,PHP继承了Perl的语法风格,变量以美元符号开始,后面跟变量名。 一个有效的变量名由字母或者下划线开头,后面跟上任意数量的字母,数字,或者下划线。 按照正常的正则表达式,它将被表述为:'^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$’
注意: $this 是一个特殊的变量,它不能被赋值
变量默认总是传值赋值。那也就是说,当将一个表达式的值赋予一个变量时,整个原始表达式的值被赋值到目标变量。这意味着,例如,当一个变量的值赋予另外一个变量时,改变其中一个变量的值,将不会影响到另外一个变量。有关这种类型的赋值操作,以后的文章也会深度讲解 主要涉及到指针和写时拷贝
PHP 也提供了另外一种方式给变量赋值:引用赋值。这意味着新的变量简单的引用(换言之,“成为其别名” 或者 “指向”)了原始变量。改动新的变量将影响到原始变量,反之亦然。使用引用赋值,简单地将一个 & 符号加到将要赋值的变量前(源变量) (关于变量赋值以后也会深度去探讨)
PHP还支持复合变量 也叫可变变量 。也就是类似$$a的变量,它会进行两次的解释。这给PHP带来了非常灵活的动态特性。一个变量的变量名可以动态的设置和使用。一个普通的变量通过声明来设置
数组使用可变变量
为了使用数组的可变变量名,你需要解决一个歧义问题。就是,如果你写$$a[1],解析器需要明白究竟你的意思是要把$a[1]当成一个变量,还是要把$$a当成变量、[1]指的是这个变量的索引。解决这个歧义问题的语法是:第一种情况使用${$a[1]},第二种情况使用${$a}[1]
类属性也可以通过可变属性名来访问。可变属性名从产生调用所在的变量的访问范围内获取。例如,如果你的表达式是这样的:$foo->$bar,那么运行时将会在本地变量范围内寻找变量$bar,它的值将会做为$foo对象的一个属性名。如果$bar是个数组也可以使用。
可变变量名不能用于PHP函数和类里的超级全局数组变量上。变量$this也是一个不能动态取名的特殊变量。
2.变量的类型
在很多静态语言中,变量在定义时就指定了,在程序运行过程中都不允许进行变更,PHP就是这样,属于弱类型语言,可以随便赋予它任何类型的值。PHP本身的变量低层存储结构是怎么样的?弱类型系统的实现的方式? 以及这些类型之间的是怎么相互转换的? 这将是本文的主要剖析内容。
要想深入了解PHP底层源码 必须要下载PHP的源码包
我在Docker环境下 下载了PHP 的源码包 同时安装了 gcc gcc-c++ 等环境 为了后续的 代码跟踪debug。
[root@2890cf458ee2 cui-php]# ls
php-7.4.15 php-7.4.15.tar.gz
[root@2890cf458ee2 cui-php]#
[root@2890cf458ee2 cui-php]# cd php-7.4.15
[root@2890cf458ee2 php-7.4.15]# ls
CODING_STANDARDS.md Makefile.objects UPGRADING.INTERNALS buildconf configure.ac main tests
CONTRIBUTING.md NEWS Zend buildconf.bat docs modules tmp-php.ini
EXTENSIONS README.REDIST.BINS appveyor config.log ext pear travis
LICENSE README.md azure config.nice include run-tests.php win32
Makefile TSRM azure-pipelines.yml config.status libs sapi
Makefile.fragments UPGRADING build configure libtool scripts
这里有必要讲一下 PHP源码的目录结构
Zend :Zend 引擎的实现目录。包括词法语法解析,OPCODE,提供语言运行环境。
TSRM :线程安全资源管理器。
build:放置一些和源码编译相关的一些文件。
ext :官方扩展目录。包括array系列,pdo系列,spl系列等函数的实现。
main :实现PHP的基本设施。其实包含主要的 PHP 宏和定义。
pear :PHP 扩展与应用仓库。
sapi :各种服务器抽象层的代码。例如apache的mod_php,cgi,fastcgi以及fpm等等接口。
tests:PHP的测试脚本集合。
scripts:Linux 下的脚本目录。
win32:Windows平台相关的一些实现。
PHP的 变量定义在Zend目录下的 zend_types.h 文件
我们cd 到Zend目录下
[root@2890cf458ee2 php-7.4.15]# cd Zend/
[root@2890cf458ee2 Zend]# ll
total 22404
-rwxrwxrwx 1 root root 2803 Feb 2 14:20 LICENSE
-rwxrwxrwx 1 root root 2008 Feb 2 14:20 Makefile.frag
-rwxrwxrwx 1 root root 4607 Feb 2 14:20 README.md
-rwxrwxrwx 1 root root 14168 Feb 2 14:20 Zend.m4
-rwxrwxrwx 1 root root 7634 Feb 2 14:20 bench.php
-rwxrwxrwx 1 root root 7226 Feb 2 14:20 micro_bench.php
drwxrwxrwx 29 root root 73728 Feb 2 14:20 tests
-rwxrwxrwx 1 root root 50788 Feb 2 14:20 zend.c
-rwxrwxrwx 1 root root 13913 Feb 2 14:20 zend.h
-rwxrwxrwx 1 root root 308 Feb 22 08:45 zend.lo
-rwxrwxrwx 1 root root 255768 Feb 22 08:45 zend.o
-rwxrwxrwx 1 root root 132287 Feb 2 14:20 zend_API.c
-rwxrwxrwx 1 root root 71109 Feb 2 14:20 zend_API.h
-rwxrwxrwx 1 root root 320 Feb 22 08:45 zend_API.lo
-rwxrwxrwx 1 root root 821976 Feb 22 08:45 zend_API.o
-rwxrwxrwx 1 root root 91551 Feb 2 14:20 zend_alloc.c
-rwxrwxrwx 1 root root 19213 Feb 2 14:20 zend_alloc.h
-rwxrwxrwx 1 root root 326 Feb 22 08:45 zend_alloc.lo
-rwxrwxrwx 1 root root 523816 Feb 22 08:45 zend_alloc.o
-rwxrwxrwx 1 root root 2629 Feb 2 14:20 zend_alloc_sizes.h
-rwxrwxrwx 1 root root 6071 Feb 2 14:20 zend_arena.h
-rwxrwxrwx 1 root root 60172 Feb 2 14:20 zend_ast.c
-rwxrwxrwx 1 root root 11697 Feb 2 14:20 zend_ast.h
-rwxrwxrwx 1 root root 320 Feb 22 08:46 zend_ast.lo
-rwxrwxrwx 1 root root 545136 Feb 22 08:46 zend_ast.o
-rwxrwxrwx 1 root root 6877 Feb 2 14:20 zend_bitset.h
-rwxrwxrwx 1 root root 1626 Feb 2 14:20 zend_build.h
-rwxrwxrwx 1 root root 75458 Feb 2 14:20 zend_builtin_functions.c
-rwxrwxrwx 1 root root 1505 Feb 2 14:20 zend_builtin_functions.h
-rwxrwxrwx 1 root root 362 Feb 22 08:45 zend_builtin_functions.lo
-rwxrwxrwx 1 root root 323432 Feb 22 08:45 zend_builtin_functions.o
-rwxrwxrwx 1 root root 26952 Feb 2 14:20 zend_closures.c
-rwxrwxrwx 1 root root 2209 Feb 2 14:20 zend_closures.h
-rwxrwxrwx 1 root root 335 Feb 22 08:46 zend_closures.lo
-rwxrwxrwx 1 root root 132304 Feb 22 08:46 zend_closures.o
-rwxrwxrwx 1 root root 268218 Feb 2 14:20 zend_compile.c
-rwxrwxrwx 1 root root 43638 Feb 2 14:20 zend_compile.h
-rwxrwxrwx 1 root root 332 Feb 22 08:45 zend_compile.lo
-rwxrwxrwx 1 root root 1189024 Feb 22 08:45 zend_compile.o
-rwxrwxrwx 1 root root 32 Feb 22 08:39 zend_config.h
-rwxrwxrwx 1 root root 2612 Feb 2 14:20 zend_config.w32.h
-rwxrwxrwx 1 root root 17607 Feb 2 14:20 zend_constants.c
-rwxrwxrwx 1 root root 6302 Feb 2 14:20 zend_constants.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_constants.lo
-rwxrwxrwx 1 root root 86680 Feb 22 08:45 zend_constants.o
-rwxrwxrwx 1 root root 4571 Feb 2 14:20 zend_cpuinfo.c
-rwxrwxrwx 1 root root 7225 Feb 2 14:20 zend_cpuinfo.h
-rwxrwxrwx 1 root root 332 Feb 22 08:46 zend_cpuinfo.lo
-rwxrwxrwx 1 root root 12416 Feb 22 08:46 zend_cpuinfo.o
-rwxrwxrwx 1 root root 1684 Feb 2 14:20 zend_default_classes.c
-rwxrwxrwx 1 root root 356 Feb 22 08:46 zend_default_classes.lo
-rwxrwxrwx 1 root root 34040 Feb 22 08:46 zend_default_classes.o
-rwxrwxrwx 1 root root 4083 Feb 2 14:20 zend_dtrace.c
-rwxrwxrwx 1 root root 2180 Feb 2 14:20 zend_dtrace.d
-rwxrwxrwx 1 root root 1937 Feb 2 14:20 zend_dtrace.h
-rwxrwxrwx 1 root root 329 Feb 22 08:45 zend_dtrace.lo
-rwxrwxrwx 1 root root 31808 Feb 22 08:45 zend_dtrace.o
-rwxrwxrwx 1 root root 2050 Feb 2 14:20 zend_errors.h
-rwxrwxrwx 1 root root 34809 Feb 2 14:20 zend_exceptions.c
-rwxrwxrwx 1 root root 3853 Feb 2 14:20 zend_exceptions.h
-rwxrwxrwx 1 root root 341 Feb 22 08:46 zend_exceptions.lo
-rwxrwxrwx 1 root root 331592 Feb 22 08:46 zend_exceptions.o
-rwxrwxrwx 1 root root 148148 Feb 2 14:20 zend_execute.c
-rwxrwxrwx 1 root root 16926 Feb 2 14:20 zend_execute.h
-rwxrwxrwx 1 root root 332 Feb 22 08:46 zend_execute.lo
-rwxrwxrwx 1 root root 6034440 Feb 22 08:46 zend_execute.o
-rwxrwxrwx 1 root root 47231 Feb 2 14:20 zend_execute_API.c
-rwxrwxrwx 1 root root 344 Feb 22 08:45 zend_execute_API.lo
-rwxrwxrwx 1 root root 245224 Feb 22 08:45 zend_execute_API.o
-rwxrwxrwx 1 root root 10174 Feb 2 14:20 zend_extensions.c
-rwxrwxrwx 1 root root 6070 Feb 2 14:20 zend_extensions.h
-rwxrwxrwx 1 root root 341 Feb 22 08:45 zend_extensions.lo
-rwxrwxrwx 1 root root 50720 Feb 22 08:45 zend_extensions.o
-rwxrwxrwx 1 root root 1796 Feb 2 14:20 zend_float.c
-rwxrwxrwx 1 root root 15438 Feb 2 14:20 zend_float.h
-rwxrwxrwx 1 root root 326 Feb 22 08:46 zend_float.lo
-rwxrwxrwx 1 root root 32656 Feb 22 08:46 zend_float.o
-rwxrwxrwx 1 root root 40057 Feb 2 14:20 zend_gc.c
-rwxrwxrwx 1 root root 2867 Feb 2 14:20 zend_gc.h
-rwxrwxrwx 1 root root 317 Feb 22 08:46 zend_gc.lo
-rwxrwxrwx 1 root root 142080 Feb 22 08:46 zend_gc.o
-rwxrwxrwx 1 root root 38819 Feb 2 14:20 zend_generators.c
-rwxrwxrwx 1 root root 7349 Feb 2 14:20 zend_generators.h
-rwxrwxrwx 1 root root 341 Feb 22 08:46 zend_generators.lo
-rwxrwxrwx 1 root root 213744 Feb 22 08:46 zend_generators.o
-rwxrwxrwx 1 root root 7767 Feb 2 14:20 zend_globals.h
-rwxrwxrwx 1 root root 2810 Feb 2 14:20 zend_globals_macros.h
-rwxrwxrwx 1 root root 71887 Feb 2 14:20 zend_hash.c
-rwxrwxrwx 1 root root 36430 Feb 2 14:20 zend_hash.h
-rwxrwxrwx 1 root root 323 Feb 22 08:45 zend_hash.lo
-rwxrwxrwx 1 root root 579040 Feb 22 08:45 zend_hash.o
-rwxrwxrwx 1 root root 5905 Feb 2 14:20 zend_highlight.c
-rwxrwxrwx 1 root root 2268 Feb 2 14:20 zend_highlight.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_highlight.lo
-rwxrwxrwx 1 root root 54368 Feb 22 08:45 zend_highlight.o
-rwxrwxrwx 1 root root 92179 Feb 2 14:20 zend_inheritance.c
-rwxrwxrwx 1 root root 2027 Feb 2 14:20 zend_inheritance.h
-rwxrwxrwx 1 root root 344 Feb 22 08:46 zend_inheritance.lo
-rwxrwxrwx 1 root root 444648 Feb 22 08:46 zend_inheritance.o
-rwxrwxrwx 1 root root 17816 Feb 2 14:20 zend_ini.c
-rwxrwxrwx 1 root root 9823 Feb 2 14:20 zend_ini.h
-rwxrwxrwx 1 root root 320 Feb 22 08:45 zend_ini.lo
-rwxrwxrwx 1 root root 114864 Feb 22 08:45 zend_ini.o
-rwxrwxrwx 1 root root 62412 Feb 2 14:20 zend_ini_parser.c
-rwxrwxrwx 1 root root 2400 Feb 2 14:20 zend_ini_parser.h
-rwxrwxrwx 1 root root 341 Feb 22 08:45 zend_ini_parser.lo
-rwxrwxrwx 1 root root 144960 Feb 22 08:45 zend_ini_parser.o
-rwxrwxrwx 1 root root 21408 Feb 2 14:20 zend_ini_parser.output
-rwxrwxrwx 1 root root 12077 Feb 2 14:20 zend_ini_parser.y
-rwxrwxrwx 1 root root 102668 Feb 2 14:20 zend_ini_scanner.c
-rwxrwxrwx 1 root root 1873 Feb 2 14:20 zend_ini_scanner.h
-rwxrwxrwx 1 root root 17171 Feb 2 14:20 zend_ini_scanner.l
-rwxrwxrwx 1 root root 344 Feb 22 08:45 zend_ini_scanner.lo
-rwxrwxrwx 1 root root 225064 Feb 22 08:45 zend_ini_scanner.o
-rwxrwxrwx 1 root root 187 Feb 2 14:20 zend_ini_scanner_defs.h
-rwxrwxrwx 1 root root 19678 Feb 2 14:20 zend_interfaces.c
-rwxrwxrwx 1 root root 4266 Feb 2 14:20 zend_interfaces.h
-rwxrwxrwx 1 root root 341 Feb 22 08:46 zend_interfaces.lo
-rwxrwxrwx 1 root root 95608 Feb 22 08:46 zend_interfaces.o
-rwxrwxrwx 1 root root 1537 Feb 2 14:20 zend_istdiostream.h
-rwxrwxrwx 1 root root 3205 Feb 2 14:20 zend_iterators.c
-rwxrwxrwx 1 root root 3404 Feb 2 14:20 zend_iterators.h
-rwxrwxrwx 1 root root 338 Feb 22 08:46 zend_iterators.lo
-rwxrwxrwx 1 root root 36896 Feb 22 08:46 zend_iterators.o
-rwxrwxrwx 1 root root 252766 Feb 2 14:20 zend_language_parser.c
-rwxrwxrwx 1 root root 5095 Feb 2 14:20 zend_language_parser.h
-rwxrwxrwx 1 root root 356 Feb 22 08:45 zend_language_parser.lo
-rwxrwxrwx 1 root root 345328 Feb 22 08:45 zend_language_parser.o
-rwxrwxrwx 1 root root 1356436 Feb 2 14:20 zend_language_parser.output
-rwxrwxrwx 1 root root 49261 Feb 2 14:20 zend_language_parser.y
-rwxrwxrwx 1 root root 186767 Feb 2 14:20 zend_language_scanner.c
-rwxrwxrwx 1 root root 2732 Feb 2 14:20 zend_language_scanner.h
-rwxrwxrwx 1 root root 69753 Feb 2 14:20 zend_language_scanner.l
-rwxrwxrwx 1 root root 359 Feb 22 08:45 zend_language_scanner.lo
-rwxrwxrwx 1 root root 475576 Feb 22 08:45 zend_language_scanner.o
-rwxrwxrwx 1 root root 267 Feb 2 14:20 zend_language_scanner_defs.h
-rwxrwxrwx 1 root root 9245 Feb 2 14:20 zend_list.c
-rwxrwxrwx 1 root root 3470 Feb 2 14:20 zend_list.h
-rwxrwxrwx 1 root root 323 Feb 22 08:45 zend_list.lo
-rwxrwxrwx 1 root root 63872 Feb 22 08:45 zend_list.o
-rwxrwxrwx 1 root root 6837 Feb 2 14:20 zend_llist.c
-rwxrwxrwx 1 root root 3790 Feb 2 14:20 zend_llist.h
-rwxrwxrwx 1 root root 326 Feb 22 08:45 zend_llist.lo
-rwxrwxrwx 1 root root 22848 Feb 22 08:45 zend_llist.o
-rwxrwxrwx 1 root root 4298 Feb 2 14:20 zend_long.h
-rwxrwxrwx 1 root root 3165 Feb 2 14:20 zend_map_ptr.h
-rwxrwxrwx 1 root root 4790 Feb 2 14:20 zend_modules.h
-rwxrwxrwx 1 root root 7322 Feb 2 14:20 zend_multibyte.c
-rwxrwxrwx 1 root root 4862 Feb 2 14:20 zend_multibyte.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_multibyte.lo
-rwxrwxrwx 1 root root 56144 Feb 22 08:45 zend_multibyte.o
-rwxrwxrwx 1 root root 9837 Feb 2 14:20 zend_multiply.h
-rwxrwxrwx 1 root root 57901 Feb 2 14:20 zend_object_handlers.c
-rwxrwxrwx 1 root root 13505 Feb 2 14:20 zend_object_handlers.h
-rwxrwxrwx 1 root root 356 Feb 22 08:46 zend_object_handlers.lo
-rwxrwxrwx 1 root root 310384 Feb 22 08:46 zend_object_handlers.o
-rwxrwxrwx 1 root root 9778 Feb 2 14:20 zend_objects.c
-rwxrwxrwx 1 root root 1807 Feb 2 14:20 zend_objects.h
-rwxrwxrwx 1 root root 332 Feb 22 08:46 zend_objects.lo
-rwxrwxrwx 1 root root 59976 Feb 22 08:46 zend_objects.o
-rwxrwxrwx 1 root root 6724 Feb 2 14:20 zend_objects_API.c
-rwxrwxrwx 1 root root 4683 Feb 2 14:20 zend_objects_API.h
-rwxrwxrwx 1 root root 344 Feb 22 08:46 zend_objects_API.lo
-rwxrwxrwx 1 root root 46120 Feb 22 08:46 zend_objects_API.o
-rwxrwxrwx 1 root root 34033 Feb 2 14:20 zend_opcode.c
-rwxrwxrwx 1 root root 329 Feb 22 08:45 zend_opcode.lo
-rwxrwxrwx 1 root root 120352 Feb 22 08:45 zend_opcode.o
-rwxrwxrwx 1 root root 83363 Feb 2 14:20 zend_operators.c
-rwxrwxrwx 1 root root 34148 Feb 2 14:20 zend_operators.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_operators.lo
-rwxrwxrwx 1 root root 506096 Feb 22 08:45 zend_operators.o
-rwxrwxrwx 1 root root 20146 Feb 2 14:20 zend_portability.h
-rwxrwxrwx 1 root root 3030 Feb 2 14:20 zend_ptr_stack.c
-rwxrwxrwx 1 root root 4306 Feb 2 14:20 zend_ptr_stack.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_ptr_stack.lo
-rwxrwxrwx 1 root root 13104 Feb 22 08:45 zend_ptr_stack.o
-rwxrwxrwx 1 root root 3000 Feb 2 14:20 zend_range_check.h
-rwxrwxrwx 1 root root 13032 Feb 2 14:20 zend_signal.c
-rwxrwxrwx 1 root root 4082 Feb 2 14:20 zend_signal.h
-rwxrwxrwx 1 root root 329 Feb 22 08:46 zend_signal.lo
-rwxrwxrwx 1 root root 29320 Feb 22 08:46 zend_signal.o
-rwxrwxrwx 1 root root 5672 Feb 2 14:20 zend_smart_str.c
-rwxrwxrwx 1 root root 5530 Feb 2 14:20 zend_smart_str.h
-rwxrwxrwx 1 root root 338 Feb 22 08:46 zend_smart_str.lo
-rwxrwxrwx 1 root root 18552 Feb 22 08:46 zend_smart_str.o
-rwxrwxrwx 1 root root 1279 Feb 2 14:20 zend_smart_str_public.h
-rwxrwxrwx 1 root root 4389 Feb 2 14:20 zend_smart_string.h
-rwxrwxrwx 1 root root 1392 Feb 2 14:20 zend_smart_string_public.h
-rwxrwxrwx 1 root root 10852 Feb 2 14:20 zend_sort.c
-rwxrwxrwx 1 root root 1636 Feb 2 14:20 zend_sort.h
-rwxrwxrwx 1 root root 323 Feb 22 08:45 zend_sort.lo
-rwxrwxrwx 1 root root 28488 Feb 22 08:45 zend_sort.o
-rwxrwxrwx 1 root root 3983 Feb 2 14:20 zend_stack.c
-rwxrwxrwx 1 root root 2360 Feb 2 14:20 zend_stack.h
-rwxrwxrwx 1 root root 326 Feb 22 08:45 zend_stack.lo
-rwxrwxrwx 1 root root 13312 Feb 22 08:45 zend_stack.o
-rwxrwxrwx 1 root root 7212 Feb 2 14:20 zend_stream.c
-rwxrwxrwx 1 root root 3542 Feb 2 14:20 zend_stream.h
-rwxrwxrwx 1 root root 329 Feb 22 08:46 zend_stream.lo
-rwxrwxrwx 1 root root 24776 Feb 22 08:46 zend_stream.o
-rwxrwxrwx 1 root root 12740 Feb 2 14:20 zend_string.c
-rwxrwxrwx 1 root root 17347 Feb 2 14:20 zend_string.h
-rwxrwxrwx 1 root root 329 Feb 22 08:46 zend_string.lo
-rwxrwxrwx 1 root root 77697 Feb 23 09:51 zend_string.o
-rwxrwxrwx 1 root root 92649 Feb 2 14:20 zend_strtod.c
-rwxrwxrwx 1 root root 1854 Feb 2 14:20 zend_strtod.h
-rwxrwxrwx 1 root root 329 Feb 22 08:46 zend_strtod.lo
-rwxrwxrwx 1 root root 117472 Feb 22 08:46 zend_strtod.o
-rwxrwxrwx 1 root root 3499 Feb 2 14:20 zend_strtod_int.h
-rwxrwxrwx 1 root root 8172 Feb 2 14:20 zend_ts_hash.c
-rwxrwxrwx 1 root root 5731 Feb 2 14:20 zend_ts_hash.h
-rwxrwxrwx 1 root root 332 Feb 22 08:45 zend_ts_hash.lo
-rwxrwxrwx 1 root root 42888 Feb 22 08:45 zend_ts_hash.o
-rwxrwxrwx 1 root root 3091 Feb 2 14:20 zend_type_info.h
-rwxrwxrwx 1 root root 40632 Feb 23 03:41 zend_types.h
-rwxrwxrwx 1 root root 4739 Feb 2 14:20 zend_variables.c
-rwxrwxrwx 1 root root 3273 Feb 2 14:20 zend_variables.h
-rwxrwxrwx 1 root root 338 Feb 22 08:45 zend_variables.lo
-rwxrwxrwx 1 root root 43816 Feb 22 08:45 zend_variables.o
-rwxrwxrwx 1 root root 43224 Feb 2 14:20 zend_virtual_cwd.c
-rwxrwxrwx 1 root root 12734 Feb 2 14:20 zend_virtual_cwd.h
-rwxrwxrwx 1 root root 344 Feb 22 08:46 zend_virtual_cwd.lo
-rwxrwxrwx 1 root root 80456 Feb 22 08:46 zend_virtual_cwd.o
-rwxrwxrwx 1 root root 1952 Feb 2 14:20 zend_vm.h
-rwxrwxrwx 1 root root 271416 Feb 2 14:20 zend_vm_def.h
-rwxrwxrwx 1 root root 2025584 Feb 2 14:20 zend_vm_execute.h
-rwxrwxrwx 1 root root 3616 Feb 2 14:20 zend_vm_execute.skl
-rwxrwxrwx 1 root root 146220 Feb 2 14:20 zend_vm_gen.php
-rwxrwxrwx 1 root root 87968 Feb 2 14:20 zend_vm_handlers.h
-rwxrwxrwx 1 root root 8522 Feb 2 14:20 zend_vm_opcodes.c
-rwxrwxrwx 1 root root 12080 Feb 2 14:20 zend_vm_opcodes.h
-rwxrwxrwx 1 root root 341 Feb 22 08:45 zend_vm_opcodes.lo
-rwxrwxrwx 1 root root 17408 Feb 22 08:45 zend_vm_opcodes.o
-rwxrwxrwx 1 root root 3212 Feb 2 14:20 zend_vm_trace_handlers.h
-rwxrwxrwx 1 root root 2654 Feb 2 14:20 zend_vm_trace_map.h
-rwxrwxrwx 1 root root 6578 Feb 2 14:20 zend_weakrefs.c
-rwxrwxrwx 1 root root 1445 Feb 2 14:20 zend_weakrefs.h
-rwxrwxrwx 1 root root 335 Feb 22 08:46 zend_weakrefs.lo
-rwxrwxrwx 1 root root 66704 Feb 22 08:46 zend_weakrefs.o
对于没有c语言基础的同学 看到这么多 .c .lo .o.h是发懵的 不像PHP 只有一个 .php格式
我先介绍下 c语言中的文件类型 和后缀
c文件:主要每个模块的原代码都在c文件中。
h文件:每个c文件都跟着一个h文件,h文件的作用是放着c文件中函数的声明,结构体的定义,宏的定义等。
o文件:目标文件。每个文件经过编译都会形成一个目标文件(二进制文件),多个目标文件链接后才能形成可执行文件。
o文件如何形成: gcc -c a.c (gcc 以后会用到 再说)
.so文件
.so文件就不一样了,它不是简单的.o文件打了一个包,它是一个ELF格式的文件,也就是linux的可执行文件。
.so文件可以用于多个进程的共享使用(位置无关的才行),所以又叫共享库文件。程序在使用它的时候,会在运行时把它映射到自己进程空间的某一处,其不在使用它的程序中。
.lo文件 libtool生成的文件,被libtool用来生成共享库的. libtool隐藏了PIC的flag的复杂性,而采用了分离的库对象文件,以“.lo”代替“.o”结尾。在不需要共享库的系统上,这些库文件等同于标准的目标文件
所有以 我们只需要看 .h 和.c就行了 其他的 文件我们想看也看不懂
其中变量的结构体定义和宏定义 在 zend_types.h 中
至于什么是结构体 什么是宏 一会再讲
[root@2890cf458ee2 Zend]# vim zend_types.h
其中前部分代码是这样的
1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Dmitry Stogov <dmitry@php.net> |
18 | Xinchen Hui <xinchen.h@zend.com> |
19 +----------------------------------------------------------------------+
20 */
21
22 #ifndef ZEND_TYPES_H
23 #define ZEND_TYPES_H
24
25 #include "zend_portability.h"
26 #include "zend_long.h"
27
28 #ifdef __SSE2__
29 # include <mmintrin.h>
30 # include <emmintrin.h>
31 #endif
32
33 #ifdef WORDS_BIGENDIAN
34 # define ZEND_ENDIAN_LOHI(lo, hi) hi; lo;
35 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi) hi; mi; lo;
36 # define ZEND_ENDIAN_LOHI_4(a, b, c, d) d; c; b; a;
37 # define ZEND_ENDIAN_LOHI_C(lo, hi) hi, lo
38 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi) hi, mi, lo,
39 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d) d, c, b, a
40 #else
41 # define ZEND_ENDIAN_LOHI(lo, hi) lo; hi;
42 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi) lo; mi; hi;
43 # define ZEND_ENDIAN_LOHI_4(a, b, c, d) a; b; c; d;
44 # define ZEND_ENDIAN_LOHI_C(lo, hi) lo, hi
45 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi) lo, mi, hi,
46 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d) a, b, c, d
47 #endif
48
49 typedef unsigned char zend_bool;
50 typedef unsigned char zend_uchar;
51
52 typedef enum {
53 SUCCESS = 0,
54 FAILURE = -1, /* this MUST stay a negative number, or it may affect functions! */
55 } ZEND_RESULT_CODE;
56
57 #ifdef ZEND_ENABLE_ZVAL_LONG64
58 # ifdef ZEND_WIN32
59 # define ZEND_SIZE_MAX _UI64_MAX
60 # else
61 # define ZEND_SIZE_MAX SIZE_MAX
62 # endif
63 #else
64 # if defined(ZEND_WIN32)
65 # define ZEND_SIZE_MAX _UI32_MAX
66 # else
67 # define ZEND_SIZE_MAX SIZE_MAX
68 # endif
69 #endif
70
71 typedef intptr_t zend_intptr_t;
72 typedef uintptr_t zend_uintptr_t;
73
74 #ifdef ZTS
75 #define ZEND_TLS static TSRM_TLS
76 #define ZEND_EXT_TLS TSRM_TLS
77 #else
78 #define ZEND_TLS static
79 #define ZEND_EXT_TLS
80 #endif
81
82 typedef struct _zend_object_handlers zend_object_handlers;
83 typedef struct _zend_class_entry zend_class_entry;
84 typedef union _zend_function zend_function;
85 typedef struct _zend_execute_data zend_execute_data;
86
87 typedef struct _zval_struct zval;
88
89 typedef struct _zend_refcounted zend_refcounted;
90 typedef struct _zend_string zend_string;
91 typedef struct _zend_array zend_array;
92 typedef struct _zend_object zend_object;
93 typedef struct _zend_resource zend_resource;
94 typedef struct _zend_reference zend_reference;
95 typedef struct _zend_ast_ref zend_ast_ref;
96 typedef struct _zend_ast zend_ast;
97
98 typedef int (*compare_func_t)(const void *, const void *);
99 typedef void (*swap_func_t)(void *, void *);
100 typedef void (*sort_func_t)(void *, size_t, size_t, compare_func_t, swap_func_t);
101 typedef void (*dtor_func_t)(zval *pDest);
102 typedef void (*copy_ctor_func_t)(zval *pElement);
这个#开始的内容并不是注释 只需要大概了解下 以下内容
#空指令,无任何效果
#include开头 -------包含一个源代码文件
#define开头 -------定义宏
#undef开头 -------取消已定义的宏
#if开头 -------如果给定条件为真,则编译下面代码
#ifdef开头 -------如果宏已经定义,则编译下面代码
#ifnde开头 -------f如果宏没有定义,则编译下面代码
#elif开头 -------如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif开头 -------结束一个#if……#else条件编译块
#error开头 -------停止编译并显示错误信息
其实就是头文件 无实际寓意 比如#ifdef WORDS_BIGENDIAN 这是大小端的 判断
196 struct _zval_struct {
197 zend_value value; /* value */
198 union {
199 struct {
200 ZEND_ENDIAN_LOHI_3(
201 zend_uchar type, /* active type */
202 zend_uchar type_flags,
203 union {
204 uint16_t extra; /* not further specified */
205 } u)
206 } v;
207 uint32_t type_info;
208 } u1;
209 union {
210 uint32_t next; /* hash collision chain */
211 uint32_t cache_slot; /* cache slot (for RECV_INIT) */
212 uint32_t opline_num; /* opline number (for FAST_CALL) */
213 uint32_t lineno; /* line number (for ast nodes) */
214 uint32_t num_args; /* arguments number for EX(This) */
215 uint32_t fe_pos; /* foreach position */
216 uint32_t fe_iter_idx; /* foreach iterator index */
217 uint32_t access_flags; /* class constant access flags */
218 uint32_t property_guard; /* single property guard */
219 uint32_t constant_flags; /* constant flags */
220 uint32_t extra; /* not further specified */
221 } u2;
222 };
这部分是 变量 的核心 代码
C语言结构体(Struct)从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由 int、char、float 等基本类型组成的。你可以认为结构体是一种聚合类型。在实际开发中,我们可以将一组类型不同的、但是用来描述同一件事物的变量放到结构体中。例如,在校学生有姓名、年龄、身高、成绩等属性,学了结构体后,我们就不需要再定义多个变量了,将它们都放到结构体中即可。 有点类似于 PHP里的对象?
结构体里面用;进行 分割 每个子变量
可以看出来 _zval_struct 结构体 包括三个变量部分 (以单下划线(_)表明是标准库的变量
双下划线(__) 开头表明是编译器的变量)
分别为 value u1 u2
(你要这样 理解 197行中 zend_value value; 这行代码中 zend_value是变量类型 value 是名字 )
结构体里第一个值类型名为 zend_value 这应该不是一个变量 我们搜一下
/zend_value
代码在176处定义了 zend_value
176 typedef union _zend_value {
177 zend_long lval; /* long value */
178 double dval; /* double value */
179 zend_refcounted *counted;
180 zend_string *str;
181 zend_array *arr;
182 zend_object *obj;
183 zend_resource *res;
184 zend_reference *ref;
185 zend_ast_ref *ast;
186 zval *zv;
187 void *ptr;
188 zend_class_entry *ce;
189 zend_function *func;
190 struct {
191 uint32_t w1;
192 uint32_t w2;
193 } ww;
194 } zend_value;
联合体 / union
union使用方法和struct非常相似,唯一的不同是struct变量所占内存长度是各成员的内存之和,而union内存长度则是占内存最大的成员的长度,也就是说union的几个成员变量是共用一块内存的。
简单点来说就是
假如
struct a里面 包含 变量a1 内存占用为1 a2 内存占用为2 那么 struct a 总占用内存为1+2=3
union b里面 包含 变量b1 内存占用为1 b2 内存占用为2 那么 union b 总占用内存为2
继续看 zend_value
zend_long lval; //整型
double dval; //浮点型
zend_refcounted *counted; //获取不同类型结构的gc头部的指针
zend_string *str; //string字符串 的指针
zend_array *arr; //数组指针
zend_object *obj; //object 对象指针
zend_resource *res; ///资源类型指针
zend_reference *ref; //引用类型指针 比如你通过&$c 定义的
zend_ast_ref *ast; // ast 指针 线程安全 相关的 内核使用的
zval *zv; // 指向另外一个zval的指针 内核使用的
void *ptr; //指针 ,通用类型 内核使用的
zend_class_entry *ce; //类 ,内核使用的
zend_function *func; // 函数 ,内核使用的
struct {
uint32_t w1;//自己定义的。 无符号的32位整数
uint32_t w2;//同上
} ww;
lval 和 dval 分别为 整型和 浮点型 剩下的 为* 开头的 指针
什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
在这里,type 是指针的基类型,它必须是一个有效的 C 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip; /* 一个整型的指针
double *dp; /* 一个 double 型的指针
float *fp; /* 一个浮点型的指针
char *ch; /* 一个字符型的指针
所有实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,对应指针的值的类型都是一样的,都是一个代表内存地址的长的十六进制数。
不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。指针占用8个字节
所以value 联合体需要的内存是 8 个字节
继续看u1
union {
struct {
//这是个宏 c语言里面 这种全部都是大写的 变量大部分是宏
ZEND_ENDIAN_LOHI_3(
///变量的类型
zend_uchar type,
//类型掩码,每个类型会有不同的属性 内存管理会用到
zend_uchar type_flags,
//这个不知道是干嘛的 估计是预留以后拓展?
union {
uint16_t extra; /* not further specified */
} u)
} v;
//一个无符号的整型 记录 变量类型的
uint32_t type_info;
} u1;
其实v 里面就是一个宏 (你可以理解为PHP里面的构造方法 )是为了兼容大小字节序,小字节序就是下面的顺序 大字节序是下面的4个顺序翻转
type_info是用来记录变量的类型 占用4个字节 每个字节对于v中一个成员
所以 u1占用 4个字节 加上 value 8个字节 4+8=12个字节
value 本来应该占 8 个字节,但是由于内存对齐,哪怕只增加一个字节,实际上也是占用 16 个字节(使用一个字节就意味着需要额外的 8 个字节)。但是显然我们并不需要 8 个字节来存储一个 type 字段,所以我们在 u1 的后面增加了了一个名为 u2 的联合体。默认情况下是用不到的,需要使用的时候可以用来存储 4 个字节的数据。这个联合体可以满足不同场景下的需求。
什么是内存对齐?
将每一个数据的起始位置,在内存的对其位置处。
为什么要内存对齐?
无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
这个u2 是扩展用的 一般不会用到
比如 next 在散列表里解决哈希冲突会用到 (现在给你说hash冲突你会懵)
再比如 fe_pos 会在 foreach遍历时候用到
union {
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* cache slot (for RECV_INIT) */
uint32_t opline_num; /* opline number (for FAST_CALL) */
uint32_t lineno; /* line number (for ast nodes) */
uint32_t num_args; /* arguments number for EX(This) */
uint32_t fe_pos; /* foreach position */
uint32_t fe_iter_idx; /* foreach iterator index */
uint32_t access_flags; /* class constant access flags */
uint32_t property_guard; /* single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
所以 PHP7 以上的 zval_struct 占用16个字节 非常小了!
以上是“PHP底层内核源码之变量的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。