search
HomeBackend DevelopmentPHP ProblemHow to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article

PHP is said to be simple, but it is not easy to master it. In addition to being able to use it, we also need to know its underlying working principle.

PHP is a dynamic language suitable for web development. To be more specific, it is a software framework that uses C language to implement a large number of components. Looking at it in a more narrow sense, it can be considered as a powerful UI framework.

What is the purpose of understanding the underlying implementation of PHP? If you want to use dynamic language well, you must first understand it. Memory management and framework models are worthy of our reference. Through extended development, we can achieve more powerful functions and optimize the performance of our programs.

1. The design concept and characteristics of PHP

Multi-process model: Since PHP is a multi-process model, different requests do not interfere with each other, which ensures that one request will hang The loss will not affect the overall service. Of course, with the development of the times, PHP has already supported the multi-threading model. Weakly typed language: Unlike C/C, Java, C# and other languages, PHP is a weakly typed language. The type of a variable is not determined at the beginning. It is determined during operation and implicit or explicit type conversion may occur. The flexibility of this mechanism is very convenient and efficient in web development. The details will be discussed in PHP later. Variables are detailed in. The engine (Zend) component (ext) pattern reduces internal coupling. The middle layer (sapi) isolates the web server and PHP. The syntax is simple and flexible, without too many specifications. Shortcomings lead to mixed styles, but no matter how bad a programmer is, he will not write a program that is too outrageous and endangers the overall situation.

2. PHP’s four-layer system

The core architecture of PHP is as shown below:

How to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article

From the picture It can be seen that PHP is a 4-layer system from bottom to top:

Zend engine: Zend is implemented entirely in pure C and is the core part of PHP. It translates PHP code (lexical, syntax analysis, etc.) The compilation process) processes executable opcodes and implements corresponding processing methods, implements basic data structures (such as hashtable, oo), memory allocation and management, and provides corresponding api methods for external calls. It is the core of everything. The peripheral functions are all implemented around Zend. Extensions: Around the Zend engine, extensions provide various basic services in a component-based manner. Our common various built-in functions (such as array series), standard libraries, etc. are all implemented through extensions. Users can also implement their own as needed. extension to achieve function expansion, performance optimization and other purposes (for example, the PHP middle layer and rich text parsing currently used by Tieba are typical applications of extension). Sapi: The full name of Sapi is Server Application Programming Interface, which is the server application programming interface. Sapi enables PHP to interact with peripheral data through a series of hook functions. This is a very elegant and successful design of PHP. Through sapi, PHP can be successfully integrated into Since it is decoupled and isolated from upper-layer applications, PHP can no longer consider how to be compatible with different applications, and the application itself can also implement different processing methods based on its own characteristics. Upper-layer application: This is the PHP program we usually write. We obtain various application modes through different sapi methods, such as implementing web applications through webserver, running them in script mode on the command line, etc.

If PHP is a car, then the frame of the car is PHP itself, Zend is the engine (engine) of the car, and the various components under Ext are the wheels of the car. Sapi can be regarded as a road, and the car can Running on different types of roads, and the execution of a PHP program is the car running on the road. So we need: a good engine, the right wheels, the right track.

3. Sapi

As mentioned above, Sapi allows external applications to exchange data with PHP through a series of interfaces and can implement specific functions according to the characteristics of different applications. Some of our common sapi processing methods are:

apache2handler: This is the processing method when using apache as the webserver and running in mod_PHP mode. It is also the most widely used one now. cgi: This is another direct interaction method between webserver and PHP, which is the famous fastcgi protocol. In recent years, fastcgi PHP has been used more and more, and it is also the only method supported by asynchronous webserver. cli: Application mode for command line calls

4. PHP execution process&opcode

Let’s first take a look at the process of executing PHP code.

How to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article

As you can see from the picture, PHP implements a typical dynamic language execution process: after getting a piece of code, after going through stages such as lexical analysis and syntax analysis, the source program will be Translated into instructions (opcodes), the ZEND virtual machine executes these instructions in sequence to complete the operation. PHP itself is implemented in C, so the functions ultimately called are all C functions. In fact, we can regard PHP as a software developed in C.

The core of PHP execution is the translated instructions, that is, opcode.

Opcode is the most basic unit of PHP program execution. An opcode consists of two parameters (op1, op2), return value and processing function. The PHP program is ultimately translated into the sequential execution of a set of opcode processing functions.

Several common processing functions:

PHP

ZEND_ASSIGN_SPEC_CV_CV_HANDLER: Variable allocation ($a=$b)

ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:Function call

ZEND_CONCAT_SPEC_CV_CV_HANDLER:String concatenation $a.$b

ZEND_ADD_SPEC_CV_CONST_HANDLER: Addition operation $a 2

ZEND_IS_EQUAL_SPEC_CV_CONST: Judgment of equality $a==1

