您好,登錄后才能下訂單哦!
小編給大家分享一下PHP底層內(nèi)核源碼之變量的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
PHP變量的四個(gè)基本特征:
1.變量命名
變量命名上,PHP繼承了Perl的語法風(fēng)格,變量以美元符號(hào)開始,后面跟變量名。 一個(gè)有效的變量名由字母或者下劃線開頭,后面跟上任意數(shù)量的字母,數(shù)字,或者下劃線。 按照正常的正則表達(dá)式,它將被表述為:'^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$’
注意: $this 是一個(gè)特殊的變量,它不能被賦值
變量默認(rèn)總是傳值賦值。那也就是說,當(dāng)將一個(gè)表達(dá)式的值賦予一個(gè)變量時(shí),整個(gè)原始表達(dá)式的值被賦值到目標(biāo)變量。這意味著,例如,當(dāng)一個(gè)變量的值賦予另外一個(gè)變量時(shí),改變其中一個(gè)變量的值,將不會(huì)影響到另外一個(gè)變量。有關(guān)這種類型的賦值操作,以后的文章也會(huì)深度講解 主要涉及到指針和寫時(shí)拷貝
PHP 也提供了另外一種方式給變量賦值:引用賦值。這意味著新的變量簡單的引用(換言之,“成為其別名” 或者 “指向”)了原始變量。改動(dòng)新的變量將影響到原始變量,反之亦然。使用引用賦值,簡單地將一個(gè) & 符號(hào)加到將要賦值的變量前(源變量) (關(guān)于變量賦值以后也會(huì)深度去探討)
PHP還支持復(fù)合變量 也叫可變變量 。也就是類似$$a的變量,它會(huì)進(jìn)行兩次的解釋。這給PHP帶來了非常靈活的動(dòng)態(tài)特性。一個(gè)變量的變量名可以動(dòng)態(tài)的設(shè)置和使用。一個(gè)普通的變量通過聲明來設(shè)置
數(shù)組使用可變變量
為了使用數(shù)組的可變變量名,你需要解決一個(gè)歧義問題。就是,如果你寫$$a[1],解析器需要明白究竟你的意思是要把$a[1]當(dāng)成一個(gè)變量,還是要把$$a當(dāng)成變量、[1]指的是這個(gè)變量的索引。解決這個(gè)歧義問題的語法是:第一種情況使用${$a[1]},第二種情況使用${$a}[1]
類屬性也可以通過可變屬性名來訪問。可變屬性名從產(chǎn)生調(diào)用所在的變量的訪問范圍內(nèi)獲取。例如,如果你的表達(dá)式是這樣的:$foo->$bar,那么運(yùn)行時(shí)將會(huì)在本地變量范圍內(nèi)尋找變量$bar,它的值將會(huì)做為$foo對(duì)象的一個(gè)屬性名。如果$bar是個(gè)數(shù)組也可以使用。
可變變量名不能用于PHP函數(shù)和類里的超級(jí)全局?jǐn)?shù)組變量上。變量$this也是一個(gè)不能動(dòng)態(tài)取名的特殊變量。
2.變量的類型
在很多靜態(tài)語言中,變量在定義時(shí)就指定了,在程序運(yùn)行過程中都不允許進(jìn)行變更,PHP就是這樣,屬于弱類型語言,可以隨便賦予它任何類型的值。PHP本身的變量低層存儲(chǔ)結(jié)構(gòu)是怎么樣的?弱類型系統(tǒng)的實(shí)現(xiàn)的方式? 以及這些類型之間的是怎么相互轉(zhuǎn)換的? 這將是本文的主要剖析內(nèi)容。
要想深入了解PHP底層源碼 必須要下載PHP的源碼包
我在Docker環(huán)境下 下載了PHP 的源碼包 同時(shí)安裝了 gcc gcc-c++ 等環(huán)境 為了后續(xù)的 代碼跟蹤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源碼的目錄結(jié)構(gòu)
Zend :Zend 引擎的實(shí)現(xiàn)目錄。包括詞法語法解析,OPCODE,提供語言運(yùn)行環(huán)境。
TSRM :線程安全資源管理器。
build:放置一些和源碼編譯相關(guān)的一些文件。
ext :官方擴(kuò)展目錄。包括array系列,pdo系列,spl系列等函數(shù)的實(shí)現(xiàn)。
main :實(shí)現(xiàn)PHP的基本設(shè)施。其實(shí)包含主要的 PHP 宏和定義。
pear :PHP 擴(kuò)展與應(yīng)用倉庫。
sapi :各種服務(wù)器抽象層的代碼。例如apache的mod_php,cgi,fastcgi以及fpm等等接口。
tests:PHP的測試腳本集合。
scripts:Linux 下的腳本目錄。
win32:Windows平臺(tái)相關(guān)的一些實(shí)現(xiàn)。
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
對(duì)于沒有c語言基礎(chǔ)的同學(xué) 看到這么多 .c .lo .o.h是發(fā)懵的 不像PHP 只有一個(gè) .php格式
我先介紹下 c語言中的文件類型 和后綴
c文件:主要每個(gè)模塊的原代碼都在c文件中。
h文件:每個(gè)c文件都跟著一個(gè)h文件,h文件的作用是放著c文件中函數(shù)的聲明,結(jié)構(gòu)體的定義,宏的定義等。
o文件:目標(biāo)文件。每個(gè)文件經(jīng)過編譯都會(huì)形成一個(gè)目標(biāo)文件(二進(jìn)制文件),多個(gè)目標(biāo)文件鏈接后才能形成可執(zhí)行文件。
o文件如何形成: gcc -c a.c (gcc 以后會(huì)用到 再說)
.so文件
.so文件就不一樣了,它不是簡單的.o文件打了一個(gè)包,它是一個(gè)ELF格式的文件,也就是linux的可執(zhí)行文件。
.so文件可以用于多個(gè)進(jìn)程的共享使用(位置無關(guān)的才行),所以又叫共享庫文件。程序在使用它的時(shí)候,會(huì)在運(yùn)行時(shí)把它映射到自己進(jìn)程空間的某一處,其不在使用它的程序中。
.lo文件 libtool生成的文件,被libtool用來生成共享庫的. libtool隱藏了PIC的flag的復(fù)雜性,而采用了分離的庫對(duì)象文件,以“.lo”代替“.o”結(jié)尾。在不需要共享庫的系統(tǒng)上,這些庫文件等同于標(biāo)準(zhǔn)的目標(biāo)文件
所有以 我們只需要看 .h 和.c就行了 其他的 文件我們想看也看不懂
其中變量的結(jié)構(gòu)體定義和宏定義 在 zend_types.h 中
至于什么是結(jié)構(gòu)體 什么是宏 一會(huì)再講
[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);
這個(gè)#開始的內(nèi)容并不是注釋 只需要大概了解下 以下內(nèi)容
#空指令,無任何效果 #include開頭 -------包含一個(gè)源代碼文件 #define開頭 -------定義宏 #undef開頭 -------取消已定義的宏 #if開頭 -------如果給定條件為真,則編譯下面代碼 #ifdef開頭 -------如果宏已經(jīng)定義,則編譯下面代碼 #ifnde開頭 -------f如果宏沒有定義,則編譯下面代碼 #elif開頭 -------如果前面的#if給定條件不為真,當(dāng)前條件為真,則編譯下面代碼 #endif開頭 -------結(jié)束一個(gè)#if……#else條件編譯塊 #error開頭 -------停止編譯并顯示錯(cuò)誤信息
其實(shí)就是頭文件 無實(shí)際寓意 比如#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語言結(jié)構(gòu)體(Struct)從本質(zhì)上講是一種自定義的數(shù)據(jù)類型,只不過這種數(shù)據(jù)類型比較復(fù)雜,是由 int、char、float 等基本類型組成的。你可以認(rèn)為結(jié)構(gòu)體是一種聚合類型。在實(shí)際開發(fā)中,我們可以將一組類型不同的、但是用來描述同一件事物的變量放到結(jié)構(gòu)體中。例如,在校學(xué)生有姓名、年齡、身高、成績等屬性,學(xué)了結(jié)構(gòu)體后,我們就不需要再定義多個(gè)變量了,將它們都放到結(jié)構(gòu)體中即可。 有點(diǎn)類似于 PHP里的對(duì)象?
結(jié)構(gòu)體里面用;進(jìn)行 分割 每個(gè)子變量
可以看出來 _zval_struct 結(jié)構(gòu)體 包括三個(gè)變量部分 (以單下劃線(_)表明是標(biāo)準(zhǔn)庫的變量
雙下劃線(__) 開頭表明是編譯器的變量)
分別為 value u1 u2
(你要這樣 理解 197行中 zend_value value; 這行代碼中 zend_value是變量類型 value 是名字 )
結(jié)構(gòu)體里第一個(gè)值類型名為 zend_value 這應(yīng)該不是一個(gè)變量 我們搜一下
/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;
聯(lián)合體 / union
union使用方法和struct非常相似,唯一的不同是struct變量所占內(nèi)存長度是各成員的內(nèi)存之和,而union內(nèi)存長度則是占內(nèi)存最大的成員的長度,也就是說union的幾個(gè)成員變量是共用一塊內(nèi)存的。
簡單點(diǎn)來說就是
假如
struct a里面 包含 變量a1 內(nèi)存占用為1 a2 內(nèi)存占用為2 那么 struct a 總占用內(nèi)存為1+2=3
union b里面 包含 變量b1 內(nèi)存占用為1 b2 內(nèi)存占用為2 那么 union b 總占用內(nèi)存為2
繼續(xù)看 zend_value
zend_long lval; //整型 double dval; //浮點(diǎn)型 zend_refcounted *counted; //獲取不同類型結(jié)構(gòu)的gc頭部的指針 zend_string *str; //string字符串 的指針 zend_array *arr; //數(shù)組指針 zend_object *obj; //object 對(duì)象指針 zend_resource *res; ///資源類型指針 zend_reference *ref; //引用類型指針 比如你通過&$c 定義的 zend_ast_ref *ast; // ast 指針 線程安全 相關(guān)的 內(nèi)核使用的 zval *zv; // 指向另外一個(gè)zval的指針 內(nèi)核使用的 void *ptr; //指針 ,通用類型 內(nèi)核使用的 zend_class_entry *ce; //類 ,內(nèi)核使用的 zend_function *func; // 函數(shù) ,內(nèi)核使用的 struct { uint32_t w1;//自己定義的。 無符號(hào)的32位整數(shù) uint32_t w2;//同上 } ww;
lval 和 dval 分別為 整型和 浮點(diǎn)型 剩下的 為* 開頭的 指針
什么是指針?
指針是一個(gè)變量,其值為另一個(gè)變量的地址,即,內(nèi)存位置的直接地址。就像其他變量或常量一樣,您必須在使用指針存儲(chǔ)其他變量地址之前,對(duì)其進(jìn)行聲明。指針變量聲明的一般形式為:
type *var-name;
在這里,type 是指針的基類型,它必須是一個(gè)有效的 C 數(shù)據(jù)類型,var-name 是指針變量的名稱。用來聲明指針的星號(hào) * 與乘法中使用的星號(hào)是相同的。但是,在這個(gè)語句中,星號(hào)是用來指定一個(gè)變量是指針。以下是有效的指針聲明:
int *ip; /* 一個(gè)整型的指針 double *dp; /* 一個(gè) double 型的指針 float *fp; /* 一個(gè)浮點(diǎn)型的指針 char *ch; /* 一個(gè)字符型的指針
所有實(shí)際數(shù)據(jù)類型,不管是整型、浮點(diǎn)型、字符型,還是其他的數(shù)據(jù)類型,對(duì)應(yīng)指針的值的類型都是一樣的,都是一個(gè)代表內(nèi)存地址的長的十六進(jìn)制數(shù)。
不同數(shù)據(jù)類型的指針之間唯一的不同是,指針?biāo)赶虻淖兞炕虺A康臄?shù)據(jù)類型不同。指針占用8個(gè)字節(jié)
所以value 聯(lián)合體需要的內(nèi)存是 8 個(gè)字節(jié)
繼續(xù)看u1
union { struct { //這是個(gè)宏 c語言里面 這種全部都是大寫的 變量大部分是宏 ZEND_ENDIAN_LOHI_3( ///變量的類型 zend_uchar type, //類型掩碼,每個(gè)類型會(huì)有不同的屬性 內(nèi)存管理會(huì)用到 zend_uchar type_flags, //這個(gè)不知道是干嘛的 估計(jì)是預(yù)留以后拓展? union { uint16_t extra; /* not further specified */ } u) } v; //一個(gè)無符號(hào)的整型 記錄 變量類型的 uint32_t type_info; } u1;
其實(shí)v 里面就是一個(gè)宏 (你可以理解為PHP里面的構(gòu)造方法 )是為了兼容大小字節(jié)序,小字節(jié)序就是下面的順序 大字節(jié)序是下面的4個(gè)順序翻轉(zhuǎn)
type_info是用來記錄變量的類型 占用4個(gè)字節(jié) 每個(gè)字節(jié)對(duì)于v中一個(gè)成員
所以 u1占用 4個(gè)字節(jié) 加上 value 8個(gè)字節(jié) 4+8=12個(gè)字節(jié)
value 本來應(yīng)該占 8 個(gè)字節(jié),但是由于內(nèi)存對(duì)齊,哪怕只增加一個(gè)字節(jié),實(shí)際上也是占用 16 個(gè)字節(jié)(使用一個(gè)字節(jié)就意味著需要額外的 8 個(gè)字節(jié))。但是顯然我們并不需要 8 個(gè)字節(jié)來存儲(chǔ)一個(gè) type 字段,所以我們在 u1 的后面增加了了一個(gè)名為 u2 的聯(lián)合體。默認(rèn)情況下是用不到的,需要使用的時(shí)候可以用來存儲(chǔ) 4 個(gè)字節(jié)的數(shù)據(jù)。這個(gè)聯(lián)合體可以滿足不同場景下的需求。
什么是內(nèi)存對(duì)齊?
將每一個(gè)數(shù)據(jù)的起始位置,在內(nèi)存的對(duì)其位置處。
為什么要內(nèi)存對(duì)齊?
無論如何,為了提高程序的性能,數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。
原因在于,為了訪問未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;然而,對(duì)齊的內(nèi)存訪問僅需要一次訪問。
這個(gè)u2 是擴(kuò)展用的 一般不會(huì)用到
比如 next 在散列表里解決哈希沖突會(huì)用到 (現(xiàn)在給你說hash沖突你會(huì)懵)
再比如 fe_pos 會(huì)在 foreach遍歷時(shí)候用到
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個(gè)字節(jié) 非常小了!
以上是“PHP底層內(nèi)核源碼之變量的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。