이 기사는 Younes Rafie가 검토 한 동료입니다. Sitepoint 콘텐츠를 최선을 다해 Sitepoint의 동료 리뷰어 덕분에!
Ruby Code가 실행 방법에 대한 최근 기사에서 영감을 얻은이 기사는 PHP 코드의 실행 프로세스를 다룹니다.
키 테이크 아웃
PHP 코드 실행에는 렉싱, 구문 분석, 컴파일 및 해석의 네 단계가 포함됩니다. 각 단계는 PHP 소스 코드를 기계 읽을 수있는 코드로 변환하는 과정에서 중요합니다.
Lexing 또는 토큰 화는 문자열 (PHP 소스 코드)을 일련의 토큰으로 전환하는 과정입니다. 각 토큰은 일치하는 값의 이름이 지정된 식별자입니다. 이 단계는 또한 Lexeme과 일치하는 토큰의 줄 번호를 저장합니다.
구문 분석 단계는 토큰 순서의 유효성을 확인하고 Abstract 구문 트리 (AST)를 생성합니다. AST는 컴파일 단계에서 사용되는 소스 코드의 트리보기입니다.
컴파일 스테이지는 AST를 통과하여 Opcodes를 방출하고 문자 그대로의 인수와 함께 함수 호출을 해결하는 것과 같은 최적화를 수행합니다. 이 단계의 출력은 Opcache, VLD 및 PHPDBG를 사용하여 검사 할 수 있습니다.
해석 단계는 ZEND Engine (ZE) VM에서 Opcodes가 실행되는 최종 단계입니다. 이 단계의 출력은 Echo, Print, Var_dump 등과 같은 명령을 통해 PHP 스크립트를 출력하는 것입니다.
소개
PHP 코드를 실행할 때 후드 아래에서 많은 일이 진행되고 있습니다. 광범위하게 말하면, PHP 통역사는 코드를 실행할 때 4 단계를 거칩니다.
Lexing
구문 분석
컴파일
해석
이 기사는이 단계를 훑어보고 각 단계의 출력을보고 실제로 무슨 일이 일어나고 있는지 알 수있는 방법을 보여줍니다. 사용 된 확장 장치 중 일부는 이미 PHP 설치의 일부 여야하지만 (Tokenizer 및 Opcache)는 수동으로 설치되어 활성화되어야합니다 (예 : PHP-AST 및 VLD).
1 단계 - 렉싱
Lexing (또는 토큰 화)은 문자열 (PHP 소스 코드,이 경우)을 일련의 토큰으로 바꾸는 과정입니다. 토큰은 단순히 일치하는 값의 이름을 딴 식별자입니다. PHP는 re2c를 사용하여 zend_language_scanner.l 정의 파일에서 Lexer를 생성합니다.
우리는 Tokenizer 확장을 통해 Lexing 단계의 출력을 볼 수 있습니다.
<:> 출력 : $code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>$tokens = token_get_all($code);
</span></span><span>
</span><span><span>foreach ($tokens as $token) {
</span></span><span> <span>if (is_array($token)) {
</span></span><span> <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL;
</span></span><span> <span>} else {
</span></span><span> <span>var_dump($token);
</span></span><span> <span>}
</span></span><span><span>}
</span></span>
로그인 후 복사
위의 출력에서 몇 가지 주목할만한 점이 있습니다. 첫 번째 요점은 소스 코드의 모든 부분이 토큰이라고 불리는 것은 아닙니다. 대신, 일부 기호는 그 자체의 토큰으로 간주됩니다 (예 : =,;, :,? 등). 두 번째 요점은 Lexer가 실제로 단순히 토큰 스트림을 출력하는 것 이상을 수행한다는 것입니다. 또한 대부분의 경우 Lexeme (토큰과 일치하는 값)과 일치하는 토큰의 줄 번호 (스택 트레이스와 같은 것들에 사용됨)를 저장합니다.
2 단계 - 구문 분석
파서도 BNF 문법 파일을 통해 들소와 함께 생성됩니다. PHP는 LALR (1) (왼쪽에서 오른쪽으로) 컨텍스트가없는 문법을 사용합니다. 미래의 부분은 단순히 파서가 n 토큰을 앞서 볼 수 있음을 의미합니다 (이 경우 1,이 경우). 왼쪽에서 오른쪽에서 라우팅 파트는 왼쪽에서 오른쪽으로 토큰 스트림을 구문 분석한다는 것을 의미합니다.
생성 된 파서 스테이지는 Lexer의 토큰 스트림을 입력으로 가져오고 두 개의 작업이 있습니다. 먼저 BNF 문법 파일에 정의 된 문법 규칙 중 하나와 일치시켜 토큰 주문의 유효성을 확인합니다. 이를 통해 유효한 언어 구성은 토큰 스트림의 토큰에 의해 형성되고 있습니다. 파서의 두 번째 작업은 Abstract 구문 트리 (AST)를 생성하는 것입니다. 다음 단계에서 사용될 소스 코드의 트리 뷰 (컴파일).
우리는 php-ast 확장을 사용하여 구문 분석기에 의해 생성 된 의 형태를 볼 수 있습니다. 내부 AST는 (일관성과 일반적인 유용성 측면에서) 작업하기에 특히 "깨끗한"것이 아니기 때문에 직접 노출되지 않으므로 PHP-AST 확장은 작업하기가 더 좋을 수 있도록 몇 가지 변환을 수행합니다.
기초적인 코드에 대한 AST를 살펴 보겠습니다.
출력 :
트리 노드 (일반적으로 유형 astnode)에는 몇 가지 속성이 있습니다.
종류 - 노드 유형을 나타내는 정수 값; 각각은 해당 상수를 가지고 있습니다 (예 : AST_STMT_LIST => 132, AST_ASSIGN => 517, AST_VAR => 256)
플래그 - 오버로드 된 동작을 지정하는 정수 (예 : ASSTAST_BINARY_OP 노드에는 어떤 바이너리 작업이 발생하는지 차별화 할 플래그가 있습니다)
.
lineno - 이전 토큰 정보에서 볼 수있는 줄 번호
Children - 하위 노드, 일반적으로 노드의 일부가 더 나빠질 수 있습니다 (예 : 함수 노드에는 매개 변수, 반환 유형, 본문 등) 가 있습니다.
이 단계의 AST 출력은 정적 코드 분석기 (예 : Phan)와 같은 도구를 위해 작동하는 데 편리합니다. 3 단계 - 컴파일
컴파일 스테이지는 AST를 소비하여 트리를 재귀 적으로 횡단하여 OPCODE를 방출합니다. 이 단계는 또한 몇 가지 최적화를 수행합니다. 여기에는 문자 그대로의 인수 (예 : strlen ( "ABC")에서 int (3)) 및 폴딩 상수 수학적 표현 (60 * 60 * 24 ~ int (86400))가있는 일부 기능 호출을 해결하는 것이 포함됩니다.
우리는 Opcache, VLD 및 PhPDBG를 포함하여 여러 가지 방법 으로이 단계에서 Opcode 출력을 검사 할 수 있습니다. 출력이 더 친숙하다고 생각하기 때문에 vld를 사용할 것입니다.
다음 파일에 대한 출력이 무엇인지 보자.
다음 명령 실행 :
우리의 출력은 다음과 같습니다
opcodes는 기본 작업을 따라갈 수있는 원래 소스 코드와 비슷합니다. (이 기사에서 Opcode의 세부 사항을 탐구하지는 않을 것입니다.이 기사 자체가 여러 기사를 가져갈 수 있기 때문입니다.) 위의 스크립트의 Opcode 레벨에서 최적화가 적용되지 않았습니다. 그러나 우리가 볼 수 있듯이 컴파일 단계. 일정한 조건 (php_version === '7.1.0-dev')을 true로 해결함으로써 일부를 만들었습니다.
opcache는 단순히 Opcodes를 캐싱하는 것 이상을 수행합니다 (따라서 Lexing, Parsing 및 Compilation States를 우회). 또한 다양한 수준의 최적화로 가득합니다. 최적화 레벨을 4 개의 패스로 올리겠습니다.
명령 :
출력 :
우리는 일정한 조건이 제거되었고 두 에코 지침이 단일 명령으로 압축되었음을 알 수 있습니다. 이것들은 스크립트의 opcodes를 통해 패스를 수행 할 때 Opcache가 적용되는 많은 최적화의 맛 일뿐입니다. 그래도이 기사에서 다양한 최적화 수준을 거치지 않을 것입니다. 그 자체로는 기사가되기 때문입니다.
.
4 단계 - 해석
마지막 단계는 opcodes의 해석입니다. 이곳은 Opcodes가 Zend Engine (ZE) VM에서 실행되는 곳입니다. 실제로이 단계에 대해 할 말이 거의 없습니다 (적어도 높은 수준의 관점에서). 출력은 Echo, Print, Var_dump 등과 같은 명령을 통해 PHP 스크립트 출력이 무엇이든간에.
따라서이 단계에서 복잡한 것을 파는 대신 재미있는 사실이 있습니다. PHP는 자체 VM을 생성 할 때 의존성으로 자체적으로 필요합니다. VM은 PHP 스크립트에 의해 생성되기 때문에 쓰기가 더 간단하고 유지 관리하기 쉽기 때문입니다.
결론
우리는 PHP 코드를 실행할 때 PHP 통역사가 겪는 4 단계를 살펴 보았습니다. 여기에는 각 단계의 출력을 조작하고보기 위해 다양한 확장 (토큰 화기, PHP-AST, Opcache 및 VLD 포함)을 사용하는 것이 포함되었습니다. 나는이 기사가 PHP의 통역사에 대한 더 나은 전체적인 이해를 제공하고 Opcache 확장의 중요성을 보여주기를 바랍니다 (캐싱 및 최적화 능력 모두).
PHP 실행 프로세스에 대한 자주 묻는 질문 (FAQ)
실행 프로세스에서 PHP 통역사의 역할은 무엇입니까?
PHP 통역사는 PHP 실행 프로세스에서 중요한 역할을합니다. PHP 소스 코드를 컴퓨터로 읽을 수있는 코드로 변환 할 책임이 있습니다. 통역사는 PHP 스크립트 라인을 라인별로 읽고 각 줄을 해석하며 필요한 작업을 수행합니다. 또한 실행 프로세스 중에 오류 및 예외를 처리 할 책임이 있습니다. PHP 인터프리터는 웹 서버와 PHP 확장 기능을 포함하는 PHP 런타임 환경의 핵심 구성 요소입니다. PHP 엔진은 어떻게 작동합니까?
PHP 엔진은 핵심입니다. PHP 실행 프로세스. PHP 스크립트를 구문 분석하고 바이트 코드로 컴파일 한 다음 바이트 코드를 실행할 책임이 있습니다. PHP 엔진은 2 단계 프로세스를 사용하여 PHP 스크립트를 실행합니다. 먼저 PHP 스크립트를 구문 분석하고 AST (Abstract Syntax Tree)로 변환합니다. 그런 다음 AST를 바이트 코드로 컴파일하여 실행합니다. PHP 엔진에는 실행 프로세스 중에 메모리 관리자와 쓰레기 수집가가 포함되어 있습니다. PHP의 명령 줄 인터페이스와 웹 서버 인터페이스의 차이점은 무엇입니까? PHP의 명령은 무엇입니까? -LINE 인터페이스 (CLI) 및 웹 서버 인터페이스는 PHP 스크립트를 실행하는 두 가지 방법입니다. CLI는 명령 줄에서 PHP 스크립트를 실행하는 데 사용되며 웹 서버 인터페이스는 웹 요청에 대한 응답으로 PHP 스크립트를 실행하는 데 사용됩니다. 두 인터페이스의 주요 차이점은 입력 및 출력을 처리하는 방법입니다. CLI에서는 입력이 명령 줄에서 읽히고 출력은 콘솔에 기록됩니다. 웹 서버 인터페이스에서는 HTTP 요청에서 입력을 읽고 출력이 HTTP 응답에 기록됩니다.
실행 프로세스 중에 PHP가 오류를 처리하는 방법은 무엇입니까?
PHP는 강력한 오류 처리가 있습니다. 실행 프로세스 중에 오류를 처리 할 수있는 메커니즘. 오류가 발생하면 PHP는 오류 메시지를 생성하여 오류 핸들러로 보냅니다. 오류 핸들러는 오류 메시지를 표시하거나 로그인하거나 오류보고 설정에 따라 무시하거나 무시할 수 있습니다. PHP는 또한 예외 처리를 지원하므로보다 체계적이고 관리 가능한 방식으로 오류를 처리 할 수 있습니다. 실행 프로세스에서 PHP 확장의 역할은 무엇입니까?
PHP 확장은 PHP 언어에 새로운 기능과 기능을 추가하는 모듈입니다. 실행 프로세스 중에 PHP 런타임 환경에로드되며 데이터베이스 액세스에서 이미지 처리에 이르기까지 광범위한 작업을 수행하는 데 사용할 수 있습니다. PHP 확장은 C로 작성되며 기계 코드로 편집되어 매우 빠르고 효율적입니다. PHP 생태계의 핵심 구성 요소이며 유연성과 힘에 기여합니다. PHP는 실행 프로세스를 어떻게 최적화 하는가?
PHP는 여러 기술을 사용하여 실행 프로세스를 최적화합니다. 이러한 기술 중 하나는 Opcode 캐싱으로, PHP 엔진에 의해 생성 된 바이트 코드를 메모리에 저장하여 후속 실행에서 재사용 할 수 있습니다. 이를 통해 PHP 스크립트가 실행될 때마다 PHP 스크립트를 구문 분석하고 컴파일 할 필요가 없으므로 성능이 크게 향상됩니다. PHP는 또한 정시 (JIT) 컴파일을 사용합니다. 여기에는 런타임시 바이트 코드를 기계 코드로 컴파일하기 위해 성능을 향상시키는 것이 포함됩니다.
실행 프로세스 중에 PHP가 메모리 관리를 어떻게 처리합니까?
PHP에는 실행 프로세스 중에 메모리 할당 및 거래를 처리하는 내장 메모리 관리자가 있습니다. 메모리 관리자는 필요에 따라 변수 및 데이터 구조에 대한 메모리를 할당하고 더 이상 필요하지 않은 경우 메모리를 처리합니다. PHP에는 또한 더 이상 사용되지 않는 메모리를 자동으로 해제하는 쓰레기 수집기가 있습니다. 이렇게하면 메모리 누출을 방지하고 메모리 사용을 제어하는 데 도움이됩니다.
PHP 실행 프로세스에서 웹 서버의 역할은 무엇입니까?
웹 서버는 PHP 실행에서 핵심 역할을합니다. 프로세스. HTTP 요청을 처리하고 이러한 요청에 대한 응답으로 PHP 스크립트를 실행하며 HTTP 응답을 클라이언트에 다시 보냅니다. 웹 서버는 PHP 인터프리터 및 PHP 엔진과 긴밀히 협력하여 PHP 스크립트를 실행하고 동적 웹 페이지를 생성합니다. PHP에 가장 일반적으로 사용되는 웹 서버는 apache 및 nginx입니다. 실행 프로세스 중에 PHP 데이터베이스 상호 작용은 어떻게 처리됩니까?
PHP MySQL, PostgreSQL 및 Sqlite. 데이터베이스 별 확장 기능을 사용하여 실행 프로세스 중에 이러한 데이터베이스와 상호 작용합니다. 이러한 확장은 데이터베이스에 연결하고 SQL 쿼리를 실행하고 결과를 가져오고 오류를 처리하는 데 사용할 수있는 일련의 함수를 제공합니다. PHP는 또한 데이터베이스 상호 작용에 대한 데이터베이스 공수 인터페이스를 제공하는 PDO (PHP Data Objects) 확장 기능을 지원합니다. 실행 프로세스 중에 PHP가 세션 관리를 처리하는 방법은 무엇입니까?
PHP는 세션 관리에 대한 내장 지원을 제공하므로 다른 HTTP 요청간에 상태를 유지할 수 있습니다. 세션이 시작되면 PHP는 고유 한 세션 ID를 생성하여 클라이언트 브라우저에 쿠키에 저장합니다. 그런 다음이 세션 ID는 각 후속 요청으로 서버로 다시 전송되어 PHP가 클라이언트를 식별하고 해당 세션 데이터를 검색 할 수 있습니다. PHP의 세션 관리 기능은 웹 애플리케이션에서 사용자 인증, 쇼핑 카트 및 기타 상태의 기능을 쉽게 구현할 수 있습니다.
위 내용은 소스 코드에서 렌더링까지 PHP 실행 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!