ZEND_IS_IDENTICAL_SPEC_CV_CONST: Judgment of equality $a===1

5. HashTable - core data structure

HashTable is the core data structure of zend. It is used to implement almost all common functions in PHP. The PHP array we know is its Typical applications, in addition, within zend, such as function symbol table, global variables, etc. are also implemented based on hash table.

PHP’s hash table has the following characteristics:

1. Supports typical key->value query

2. Can be used as an array

3 , adding and deleting nodes is O(1) complexity

4. Key supports mixed types: there are both associative arrays and index arrays

5. Value supports mixed types: array ("string" ,2332)

6. Support linear traversal: for example, foreach

Zend hash table implements a typical hash table hash structure, and at the same time provides forward and reverse by attaching a doubly linked list Function to traverse an array. Its structure is as shown below:

How to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article

It can be seen that in the hash table, there are both hash structures in the form of key->value and doubly linked list mode, so that It can very conveniently support fast search and linear traversal.

Hash structure: Zend's hash structure is a typical hash table model, which resolves conflicts through a linked list. It should be noted that zend's hash table is a self-growing data structure. When the hash table is full, it will dynamically expand by 2 times and reposition elements. The initial size is 8. In addition, when performing key->value fast search, zend itself has also made some optimizations to speed up the process by exchanging space for time. For example, a variable nKeyLength is used in each element to identify the length of the key for quick determination.

Doubly linked list: Zend hash table implements linear traversal of elements through a linked list structure. In theory, it is enough to use a one-way linked list for traversal. The main purpose of using a two-way linked list is to quickly delete and avoid traversal. Zend hash table is a composite structure. When used as an array, it supports common associative arrays and can also be used as sequential index numbers, and even allows a mixture of the two.

PHP associative array: Associative array is a typical hash_table application. A query process goes through the following steps (as can be seen from the code, this is a common hash query process and some quick judgments are added to speed up the search.):

PHP

getKeyHashValue h;
index = n & nTableMask;
Bucket *p = arBucket[index];
while (p) {
if ((p->h == h) & (p->nKeyLength == nKeyLength)) {
RETURN p->data;  
}
p=p->next;
}
RETURN FALTURE;

PHP index array:

The index array is our common array, accessed through subscripts. For example, $arr[0], Zend HashTable is internally normalized, and the hash value and nKeyLength (0) are also assigned to the index type key. The internal member variable nNextFreeElement is the currently assigned maximum id, which is automatically increased by one after each push. It is this normalization process that allows PHP to achieve a mixture of associative and non-associative data. Due to the particularity of the push operation, the order of the index keys in the PHP array is not determined by the size of the subscript, but by the order of the push. For example, $arr[1] = 2; $arr[2] = 3; for double type keys, Zend HashTable will treat them as index keys

6. PHP variables

PHP is a weakly typed language and does not strictly distinguish the types of variables. PHP does not need to specify the type when declaring variables. PHP may perform implicit conversions of variable types during program execution. Like other strongly typed languages, explicit type conversion can also be performed in the program. PHP variables can be divided into simple types (int, string, bool), collection types (array resource object) and constants (const). All the above variables have the same structure zval under the hood.

Zval is another very important data structure in zend, used to identify and implement PHP variables. Its data structure is as follows:

How to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article

Zval is mainly composed of three Part composition:

type: specifies the type of variable (integer, string, array, etc.)

refcount&is_ref: used to implement reference counting (detailed introduction later)

value: The core part, which stores the actual data of the variable

Zvalue is used to save the actual data of a variable. Because multiple types need to be stored, zvalue is a union, thus implementing weak typing.

The corresponding relationship between PHP variable types and their actual storage is as follows:

1, IS_LONG -> lvalue

2, IS_DOUBLE -&gt ; dvalue

3、IS_ARRAY -> ht

4、IS_STRING -> str

5 , IS_RESOURCE -> lvalue

Reference counting is widely used in memory recycling, string operations, etc. Variables in PHP are a typical application of reference counting. Zval's reference counting is implemented through the member variables is_ref and ref_count. Through reference counting, multiple variables can share the same data. Avoid the huge consumption caused by frequent copying.

When performing an assignment operation, zend points the variable to the same zval and ref_count. During the unset operation, the corresponding ref_count-1. The destruction operation will only be performed when ref_count is reduced to 0. If it is a reference assignment, zend will modify is_ref to 1.

PHP variables realize variable sharing data through reference counting. What if you change the value of one of the variables? When trying to write a variable, if Zend finds that the zval pointed to by the variable is shared by multiple variables, it will copy a zval with a ref_count of 1 and decrement the refcount of the original zval. This process is called "zval separation". It can be seen that zend only performs copy operations when a write operation occurs, so it is also called copy-on-write (copy on write)

