您好,登錄后才能下訂單哦!
小編給大家分享一下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底層內核源碼之變量的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。