이 글에서는 "PHP의 기본 커널 소스 코드의 변수 분석 (1)"을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
추천 관련 기사: "PHP의 기본 커널 소스 코드에 있는 변수 분석(2) zend_string" "PHP의 기본 커널 소스 코드에 있는 변수 분석(3)"
당분간 가장 중요한 것은 PHP의 기본 커널 연구를 위한 요소는 다음과 같습니다. 가변 배열 메모리 관리 SAPI 객체 가상 머신
PHP 변수에는 20가지 유형이 포함되어 있으므로 변수로 시작하면 다른 요소를 더 쉽게 이해할 수 있습니다
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 소스코드 패키지를 다운로드해야 합니다
저는 PHP 소스코드 패키지를 Docker 환경에 다운로드하고 후속 코드 추적을 위해 gcc gcc-c++ 및 기타 환경을 설치했습니다. 디버깅.
[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: 공식 확장 디렉토리. 어레이 시리즈, pdo 시리즈, spl 시리즈 및 기타 기능의 구현을 포함합니다.
main: PHP의 기본 기능을 구현합니다. 실제로 주요 PHP 매크로와 정의가 포함되어 있습니다.
배: PHP 확장 및 애플리케이션 저장소.
sapi: 다양한 서버 추상화 계층을 위한 코드. 예를 들어 Apache의 mod_php, cgi, fastcgi, fpm 및 기타 인터페이스입니다.
tests: PHP 테스트 스크립트 모음입니다.
scripts: Linux의 스크립트 디렉터리입니다.
win32: Windows 플랫폼과 관련된 일부 구현입니다.
PHP 변수는 Zend 디렉터리의 zend_types.h 파일에 정의되어 있습니다.
우리는 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崔雪峰同意,发布在php中文网,原文地址:https://zhuanlan.zhihu.com/p/352507796
위 내용은 PHP의 기본 커널 소스 코드 변수 분석 (1)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!