For reference variables, the requirements are opposite to non-reference types. Reference assignment Variables must be bundled. Modifying one variable modifies all bundled variables.

Integers and floating-point numbers are one of the basic types in PHP and are also simple variables. For integers and floating point numbers, the corresponding values ​​are stored directly in zvalue. Their types are long and double respectively.

It can be seen from the zvalue structure that for integer types, unlike strongly typed languages ​​such as c, PHP does not distinguish between int, unsigned int, long, long long and other types. For it, integers only One type is long. From this, it can be seen that in PHP, the value range of integers is determined by the number of compiler bits and is not fixed.

For floating point numbers, similar to integers, it does not distinguish between float and double but only double.

In PHP, what should I do if the integer range is out of bounds? In this case, it will be automatically converted to double type. You must be careful about this, as many tricks are caused by this.

Like integers, character variables are also basic types and simple variables in PHP. As can be seen from the zvalue structure, in PHP, a string is composed of a pointer to the actual data and a length structure, which is similar to the string in C. Since the length is represented by an actual variable, unlike c, its string can be binary data (inclusive). At the same time, in PHP, finding the string length strlen is an O(1) operation.

When adding, modifying, or appending string operations, PHP will reallocate memory to generate new strings. Finally, for security reasons, PHP will still add

at the end when generating a string. Common string splicing methods and speed comparison:

Assume there are the following 4 variables: $strA= '123'; $strB = '456'; $intA=123; intB=456;

Now we will compare and explain the following string splicing methods:

PHP

$res = $strA.$strB and $res = “$strA$strB”

In this case, zend will re-malloc a piece of memory and process it accordingly , its speed is generally

$strA = $strA.$strB

This is the fastest, zend will directly relloc based on the current strA to avoid repeated copying

$res = $intA.$intB

This is slower because implicit format conversion is required. In actual programming, you should also pay attention to avoid

$strA = sprintf ( "%s%s",$strA.$strB);

This will be the slowest way, because sprintf is not a language structure in PHP. It takes a lot of time to identify and process the format. In addition, the mechanism itself is malloc. However, the sprintf method is the most readable, and in practice it can be chosen flexibly according to specific circumstances.

PHP arrays are naturally implemented through Zend HashTable.

How to implement foreach operation? Foreach on an array is completed by traversing the doubly linked list in the hashtable. For index arrays, traversal through foreach is much more efficient than for, eliminating the need to search for key->value. The count operation directly calls HashTable->NumOfElements, O(1) operation. For a string like '123', zend will convert it to its integer form. $arr[‘123’] and $arr[123] are equivalent

The resource type variable is the most complex variable in PHP and is also a composite structure.

PHP's zval can represent a wide range of data types, but it is difficult to fully describe custom data types. Since there is no efficient way to represent these composite structures, there is no way to use traditional operators on them. To solve this problem, you only need to refer to the pointer through an essentially arbitrary identifier (label), which is called a resource.

In zval, for resource, lval is used as a pointer, directly pointing to the address of the resource. Resource can be any composite structure. The familiar mysqli, fsock, memcached, etc. are all resources.

How to use resources:

Registration: For a custom data type, you want to use it as a resource. First, you need to register it, and zend will assign it a globally unique identifier. Get a resource variable: For resources, zend maintains an id->hash_tale of actual data. For a resource, only its id is recorded in zval. When fetching, find the specific value in the hash_table through the id and return it. Resource destruction: The data types of resources are diverse. Zend itself has no way to destroy it. Therefore, users need to provide a destruction function when registering resources. When unset resources, zend calls the corresponding function to complete the destruction. Also delete it from the global resource table.

Resources can persist for a long time, not only after all variables referencing it go out of scope, but even after a request ends and a new request is generated. These resources are called persistent resources because they persist throughout the life cycle of the SAPI unless specifically destroyed. In many cases, persistent resources can improve performance to a certain extent. For example, in our common mysql_pconnect, persistent resources allocate memory through pemalloc so that they will not be released when the request ends.
For zend, there is no distinction between the two.

How are local variables and global variables implemented in PHP? For a request, PHP can see two symbol tables (symbol_table and active_symbol_table) at any time, with the former used to maintain global variables. The latter is a pointer pointing to the currently active variable symbol table. When the program enters a function, zend will allocate a symbol table x to it and point active_symbol_table to a. In this way, the distinction between global and local variables is achieved.

Get variable values: PHP's symbol table is implemented through hash_table. Each variable is assigned a unique identifier. When obtaining, the corresponding zval is found from the table according to the identifier and returned.

Using global variables in functions: In functions, we can use global variables by explicitly declaring global. Create a reference to the variable with the same name in symbol_table in active_symbol_table. If there is no variable with the same name in symbol_table, it will be created first.

For more related questions, please visit the PHP Chinese website: PHP practical video tutorial

The above is the detailed content of How to understand the underlying operating mechanism and principles of PHP? It is enough to understand this article. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:博客园. If there is any infringement, please contact admin@php.cn delete
PHP核心的运行机制与实现原理详解PHP核心的运行机制与实现原理详解Nov 08, 2023 pm 01:15 PM

PHP是一种流行的开源服务器端脚本语言,大量被用于Web开发。它能够处理动态数据以及控制HTML的输出,但是,如何实现这一切?那么,本文将会介绍PHP的核心运行机制和实现原理,并利用具体的代码示例,进一步说明其运行过程。PHP源码解读PHP源码是一个由C语言编写的程序,经过编译后生成可执行文件php.exe,而对于Web开发中使用的PHP,在执行时一般通过A

深度解析:Go语言中goroutine的本质和运行机制深度解析:Go语言中goroutine的本质和运行机制Mar 12, 2024 pm 03:39 PM

在Go语言中,goroutine是一种轻量级的线程,用于并发执行代码片段。与传统的线程相比,goroutine更加高效,具有更低的内存消耗和更快的启动速度。在本文中,我们将深度解析Go语言中goroutine的本质和运行机制,同时会提供具体的代码示例来帮助读者更好地理解。1.Goroutine的本质在Go语言中,goroutine是由Go运行时管理的轻量级

探究Swoole中协程的运行机制探究Swoole中协程的运行机制Jun 13, 2023 am 10:27 AM

Swoole是一个基于PHP的协程框架,它的异步IO性能非常出色。Swoole的核心是协程,协程是一种比线程更轻量级的并发机制,可以在同一线程中切换任务来实现并发执行。本文将会探究Swoole中协程的运行机制。一、协程的概念协程,又称微线程,是一种比线程更细粒度的并发机制。协程与线程的区别在于,协程通过时间片轮转来实现任务切换,而线程由操作系统调度器负责切换

解析ApacheTomcat的工作原理与运行机制解析ApacheTomcat的工作原理与运行机制Jan 24, 2024 am 10:14 AM

ApacheTomcat是一个开源的JavaServlet容器,由Apache软件基金会开发和维护。它是最流行的用于Java应用程序开发的Servlet容器之一,广泛用于企业级Web应用程序的部署。本文将详细解析ApacheTomcat的原理及运行机制,并提供具体的代码示例。Tomcat的架构ApacheTomcat采用了基于组件的架构,由多个模块组

深入解析Tomcat中间件的运行机制和内部工作原理深入解析Tomcat中间件的运行机制和内部工作原理Dec 28, 2023 pm 01:20 PM

解密Tomcat中间件的运行机制和内部工作原理摘要:Tomcat是一个广泛用于JavaWeb应用程序的开源HTTP服务器和Servlet容器。它提供了丰富的功能,如处理HTTP请求、管理Web应用程序和Servlet生命周期管理等。本文将深入探讨Tomcat中间件的运行机制和内部工作原理,包括掌握Tomcat的核心组件、请求处理流程、类加载机制、Servl

Linux内核功能详解:五大部分的全面解读Linux内核功能详解:五大部分的全面解读Mar 21, 2024 am 08:18 AM

Linux内核功能详解:五大部分的全面解读Linux内核是一个开源的操作系统内核,负责管理计算机的硬件资源,并提供进程管理、文件系统和设备驱动等功能。Linux内核由许多不同的部分组成,每个部分拥有特定的功能和责任。本文将对Linux内核的五大部分进行全面解读,并提供具体的代码示例帮助读者更好地理解。1.进程管理进程管理是Linux内核的核心功能之一,负责

了解Zend Framework中间件的运行机制和原理了解Zend Framework中间件的运行机制和原理Jul 28, 2023 pm 01:49 PM

了解ZendFramework中间件的运行机制和原理随着互联网的不断发展,web应用程序的复杂性也在不断增加。为了解决这些问题,中间件的概念应运而生。中间件是一个非常重要的技术,在ZendFramework中也得到了广泛的应用。本文将介绍ZendFramework中间件的运行机制和原理,并通过示例代码来详细说明。首先,什么是中间件?中间件是一种可以对请

如何通过编写代码来深入理解 PHP8 的运行机制如何通过编写代码来深入理解 PHP8 的运行机制Sep 12, 2023 pm 02:25 PM

如何通过编写代码来深入理解PHP8的运行机制引言:PHP8是PHP编程语言的下一个主要版本,带来了许多新的功能和改进。要充分发挥PHP8的优势,程序员需要对其运行机制有深入的理解。编写代码的过程可以帮助我们更好地了解PHP8的内部工作原理。本文将介绍一些可以帮助我们深入理解PHP8运行机制的编码技巧。一、了解PHP8的新特性在编写代码之前,首先需要了解P

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools